A gallery of reference applications built with the Astryx design system, React 19, TypeScript and Vite.
Each directory is a standalone project — not a workspace package. There is no root
package.json; you install and run each template on its own. Copy the one closest to what
you are building, or read it as a worked example of how a real Astryx page is composed.
Every template starts from the same harness (Vite + React 19 + TypeScript + oxlint +
@astryxdesign/core + tdesign-icons-react) and differs only in its frame, its content and,
in five cases, a custom theme.
Live demos: astryx-templates.pages.dev — every
template, built and served under one directory (/dashboard/, /chat-app/, …). That page
also introduces the astryx agent skill, which teaches
a coding agent the procedure these templates were built with; install it with
npx skills add hex2null/astryx.
![]() dashboard · Meridian Console / back-office |
![]() chat-app · Nova Messaging |
![]() kanban · Relay Tracker (board) |
![]() inbox · Dispatch Tracker (master–detail) |
![]() social-feed · Astryx Social Feed |
![]() image-hub · Aperture Media library |
![]() tech-store · Voltyx Storefront |
![]() bento-grid · Kite Landing page |
![]() consulting · Meridian Vantage Marketing |
![]() magazine · Broadsheet Editorial |
![]() resume · Rowan Alcántara Document |
![]() docs-site · Astryx Docs Docs |
Every shot is the template's own dev server at a 1485×850 viewport on a retina scale factor, in light mode — see Screenshots for how to replace one.
Requires Node.js ^20.19.0 or >=22.12.0 (Vite 8).
git clone https://github.com/hex2null/astryx-templates.git
cd astryx-templates/dashboard # or any other template
npm install
npm run dev # dev server on http://localhost:5173
npm run build # tsc -b && vite build
npm run lint # oxlint
npm run preview # serve the production build| Template | What it is | Archetype / frame | Theme |
|---|---|---|---|
dashboard |
Meridian — a commerce operations console: KPI tiles, chart panels (Recharts) and a dense orders table | Console / back-office. AppShell + TopNav + collapsible 256px SideNav over a Layout |
neutral |
chat-app |
Nova — a ChatGPT-style AI assistant with conversation history and a docked composer | Messaging. AppShell + resizable SideNav over ChatLayout |
neutral |
kanban |
Relay — a sprint board of draggable issue cards in five status columns | Tracker (board). AppShell + TopNav + SideNav 260; LayoutContent scrolls horizontally over fixed 304px columns, each its own Layout |
neutral |
inbox |
Dispatch — a three-pane mail client: mailboxes, thread list, reading pane | Tracker (master–detail). AppShell + SideNav 260 + Layout with a 400px start LayoutPanel |
neutral |
social-feed |
Astryx Social — an x.com-style timeline with a composer and a discover rail | Feed (column frame). AppShell + SideNav | timeline 600 | rail 350, each with its own scroll |
custom (x-blue) |
image-hub |
Aperture — a community image library; clicking a tile opens the photo detail view with comments | Media library / gallery. AppShell + TopNav (identity, search, upload) |
custom (aperture) |
tech-store |
Voltyx — a consumer electronics storefront: category and product tiles, value props, promo band | Storefront (marketing + gallery). AppShell + TopNav, centred 1200 column of full-bleed bands |
neutral |
bento-grid |
A product landing page whose centrepiece is a mixed-size tile mosaic | Landing page. AppShell height="auto" + TopNav, full-bleed bands over a 1200 column; six-column Grid with uniform rows and GridSpan tiles |
neutral |
consulting |
Meridian Vantage Partners — the homepage of a global management consulting firm | Marketing / document site, single scroll of composed bands | custom (meridian) |
magazine |
An editorial front page — lead story, front section, opinion, long read and a wire column | Editorial document. AppShell height="auto" + TopNav folio; twelve-column grid split differently in every band |
custom (press) |
resume |
A personal résumé / CV page, with a real print stylesheet | Document / profile. AppShell height="auto" + TopNav identity band, centred 1120 column |
custom (ink) |
docs-site |
Documentation site — side nav, article body and a right-hand outline | Docs. AppShell + Layout with LayoutPanel outline |
neutral |
All twelve build and run. Every template except dashboard and tech-store has its own
README.md with layout notes; those two still carry the default Vite boilerplate README.
In all twelve the authoritative frame contract is the comment at the top of src/App.tsx
(or, in consulting and magazine, the band components it composes).
<template>/
index.html page title + #root + /src/main.tsx
vite.config.ts vite + @vitejs/plugin-react
tsconfig*.json app / node project references
.oxlintrc.json react + typescript + oxc rules
.claude/CLAUDE.md Astryx agent guidance (identical in every template)
public/favicon.svg
src/
main.tsx reset.css/astryx.css load order, <Theme>, registerIcons()
index.css @import of Astryx reset + astryx.css + the theme's CSS
App.tsx the page — opens with a frame contract comment
data.ts seed content, kept out of the layout code
icons.tsx thin wrapper over Astryx <Icon> with tdesign glyphs
iconType.ts bridges tdesign icon types onto Astryx's SVGProps slots
theme.ts custom theme source (only in themed templates)
src/App.tsx (or, in consulting, the band components it composes) begins with a comment
that states the archetype, the frame, the container choices and the responsive behaviour
before any code. That contract is the point of these templates: the frame is decided
first, then content is fitted to it.
Five templates ship a custom theme — consulting (meridian), image-hub (aperture),
magazine (press), resume (ink) and social-feed (x-blue). The workflow is
source → generated:
# src/theme.ts is the source of truth
npx astryx theme build src/theme.ts
# → src/<name>.js, <name>.css, <name>.d.ts, <name>.variants.d.ts (generated — do not edit)src/index.css imports the generated <name>.css, and src/main.tsx wraps the app:
import { Theme } from '@astryxdesign/core/theme'
import { inkTheme } from './ink' // the generated module, not theme.ts
<Theme theme={inkTheme}><App /></Theme>Themes extend neutralTheme and adjust accents, neutral temperature and a small number of
component variants — brand colour is set through defineTheme, never by overriding
--color-* in :root. The unthemed templates import @astryxdesign/theme-neutral/theme.css
directly instead.
Icons come from tdesign-icons-react.
main.tsx calls registerIcons() to map Astryx's semantic icon slots (close, chevronDown,
search, …) onto tdesign glyphs, so built-in components render correctly. For icons used
directly in the page, go through the local Icon wrapper in src/icons.tsx to keep Astryx's
semantic size/color props.
The rules the templates follow are documented in each project's .claude/CLAUDE.md
(identical everywhere) and enforced by review, not by tooling. In short:
- No raw
<div>— Astryx components do all layout and spacing. - Frame first — pick the shell (
AppShell, orLayout+LayoutPanel) and budget regions in px before writing content. - Rows for dense data (
Table,List/Item), edge to edge.Cardis for dashboard widgets, galleries and settings groups — never one card per list row. - Tokens for every value —
var(--color-*),var(--spacing-*),var(--radius-*). No raw hex or px, no utility-class CSS, no hand-written stylesheets except where a platform feature has no component API (e.g. the print rules inresume/src/index.css).
The Astryx CLI is the discovery tool — run it from inside a template:
npx astryx build "<idea>" # returns a kit: closest page + blocks + components
npx astryx template <name> # scaffold or study a page/block recipe
npx astryx component <Name> # props + examples
npx astryx search "<query>" # find a component, hook, doc or template
npx astryx docs <topic> # layout, tokens, color, spacing, typography, motion, …
npx astryx upgrade --apply # run after bumping @astryxdesign/corescreenshot/<template>.webp is a 1200×675 image used by the README gallery above and by
the demo site's cards. These twelve files are the only images the repository keeps: the
full-resolution captures they were cut from are throwaway and deliberately not committed, so
cloning stays cheap and the site build only ever copies bytes.
To replace one, capture the page, then convert it:
./screenshot/build-thumbs.sh resume ~/Desktop/shot.pngThat script needs ImageMagick (brew install imagemagick); nothing else in the repo does.
It crops to a uniform 16:9 anchored at the top, because GitHub's markdown has no object-fit
and the README relies on the files themselves being the same shape. Since the source is not
kept, changing the crop or the size means recapturing every template — worth knowing before
you touch those numbers.
Capture from the template's own dev server at a 1485×850 viewport, device pixel ratio 2, light mode, which is what makes the set look like one gallery rather than twelve unrelated images, and lands almost exactly on the 16:9 crop. Three things to check before committing a new one:
- Recapture after changing the page. A screenshot is a copy of the source at one moment and
nothing enforces that it stays current —
kanban's first capture was taken minutes beforekanban/src/dates.tspinned its formatter, so it shipped2026年7月29日on azh-CNmachine while the code it depicted already read29 Jul. - Every date and number formatter is locale-pinned (
en-GBininboxandkanban,en-USindashboardandtech-store), so a capture reads the same on any machine. If you add a baretoLocaleDateString()ornew Intl.DateTimeFormat(undefined, …), that stops being true — the shot then follows whatever locale the capturing browser happens to use. - Wait for images. The gallery cards are
loading="lazy"; a full-page screenshot taken too early shows empty slots that are not actually broken.
All twelve templates are published together as one Cloudflare Pages site, each mounted on its
own path. deploy/build-site.mjs builds every template with --base=/<name>/ straight into
site/<name>/ — Vite rewrites the bundle, favicon and public/ URLs with that base, so each
app works unchanged from a subdirectory. The landing page at site/index.html and the
site/404.html beside it are generated from the same script — markup, stylesheet and all —
so the site has no build step of its own and no framework behind it.
The landing page leads with the astryx agent skill,
not with the grid: the demos are what the skill produces, so the page shows the procedure
first and the evidence second. Its hero is a console running one /astryx build to
completion, printing the frame as a box diagram with real region budgets before it names a
file — the skill's own argument, made in the skill's own vernacular. Below that come the
usage examples, then the demo grid, then Astryx itself.
That page is hand-written HTML and CSS inside build-site.mjs, deliberately not an Astryx
app — it is the wrapper around the templates, not one of them, so the conventions above do
not apply to it. It ships one small inline script, for the install command's copy button.
The console keeps its own dark palette in both colour schemes; everything else follows
prefers-color-scheme.
The demo grid is generated from the template list in that script, so the landing page can
never advertise a demo that was not built. Each card carries the template's screenshot,
copied from screenshot/ into site/screenshot/; a template with no image still builds, its
card simply renders without one and the missing name is reported at the end of the run.
node deploy/build-site.mjs # build all twelve into ./site
node deploy/build-site.mjs dashboard # rebuild one (gallery is regenerated either way)
npx wrangler pages deploy site --project-name astryx-templatessite/ is generated and git-ignored. There is still no root package.json — the script
shells out to each template's own local tsc and vite, and installs its dependencies first
if node_modules is missing. None of the templates use a router, so no SPA fallback or
_redirects file is needed; Pages resolves /<name>/ to /<name>/index.html on its own.
To deploy from CI instead, point a Cloudflare Pages Git integration at this repo with build
command node deploy/build-site.mjs and output directory site.
- Copy the closest existing template into a new top-level directory.
- Update
index.html(<title>),src/data.tsandsrc/App.tsx; keep the frame contract comment at the top ofApp.tsxcurrent. - Replace the boilerplate
README.mdwith a description of the template and its frame. - Add an entry to
TEMPLATESindeploy/build-site.mjsso it ships with the demo site. - Capture the page per Screenshots, run
./screenshot/build-thumbs.sh <name> <capture.png>, and add a cell to the README gallery. - Verify
npm run buildandnpm run lintpass before opening a pull request.
MIT — use these templates as the starting point for anything, commercial work
included. @astryxdesign/*, react and the other dependencies keep their own licenses.











