agentleFS
Autocss-comAutocss-com/ai/.agents/skills/spa/SKILL.md

spa

Skill1 starsChanged 2 months agoMITView on GitHub

Single-Page-Application rules for projects following the air-gapped, browser-native architecture. Defines the one entry document, radio-driven navigation read by CSS `:has()`, the fetch-once shell, the `oninput` data lifecycle per view change, and same-document content transitions. Use whenever wiring navigation, routing, view switching, deep-linking, or page-to-page behavior. Pairs with the `pwa` skill.

2 other projects use a version of this.

Adopted by

Most recently taken up by

  • Other versions2 projects use a version of this.

    Word for word · 0

    None found.

    Edited · 0

    None found.

    Wrote their own version · 2

    1. aigengame/aseprite-automation★ 25same name
    2. ffsshhttiikk/opencode-agents-skills★ 2same name

    How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.

  • In this repository14 other files it gives its agents.

The file

We split this skill into the rules it gives an agent

6 rules. About 0 are common, 2 are distinctive, and 4 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈2

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 4

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Never a client-side router library (no hash router, no History-API view routing)

    line 57
  2. Distinctive:

    Never a second HTML page or a JS template/rendering engine for views

    line 58
  3. Very specific:

    Never <a href> for in-app view changes (anchors are for real cross-document links only)

    line 59
  4. Very specific:

    Never a user-event handler for data fetching — the oninput lifecycle owns all CRUD

    line 60
  5. Very specific:

    Never @view-transition (cross-document only.

    line 61
  6. Very specific:

    Never store view state in JS variables — :checked in the DOM is the state

    line 62

≈ “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.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

SPA

One document. The browser is the router. Navigation is DOM state (:checked), read by CSS. JavaScript moves data, never drives the view. This is the twin of the pwa skill: SPA defines the in-page model, PWA defines the deployment posture.

One entry document

A single index.html at project root holds the entire DOM up front (see the html skill's shell). There is no second HTML page, no client-side template engine, no innerHTML view rendering. Views are regions of the one document that show or hide based on data presence and :checked state.

Navigation is a radio state machine

Global navigation is mutually-exclusive radio inputs inside labels, inside <nav> — never <a href> page loads, never a JS router, never the History API for view switching:

<nav>
  <label><input type="radio" name="nav" aria-hidden="true" /></label>
  <label><input type="radio" name="nav" aria-hidden="true" /></label>
</nav>

CSS reads the checked radio with :has() and reveals the matching view. The name="nav" group gives single-selection for free (the browser enforces exclusivity). The full input-hiding + accessibility details live in the css skill's state-machines reference; the visual reaction lives in css layout/state.

No checked attribute is set in the HTML. The startup script restores the persisted selection (or the first radio) and dispatches an input event — see below.

The shell is fetched once

Chrome-of-the-app content — header, nav, footer, meta — is fetched and injected a single time per runtime session, not on every view change. Only the per-view data is re-fetched when the nav selection changes. The javascript skill owns the transport; this skill owns the rule: shell once, view data per selection.

Every view change enters the same oninput lifecycle

A view change is an input event on the selected nav radio. That is the only trigger for a data fetch. The lifecycle:

  1. A nav radio becomes :checked (user click, or programmatic restore on load).
  2. Its own oninput fires the shared lifecycle in oninput.js.
  3. The lifecycle maps the radio's index to an endpoint suffix and fetches that view's JSON.
  4. JSON is injected into the reused DOM targets; CSS reveals them via :not(:empty) / :has().

:checked is the single source of truth for both the CSS view state and the data call. Full lifecycle rules are in the javascript skill — this skill only fixes that navigation and data are one event, never two.

Initial load and return visits

No nav radio is checked in the HTML. On load, the startup script reads the persisted selection from storage (or falls back to the first nav radio), sets input.checked = true, then dispatches input.dispatchEvent(new Event('input', { bubbles: true })) so the input's own oninput runs the lifecycle. This dispatchEvent is the single sanctioned programmatic selection — .click() / onclick are forbidden. Return visits restore the persisted radio the same way, which is how the SPA "deep-links" to a view without a URL router.

Same-document view transitions

Switching views is a same-document change, so it fades via the universal * transition plus transition-behavior: allow-discrete (see the css skill's transitions reference). @view-transition is not used — it fires only on cross-document navigations and is inert in this single-document app. If the project ever becomes multi-document, revisit that decision then.

What the SPA never does

  • Never a client-side router library (no hash router, no History-API view routing)
  • Never a second HTML page or a JS template/rendering engine for views
  • Never <a href> for in-app view changes (anchors are for real cross-document links only)
  • Never a user-event handler for data fetching — the oninput lifecycle owns all CRUD
  • Never @view-transition (cross-document only; does nothing here)
  • Never store view state in JS variables — :checked in the DOM is the state

Boundaries with other skills

PieceOwned by
The one index.html shell + regionshtml
Nav state machine markup + input hidinghtml + css (state-machines)
View reveal, layout, view transitionscss (layout, transitions)
oninput lifecycle, fetch, storage, startup dispatchjavascript
View JSON shapejson
Offline shell caching + installpwa

Baseline & support

Checked against MDN as of 2026-07-16.

Canonical rules: https://github.com/Autocss-com/ai/blob/main/AGENTS.md

Reference

Download now (ZIP)

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
What did you use it for? e.g. Reviewing pull requests in a Rails app

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.