data-flow
Skill1 starsChanged 2 months agoMITView on GitHub
The JSON-to-custom-element rendering pipeline used for data tables and list-rendered content. Defines toTagName key conversion, the lifecycle from fetch to DOM, and the strict scope (data tables only — other features have their own patterns). Use when rendering tabular or list data from JSON, never for layout, never for static content.
1 other project uses a version of this.
Adopted by
Most recently taken up by
- sankalpaacharya/skillstheir own version, first seen Nov 8, 2026
Other versions1 project uses a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 1
- sankalpaacharya/skills★ 1same 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.
- AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- architectureSkill
- cssSkill
- htmlSkill
- javascriptSkill
- jsonSkill
- namingSkill
- principlesSkill
- pwaSkill
- securitySkill
- sessionSkill
- spaSkill
- testingSkill
The file
We split this skill into the rules it gives an agent
6 rules. About 0 are common, 4 are distinctive, and 2 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈4
Distinctive · estimate
This author's own choices. Worth a look.
2
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 28
If a feature has its own pattern in its own skill, that pattern wins.
- Very specific: line 126
Never injects HTML strings (innerHTML = '...')
- Very specific: line 127
Never reads class, id, or data-* (those don't exist)
- Distinctive: line 128
Never writes inline styles
- Distinctive: line 129
Never sets visibility via JS (CSS does that)
- Distinctive: line 130
Never re-renders the shell (shell fetched once per session)
≈ “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
Data Flow
The pipeline that turns a JSON object into a populated set of DOM elements. Used for data tables and list-rendered content only. Other features have their own patterns and do not use this pipeline.
Scope
This pipeline applies to:
- Data tables rendered as
<ul>/<li>rows - Form fieldsets populated from an API response
- Any structurally repeating content driven by an API
This pipeline does not apply to:
- Static layout regions (HTML provides them, CSS styles them)
- Theme tokens (CSS owns)
- Navigation behavior (CSS state machines own)
- Any feature with its own pattern documented in its own skill
If a feature has its own pattern in its own skill, that pattern wins.
Why <ul> / <li> for data tables, not <table>
Data tables are a primary surface in this architecture — government work especially, where users interact with tabular data daily and have strong preferences about how they see it. The choice of <ul> / <li> over <table> is deliberate and produces several wins at once.
Accessibility for keyboard and screen readers. <ul> / <li> markup is intrinsically navigable by keyboard and read clearly by screen readers without needing role overrides, ARIA scaffolding, or accessibility plugins. <table> markup, by contrast, often loses screen-reader accessibility once styling, sticky headers, virtualization, or interactive cells are added — recovering it requires layered ARIA and JS.
Semantically meaningful parent/child relationships. A list of rows is, semantically, a list. The data is a collection of items; each item is a record. <ul> / <li> says exactly that. <table> implies a two-dimensional layout — rows × columns as a presentational grid — which couples the data shape to a single rendering. Using a list keeps the data's nature separate from how it's currently displayed.
Multiple view modes from the same markup. Because the markup is a list of items, CSS can render it in different shapes without changing the DOM:
- List view — one row per visible line, columns aligned via subgrid
- Card view — each
<li>displayed as a card, columns laid out per-card - Other views as needed (gallery, compact, dense, expanded)
The user picks the view; CSS reacts. No DOM rebuild, no JS template swap. <table> markup cannot do this without restructuring the DOM.
End-user customization is a first-class design priority. Users have spent careers looking at their data. They have preferences. They earn the right to see it the way they want. The architecture treats this as a feature, not an edge case — which means the markup needs to support it intrinsically. <ul> / <li> does. <table> does not.
CSS subgrid for column alignment. Now cross-browser baseline, subgrid lets each <li> inherit its parent <ul>'s column tracks so values align across rows the way table columns do — without using <table>. The list keeps its semantic and accessibility advantages; the columns line up exactly. (Pattern in references/lifecycle.md; full-column subgrid example to be added once the surface is researched and validated.)
Future zen-mode (full-screen) view. A planned, consistent feature across the architecture: any section the user is working in can be expanded to full-screen — not as a modal overlay but as a true zen view of that section. <ul> / <li> data tables are amenable to this without restructuring; they expand and reflow naturally inside the new viewport. (When implemented, lives under css/references/.)
The pipeline
1. fetch JSON (api.js)
2. parse to object (api.js)
3. for each row: (oninput.js)
a. for each key in row:
- tag = toTagName(key)
- element = document.createElement(tag)
- element.textContent = row[key]
- row container appends element
4. row container appends to <ul>
5. CSS reacts via :empty / :has() / :not(:empty)Step 3 is the only DOM mutation. It is idempotent: the row container is cleared via clearFieldset before re-render.
toTagName(key) — the key-to-tag rule
A JSON key becomes a custom element tag name via toTagName(). The function:
- Splits the key on camelCase boundaries (
productName→product,Name). - Lowercases each part.
- Joins with hyphens (
product-name). - Prepends a namespace if none exists, to satisfy the custom-element hyphen requirement (
row-product-nameif the key is a single word). - Returns the tag name.
Examples:
| JSON key | Tag |
productName | <product-name> |
unitPrice | <unit-price> |
id | <row-id> (single-word keys get a row- prefix) |
lastModified | <last-modified> |
Custom element tag names always contain a hyphen — this is an HTML spec requirement, not a stylistic choice.
The function is named toTagName, not toKebab. The name describes the concern (producing a valid tag name), not the implementation (kebab-case).
Schema-driven visibility and ordering
The order of keys in JSON does not determine the DOM render order. The order comes from a schema (external .json file) that lists the permitted keys for a payload type along with their preferred order.
schema example
[
"id",
"productName",
"unitPrice",
"lastModified"
]Visibility is not a flag in the schema. Visibility is the data presence — an empty value renders an empty element which CSS hides via :empty.
Positional mapping for page-level fields
Page-level fields map to canonical semantic positions, not to custom elements:
| JSON key | DOM target |
pageTitle | main article h1 |
intro | main article p:nth-of-type(1) |
body | main article section |
This mapping is fixed by the architecture and lives in oninput.js. New page-level fields require updating both the schema and the mapping.
Card pattern reminder
Cards exist only in plural as ul / li. Each card row is a <li> whose children are toTagName-generated custom elements carrying the per-row data. A single, identity-bearing item uses <article> instead.
What data-flow never does
- Never injects HTML strings (
innerHTML = '...') - Never reads
class,id, ordata-*(those don't exist) - Never writes inline styles
- Never sets visibility via JS (CSS does that)
- Never re-renders the shell (shell fetched once per session)
Baseline & support
Checked against MDN as of 2026-07-16.
custom elements— Baseline Widely available — https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elementssubgrid— Baseline Widely available — https://developer.mozilla.org/en-US/docs/Web/CSS/Guides/Grid_layout/Subgrid:has()— Baseline Widely available — https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Selectors/:has
Canonical rules: https://github.com/Autocss-com/ai/blob/main/AGENTS.md
References
references/totagname.md— the function specification with edge cases (single words, all-caps, numerals)references/lifecycle.md— fetch → parse → render sequence in detailreferences/schema.md— schema file format and where it livesreferences/positional-mapping.md— page-level field-to-element table- Custom elements spec: https://html.spec.whatwg.org/multipage/custom-elements.html
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.

