-
Notifications
You must be signed in to change notification settings - Fork 22
feat(skills): pin the Astryx design system on every web application #470
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
d548d44
8a812f2
5df338c
abd3052
dbe167f
4613c3d
df462bd
e1f9f2c
3c7d959
5425195
0adbcdf
2f35827
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,196 @@ | ||
| --- | ||
| name: astryx-design-system | ||
| description: Astryx (`@astryxdesign/core`) — the platform's default web-app design system, its Theme + StyleX wiring, and the CLI you confirm every component's props against before writing JSX. Apply to all UI work in a `web-application` component that pins this skill — pages, layouts, forms, tables, dialogs, nav, theming — even when the task never names Astryx. | ||
| metadata: | ||
| aep: | ||
| kind: org | ||
| audience: [coding] | ||
| --- | ||
|
|
||
| # Astryx Design System | ||
|
|
||
| You are reading this because the component you are building pinned it, which | ||
| means Astryx (`@astryxdesign/core`) is **this organization's** UI toolkit — | ||
| components, layout, and styling (via StyleX) all come from it. Never raw HTML | ||
| styling, never another component library, never an invented component prop. | ||
|
|
||
| `react-webapp` owns the app: layout, config, verify sequence, Dockerfile, nginx. | ||
| This skill owns what goes **inside** `src/` — the UI. Where the two appear to | ||
| disagree, `react-webapp` wins; the conflicts worth naming are listed under | ||
| Platform constraints below. | ||
|
|
||
| ## Correctness through the CLI, not memory | ||
|
|
||
| Astryx ships `@astryxdesign/cli` because component APIs move faster than any | ||
| model's training data. The CLI reads the *installed* version, so it is always | ||
| right; a guessed prop is never right by comparison. The discipline: **before | ||
| writing JSX for a component you have not confirmed this session, run the CLI, | ||
| then write the JSX** — never the reverse. | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
|
|
||
| **Always invoke it as `npx --no astryx …`.** `--no` restricts resolution to the | ||
| `@astryxdesign/cli` in this app's `node_modules` — the version `package-lock.json` | ||
| pins. Without it, an `npx astryx` in an app whose install has not run fetches and | ||
| executes the unrelated `astryx` package that exists on the public registry. Do not | ||
| drop the flag to shorten a command: if the CLI is missing, the right outcome is the | ||
| loud `could not determine executable to run`, not a stranger's postinstall script | ||
| running in the build pod. | ||
|
|
||
| **Violating the letter of this rule is violating the spirit of it.** "It's just a | ||
| placeholder page," "the app doesn't have Astryx wired up yet," and "this screen | ||
| is throwaway" are reasons to wire Astryx up *faster*, not reasons to skip it — a | ||
| page built in raw `<div>`s is what deploys, because there is no human code-review | ||
| gate between your PR and the dev environment. | ||
|
|
||
| ## Setup | ||
|
|
||
| `react-webapp` scaffolds the app. Add Astryx to it: | ||
|
|
||
| ```bash | ||
| npm install @astryxdesign/core @stylexjs/stylex @astryxdesign/theme-neutral @astryxdesign/build | ||
| npm install -D @astryxdesign/cli | ||
| ``` | ||
|
|
||
| `@astryxdesign/core` declares React **19+** as a hard peer dependency — set | ||
| `react` / `react-dom` to `^19` in `package.json`, not an older major. | ||
|
|
||
| Wire the build (order matters — `astryxStylex()` before `react()`, and **no | ||
| `base`**, per `react-webapp`): | ||
|
|
||
| ```ts | ||
| // vite.config.ts | ||
| import {defineConfig} from 'vite'; | ||
| import react from '@vitejs/plugin-react'; | ||
| import {astryxStylex} from '@astryxdesign/build/vite'; | ||
|
|
||
| export default defineConfig({plugins: [...astryxStylex(), react()]}); | ||
| ``` | ||
|
|
||
| ```tsx | ||
| // main.tsx — reset + theme CSS load before anything renders | ||
| import '@astryxdesign/core/reset.css'; | ||
| import '@astryxdesign/theme-neutral/theme.css'; | ||
| import {Theme} from '@astryxdesign/core/theme'; | ||
| import {neutralTheme} from '@astryxdesign/theme-neutral/built'; | ||
| // wrap <App/> in <Theme theme={neutralTheme}> — swap the theme package to change | ||
| // the look, never hand-roll colors instead | ||
| ``` | ||
|
|
||
| ## Verify | ||
|
|
||
| This skill's step in `react-webapp`'s verify sequence — after `npm install`, | ||
| before `npx tsc --noEmit`: | ||
|
|
||
| ```bash | ||
| npx --no astryx doctor | ||
| ``` | ||
|
|
||
| A non-zero exit fails verification like any other step in that sequence. It is | ||
| there because a wiring fault (a missing `astryxStylex()` plugin, an unimported | ||
| theme, a React peer-dependency mismatch) type-checks and builds perfectly clean, | ||
| then renders an unstyled page in the cluster — cheap to fix here, expensive to | ||
| debug after the Docker build. | ||
|
|
||
| ## Platform constraints that override this system's defaults | ||
|
|
||
| Four places where Astryx's own defaults do not fit this platform. Each is a | ||
| runtime, build, or guidance failure, not a style preference: | ||
|
|
||
| 1. **Never install Astryx's agent docs.** `astryx init` itself is fine — it | ||
| initializes the design system in an *existing* project, and it is not | ||
| required, because the Setup section above already states the wiring. What | ||
| must not land is the `agents` feature: `astryx init --features agents` | ||
| writes `AGENTS.md` into the repo root, and `--all` includes it. Guidance | ||
| reaches you as skills, so a committed agent file is a second authority that | ||
| nothing updates — it is stale the moment this skill changes. `--features` is | ||
| an allow-list, so name only what you want (`--features theme`) and never | ||
| `--all`; if agent docs already landed, `astryx init --remove-agents` deletes | ||
| them. | ||
| 2. **Never set `base` in `vite.config.ts`**, whatever an Astryx snippet shows. | ||
| Each web app is served at its own gateway host root; a `base` 404s every asset | ||
| and the page renders blank (`react-webapp`, Served at host root). | ||
| 3. **The CSS imports go in `main.tsx`, never in `index.html`.** `index.html`'s | ||
| only `<script>` rules are `react-webapp`'s: the synchronous `env-config.js` | ||
| tag first, the module bundle second. Adding a stylesheet or script tag around | ||
| them risks `window._env_` being unset when the first module evaluates. | ||
| 4. **Theme tokens are not runtime config.** Colors and spacing come from the | ||
| theme package at build time. `window._env_` carries only what the **browser** | ||
| needs — OIDC config and flags — so do not plumb a theme value through it. | ||
|
Comment on lines
+116
to
+117
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win Keep the runtime configuration contract consistent.
🧰 Tools🪛 SkillSpector (2.5.1)[warning] 30: [RP1] null: npx commands without a version suffix (e.g. Remediation: Pin the version: npx (MCP Rug Pull (RP1)) [warning] 32: [RP1] null: npx commands without a version suffix (e.g. Remediation: Pin the version: npx (MCP Rug Pull (RP1)) [warning] 81: [RP1] null: npx commands without a version suffix (e.g. Remediation: Pin the version: npx (MCP Rug Pull (RP1)) [warning] 84: [RP1] null: npx commands without a version suffix (e.g. Remediation: Pin the version: npx (MCP Rug Pull (RP1)) [warning] 129: [RP1] null: npx commands without a version suffix (e.g. Remediation: Pin the version: npx (MCP Rug Pull (RP1)) [warning] 132: [RP1] null: npx commands without a version suffix (e.g. Remediation: Pin the version: npx (MCP Rug Pull (RP1)) [warning] 142: [RP1] null: npx commands without a version suffix (e.g. Remediation: Pin the version: npx (MCP Rug Pull (RP1)) [warning] 145: [RP1] null: npx commands without a version suffix (e.g. Remediation: Pin the version: npx (MCP Rug Pull (RP1)) [warning] 145: [RP1] null: npx commands without a version suffix (e.g. Remediation: Pin the version: npx (MCP Rug Pull (RP1)) [warning] 171: [RP1] null: npx commands without a version suffix (e.g. Remediation: Pin the version: npx (MCP Rug Pull (RP1)) [warning] 172: [RP1] null: npx commands without a version suffix (e.g. Remediation: Pin the version: npx (MCP Rug Pull (RP1)) [warning] 178: [RP1] null: npx commands without a version suffix (e.g. Remediation: Pin the version: npx (MCP Rug Pull (RP1)) [warning] 182: [RP1] null: npx commands without a version suffix (e.g. Remediation: Pin the version: npx (MCP Rug Pull (RP1)) [warning] 183: [RP1] null: npx commands without a version suffix (e.g. Remediation: Pin the version: npx (MCP Rug Pull (RP1)) 🤖 Prompt for AI Agents |
||
|
|
||
| Astryx replaces hand-written UI, not the platform's data layer: `openapi-fetch` | ||
| and the committed `src/generated/` client stay exactly as `react-webapp` | ||
| specifies. "Install no other library" below is about UI and styling. | ||
|
|
||
| ## Critical rules | ||
|
|
||
| 1. **Import everything from `@astryxdesign/core/<Category>`** (per-category | ||
| subpath entry points, e.g. `@astryxdesign/core/Button`, | ||
| `@astryxdesign/core/Layout`) — never from Tailwind, MUI, Chakra, Ant Design, | ||
| Bootstrap, or a hand-rolled component. | ||
| 2. **Run `npx --no astryx component <Name> --dense` before using ANY component**, | ||
| even one already used earlier in this session — confirm the prop exists before | ||
| writing it, don't guess. | ||
| 3. **Search before building.** Run `npx --no astryx search "<thing>"` when unsure | ||
| what exists; Astryx ships more components than you would assume (tag inputs, | ||
| command palettes, tree lists, chat UI) — check before reaching for a wrapper | ||
| `<div>` or a new dependency. | ||
| 4. **Layout is `VStack`/`HStack`/`Grid`/`Stack` from `@astryxdesign/core/Layout`** | ||
| — never a raw `<div>`/`<span>` for spacing or arrangement. | ||
| 5. **Style overrides are `stylex.create()` + the component's `xstyle` prop** — | ||
| never `style={{...}}`, and never `className`/`style` alongside | ||
| `{...stylex.props()}` (use `mergeProps()` if you must combine). | ||
| 6. **Colors and spacing are tokens, never literals.** Run | ||
| `npx --no astryx docs tokens --dense`; use the CSS-var color tokens and | ||
| `spaceN` gap values it documents, not hex/rgb or raw px. | ||
| 7. **Page-level structure follows a template, not intuition.** Run | ||
| `npx --no astryx template --list` and `npx --no astryx template <name> | ||
| --skeleton` to find and study a layout skeleton before hand-building a page (dashboard, | ||
| settings, list, wizard, auth) from scratch. | ||
| 8. **Navigation uses `useLinkComponent()`**, never a hardcoded `<a>`. | ||
| 9. **Dense data is rows, not cards.** Use `Table` or `List`+`Item` for lists of | ||
| records; `Card` is for widgets, galleries, or grouped settings — not one card | ||
| per row. | ||
|
|
||
| ## Reach for these components (not raw HTML) | ||
|
|
||
| | If you're about to build… | Use instead | | ||
| |---|---| | ||
| | Page shell with top bar + side nav | `AppShell`, `TopNav`, `SideNav`, `MobileNav` | | ||
| | A data table / list view | `Table`, `List` + `Item`, `MetadataList` | | ||
| | A form with grouped fields | `FormLayout`, `Field`, `FieldStatus` | | ||
| | A select / combobox / tag input | `Selector`, `MultiSelector`, `ComplexSelector`, `Typeahead`, `Tokenizer` | | ||
| | A modal / confirmation dialog | `Dialog`, `AlertDialog` | | ||
| | A dropdown / context / command menu | `DropdownMenu`, `ContextMenu`, `MoreMenu`, `CommandPalette` | | ||
| | Status / count / label chip | `Badge`, `StatusDot`, `Token`, `Indicator` | | ||
| | Tooltip / hover detail / anchored popup | `Tooltip`, `HoverCard`, `Popover` | | ||
| | Date/time entry | `DateInput`, `DateRangeInput`, `DateTimeInput`, `TimeInput`, `Calendar` | | ||
| | Loading / empty state | `Skeleton`, `Spinner`, `ProgressBar`, `EmptyState` | | ||
| | Breadcrumbs / global search | `Breadcrumbs`, `PowerSearch` | | ||
| | Toggle / choice input | `Switch`, `CheckboxInput`, `CheckboxList`, `RadioList`, `SegmentedControl`, `ToggleButton` | | ||
|
|
||
| This table is a quick guide, not the catalog — run | ||
| `npx --no astryx component --list` for every component grouped by category, or | ||
| `npx --no astryx search` when nothing here fits. | ||
|
|
||
| ## Pitfalls | ||
|
|
||
| | Symptom | Cause | Fix | | ||
| |---|---|---| | ||
| | Astryx components render unstyled/unthemed | `reset.css`/theme CSS not imported, or imported after other global CSS without layer ordering | Import reset + theme first in `main.tsx`; if the app has other global CSS, assign every stylesheet an explicit `@layer` (`npx --no astryx docs migration`) | | ||
| | `npm install` fails / peer-dependency warnings on React | `package.json` is on React <19 | Set `react`/`react-dom` to `^19` before installing `@astryxdesign/core` | | ||
| | Build succeeds but StyleX classes/styles don't apply | `astryxStylex()` missing from `vite.config.ts`, or ordered after `react()` | Add `...astryxStylex()` to `plugins`, listed before `react()` | | ||
| | Page renders blank in dev, every asset 404s | `base` was set in `vite.config.ts` from an Astryx snippet | Remove it — served at host root (`react-webapp`) | | ||
| | A prop doesn't exist, or is the old spelling | Answered from memory instead of the CLI | Run `npx --no astryx component <Name> --dense` — the CLI reflects the installed version, training data doesn't | | ||
| | Every row in a list is wrapped in its own `Card` | Defaulted to a generic "card grid" instead of checking data density | `npx --no astryx docs principles --dense` — dense data is `Table`/`List`+`Item`; `Card` is for widgets/galleries/settings groups | | ||
|
|
||
| ## Red flags — stop and use Astryx | ||
|
|
||
| - About to write `<div style={{...}}>` or a raw `className` for layout, color, or | ||
| spacing | ||
| - About to `npm install` any other component or styling library | ||
| - About to write JSX for a form, list, card, dialog, nav, or button from scratch | ||
| - Thinking "it's just a placeholder" or "Astryx isn't set up in this app yet" | ||
| - Using a prop without having confirmed it exists via | ||
| `astryx component <Name> --dense` | ||
|
|
||
| All of these mean: stop, run `astryx search` / `astryx component <Name> --dense`, | ||
| and use what it returns. | ||
Uh oh!
There was an error while loading. Please reload this page.