1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
|
# 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](https://vite.dev) | 8.x |
| [React](https://react.dev) | 19.x |
| [React Router](https://reactrouter.com) | 7.x |
| [Astryx](https://astryx.atmeta.com) | 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
```bash
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:
```bash
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
```text
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](./vite.config.ts) splits React and React Router into stable `react-vendor` and `router-vendor` chunks.
- In the current production build, the main `index` chunk 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](./app.config.ts) controls which router React Router creates:
```ts
export const appConfig = {
routerMode: 'browser', // or 'hash'
}
```
- `browser` uses normal URLs such as `/components`. The host must rewrite unknown paths to `index.html`.
- `hash` uses 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
```tsx
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:
```bash
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`:
```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.md` contains the Astryx agent guide generated by `astryx init`.
- `theme.template.ts` is the editable template for authoring a custom theme.
- The `@astryxdesign/cli` package is a dev dependency; use the project-local `pnpm astryx` script so the versions stay in sync.
|