axum-single-page-ui
Skill1 starsChanged 9 months agoMITView on GitHub
Build and serve a single-page web UI from an Axum service, including plain-JS mode and optional TypeScript build/fallback patterns.
In this repository13 other files it gives its agents.
- feishuSkill
- frontend-designSkill
- git-opsSkill
- gui-automationSkill
- macos-gui-automationSkill
- mermaidSkill
- npmSkill
- playrightSkill
- playwright-cliSkill
- pythonSkill
- python-uvSkill
- rust-coding-styleSkill
- youtrackSkill
The file
Show its rules and text
We split this skill into the rules it gives an agent
21 rules. About 0 are common, 13 are distinctive, and 8 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈13
Distinctive · estimate
This author's own choices. Worth a look.
8
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 10
Use this skill when the user wants a single-page UI served by axum from the same Rust service as API routes.
- Distinctive: line 21
Prefer plain JS + single HTML for fastest, lowest-risk delivery.
- Distinctive: line 22
Keep API unchanged; only adjust UI asset serving and frontend script.
- Distinctive: line 23
Use TypeScript only when user explicitly asks for it.
- Very specific: line 33
Keep frontend as single page (one index.html) with client-side rendering.
- Distinctive: line 39
Use when speed and operability matter more than tooling.
- Distinctive: line 50
No TS type checking
- Distinctive: line 55
Use when frontend complexity grows.
- Distinctive: line 70
Use only when explicitly requested.
- Distinctive: line 76
Never enable fallback silently in production
- Distinctive: line 78
Add visible UI banner when fallback mode is active
- Distinctive: line 82
Keep API and UI concerns separate:
- Very specific: line 85
Do not let SPA fallback intercept /api/*
- Very specific: line 86
Keep /health independent and always fast
- Distinctive: line 90
When table/count mismatch appears (e.g., count shows rows but table is empty):
- Distinctive: line 92
Verify API payload shape matches renderer field names.
- Distinctive: line 95
Check runtime JS errors in browser console before patching backend.
- Very specific: line 96
Prefer robust field fallback mapping in UI (currency || symbol, etc.).
- Very specific: line 111
Keep <tbody> children as actual <tr> nodes only.
- Very specific: line 139
When a package has deployment.yaml, deploy with:
- Very specific: line 147
Check one /api/... endpoint and / page rendering
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Axum Single Page UI
Use this skill when the user wants a single-page UI served by axum from the same Rust service as API routes.
When to use
- Axum backend needs to serve one UI page at
/ - UI and API are in one service (
/api/*+ browser UI) - User wants plain JavaScript first, with optional TypeScript path later
- User asks for runtime/browser transpile trade-offs or fallback design
Defaults
- Prefer plain JS + single HTML for fastest, lowest-risk delivery.
- Keep API unchanged; only adjust UI asset serving and frontend script.
- Use TypeScript only when user explicitly asks for it.
- For production reliability, prefer build-time compilation over runtime transpilation.
Canonical architecture
axumroutes:GET /healthGET /api/...for JSON APIsGET /for SPA shell
- Serve static frontend assets with
tower-http(ServeDir/ServeFile) or embed viainclude_str!/include_bytes!. - Keep frontend as single page (one
index.html) with client-side rendering.
Implementation patterns
Pattern A: Plain JS single-file page (default)
Use when speed and operability matter more than tooling.
- One HTML page with inline
<script type="module"> - Optional CDN dependencies (e.g., SolidJS, Tailwind)
- Axum returns the page directly or as embedded static asset
Pros:
- Zero frontend toolchain
- Easiest deploy/debug
Cons:
- No TS type checking
- Harder to scale frontend complexity
Pattern B: TS build + Axum static serving
Use when frontend complexity grows.
- Author UI in
tsx/ts - Build to static assets (
index.html,app.js,app.css) - Axum serves built assets
Pros:
- Type safety and better maintainability
- Better performance/caching
Cons:
- Adds build pipeline
Pattern C: Build-first + runtime transpile fallback (opt-in)
Use only when explicitly requested.
- Primary: prebuilt bundle from build/deploy
- Fallback: runtime/browser transpile path (feature-flagged)
Rules:
- Never enable fallback silently in production
- Gate fallback with explicit env flag (e.g.,
UI_TRANSPILE_FALLBACK=1) - Add visible UI banner when fallback mode is active
Route structure guidance
- Keep API and UI concerns separate:
Router::new().nest("/api", api_router)- UI fallback for
/and frontend routes
- Do not let SPA fallback intercept
/api/* - Keep
/healthindependent and always fast
Frontend data contract guidance
When table/count mismatch appears (e.g., count shows rows but table is empty):
- Verify API payload shape matches renderer field names.
- Confirm rendering loops receive arrays (
Array.isArray(payload)). - Validate filter/query param names on both sides.
- Check runtime JS errors in browser console before patching backend.
- Prefer robust field fallback mapping in UI (
currency || symbol, etc.).
Known repeated issue: counter updates but table looks empty
Symptom:
- Header/count shows rows (for example
Top Pairs: 200), but<tbody>appears empty.
Likely root cause in Solid template mode:
- Using control-flow components directly inside table sections (
<tbody><Show>...<For>...</For></Show></tbody>) can produce invalid table child nodes in some runtime/parser paths.
Reliable fix:
- Keep
<tbody>children as actual<tr>nodes only. - Replace table-local
<Show>/<For>wrappers with a single function expression in<tbody>. - Return either:
- one fallback
<tr>for empty state, or rows.map(...)of<tr>templates for data rows.
- one fallback
Reference rendering pattern:
<tbody>
${() => {
const rows = pairs();
if (rows.length === 0) {
return html`<tr><td colspan="6">No pair matched the current filters.</td></tr>`;
}
return rows.map((row) => html`<tr>...</tr>`);
}}
</tbody>Verification checklist:
- API returns non-empty array (
/api/v1/pairs/select?...). - Served HTML contains the
const rows = pairs();table-body renderer. - Browser console has no runtime render errors.
Deployment guidance
When a package has deployment.yaml, deploy with:
infra deploy --package <app>
After deploy:
- Check rollout status
- Check
/health - Check one
/api/...endpoint and/page rendering
Output checklist for Codex
For implementation tasks, return:
- Files changed and why
- Commands run for verify/deploy
- API/UI smoke-check results
- Any fallback flags or operational caveats
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

