Astryx Starter
A Vite + React + React Router + Astryx starter with a working app shell, client-side routing, light/dark theming, a Chinese UI, an interactive component gallery, and an icon browser.
Stack
| Tool | Version |
|---|---|
| Vite | 8.x |
| React | 19.x |
| React Router | 7.x |
| Astryx | 0.7.2 |
| TypeScript | 6.0 |
| Oxlint | 1.x |
| pnpm | 11.x |
Astryx requires React 19 or later. It ships pre-built CSS, so this project does not need a StyleX, PostCSS, or Babel plugin.
Requirements
- Node.js 20.19 or newer
- pnpm 11 or newer
Getting started
pnpm install
pnpm dev
Vite prints the local URL. Open it in a browser and edit any file under src/; HMR updates the page immediately.
Scripts
| Command | Description |
|---|---|
pnpm dev |
Start the Vite dev server |
pnpm build |
Type-check with TypeScript and build for production |
pnpm lint |
Run Oxlint |
pnpm preview |
Preview the production build locally |
pnpm astryx <command> |
Run the project-local Astryx CLI |
Useful Astryx commands:
pnpm astryx component Button # full props, examples, and theming
pnpm astryx component --list # list every component
pnpm astryx template --list # browse page and block templates
pnpm astryx docs theme # theme reference
Project structure
app.config.ts router mode (browser or hash)
src/
app-routes.tsx routes + sidebar labels/icons (single source of truth)
components/
AppLayout.tsx app shell, top nav, side nav, route scroll reset
ComponentsRoute.tsx lazy route for the component gallery
IconsRoute.tsx lazy route for the icon browser
Page.tsx shared page frame and page header
data/
astryxComponents.ts all 173 components and their groups
demos/
ActionsDemo.tsx … interactive examples by category
pages/
HomePage.tsx
ComponentsPage.tsx
IconsPage.tsx
AboutPage.tsx
NotFoundPage.tsx
theme/
ThemeMode.tsx light/dark provider, persisted to localStorage
astryx-themes.ts generated theme registry (CLI-managed)
router.tsx React Router route table
App.tsx providers and router
main.tsx entry point
src/app-routes.tsx is the single source of truth for pages and navigation. Add a page there once; src/router.tsx derives the route tree from it and src/components/AppLayout.tsx derives the sidebar from the same list. Set showInNav: false for routes that should not appear in the sidebar.
Component gallery
The components page renders 14 interactive scenes grouped into base, form, and overlay sections. The scenes cover buttons, typography, layout, data tables, feedback, navigation, chat, form inputs, selection controls, selectors, dialogs, menus, the command palette, and toasts. All 173 Astryx components are represented in the scene metadata, and the full component list is available in a collapsible section at the bottom. Use the search field or the group toggles to narrow the gallery.
Icons
The icons page (/icons) browses 29 Astryx semantic icons and 1,903 Lucide icons. Click any icon to copy its usage, search by name, and page through the Lucide library. The Lucide catalog is lazy-loaded so it does not affect the initial route bundle.
Build and chunking
- The component gallery (
/components) and icon browser (/icons) are lazy-loaded routes. - vite.config.ts splits React and React Router into stable
react-vendorandrouter-vendorchunks. - In the current production build, the main
indexchunk is about 231 kB minified / 72 kB gzip, the lazy component gallery is about 385 kB / 118 kB gzip, and the lazy Lucide catalog is about 639 kB / 169 kB gzip.
Router mode
The root app.config.ts controls which router React Router creates:
export const appConfig = {
routerMode: 'browser', // or 'hash'
}
browseruses normal URLs such as/components. The host must rewrite unknown paths toindex.html.hashuses URLs such as/#/components. It works on static hosting without a rewrite.- Restart the dev server after changing the mode.
Astryx LinkProvider is wired to React Router's Link, so internal links, nav items, and buttons keep working in both modes.
Routing
const pageRoutes: RouteObject[] = appRoutes.map((route) =>
route.path === '/'
? { index: true, element: route.element }
: { path: route.path.slice(1), element: route.element },
)
const routes: RouteObject[] = [
{
path: '/',
element: <AppLayout />,
children: [...pageRoutes, { path: '*', element: <NotFoundPage /> }],
},
]
export const router =
appConfig.routerMode === 'hash'
? createHashRouter(routes)
: createBrowserRouter(routes)
LinkProvider is wired to React Router's Link, so Astryx links, buttons with href, nav items, and list rows all participate in client-side navigation. Absolute URLs are handled as external links by React Router.
When using browser mode on static hosting, configure the host to rewrite unknown paths to index.html so deep links such as /components reach the client router. hash mode does not need a rewrite.
Theming
src/astryx-themes.ts is generated by the Astryx CLI and imports the production theme CSS plus font CSS. ThemeModeProvider wraps the app in <Theme mode={...}> and exposes a toggle to the app shell.
To add another installed theme:
pnpm add @astryxdesign/theme-matcha
pnpm astryx theme add matcha
Then select it in src/theme/ThemeMode.tsx. The mode toggle supports light and dark, starts from the OS preference, and remembers the choice in localStorage.
The base styles are imported in src/index.css:
@import '@astryxdesign/core/reset.css';
@import '@astryxdesign/core/astryx.css';
Localization
All app copy is Chinese. Astryx's built-in strings (for example the required-field label, skip link, and navigation controls) are localized through InternationalizationProvider in src/main.tsx, which loads the shipped zh-CN catalog.
Package manager policy
The project uses pnpm 11 and pins the versions in pnpm-lock.yaml. Astryx 0.7.2 and lucide-react 1.61.0 were published inside pnpm's minimum release age window, so pnpm-workspace.yaml explicitly excludes those exact versions from the policy and allows the Astryx postinstall scripts. If you bump these packages, update the exclusions or wait until the new versions age past the policy window.
Notes
AGENTS.mdcontains the Astryx agent guide generated byastryx init.theme.template.tsis the editable template for authoring a custom theme.- The
@astryxdesign/clipackage is a dev dependency; use the project-localpnpm astryxscript so the versions stay in sync.
