React + TypeScript + Vite
This template provides a minimal setup to get React working in Vite with HMR and some Oxlint rules.
Environment variables
Copy .env.example to .env and adjust the values:
VITE_ROUTER_MODE=hash
VITE_BASE_URL=/app/
| Variable | Default | Description |
|---|---|---|
VITE_ROUTER_MODE |
history |
history or hash; other values fail startup/build. |
VITE_BASE_URL |
/ |
Deployment pathname for assets and routing, such as /app/. Must start with a single /, without query strings, fragments, whitespace, or backslashes. A trailing / is added automatically. |
With /app/, the About page is /app/about in history mode and
/app/#/about in hash mode. History mode requires the host to serve
/app/index.html for application paths under /app/. Hash mode does not
require a server-side route fallback.
Shell environment variables override .env values:
VITE_ROUTER_MODE=hash VITE_BASE_URL=/app/ pnpm build
Vite also loads .env.local, .env.[mode], and .env.[mode].local.
Mode-specific files override generic files; shell variables have highest priority.
For example, pnpm build --mode staging loads .env.staging.
Environment files are ignored by Git except for .env.example.
Restart the development server after changing variables. Production values are
embedded during the build; changing server environment variables requires rebuilding.
Custom frontend variables use the VITE_ prefix and are read through
import.meta.env. These values are public, so do not put secrets in them.
See Vite environment variables.
Routing
Routing uses React Router Data Mode.
src/route-config.ts is the single source for page paths, components, titles,
icons, menu groups, and default expanded groups. It generates the page routes and
menu data. src/router.tsx creates the router with createBrowserRouter or createHashRouter, and
src/main.tsx renders it with RouterProvider. src/App.tsx configures the
Spectrum Provider and renders the route Outlet inside BasicLayout.
src/components/layout-basic.tsx owns the sidebar, top bar, collapse state, and content area,
with styles in src/components/layout-basic.module.css. It accepts page content through children.
src/components/sidebar-menu.tsx provides the shared menu list, and
src/components/collapsed-navigation.tsx renders the same data in icon mode.
The top bar reads the title from the matched route's metadata. On screens up to
640px wide, src/components/mobile-navigation.tsx opens it in a full-screen modal
from the top bar. Selecting a page or closing the modal returns to the content.
/: the homepage insrc/page-home.tsx./about: the about page insrc/page-about.tsx./form: the Spectrum form showcase insrc/page-form.tsx./ui-kit: the Spectrum component showcase insrc/page-ui-kit.tsx.- Unmatched paths: the 404 page in
src/page-not-found.tsx.
Place page components directly in src/ and name their files page-*.tsx.
Place shared components and their styles in src/components/.
Use colocated *.module.css files for page and component styles. Keep global
theme variables, document styles, and resets in src/index.css. Shared menu icon
styles live in src/components/menu-icon.module.css, and the basic page spacing
is shared through src/page.module.css.
The top-right settings button opens src/components/global-settings.tsx with
light and dark appearance options. src/theme.ts provides the shared theme
context; App synchronizes it with Spectrum's Provider and the document theme.
The initial theme uses the saved preference, or the system preference on first
visit. Selections persist in local storage when it is available.
UI Kit
src/components/ui-kit/ contains lazily loaded examples of buttons, badges,
status lights, alerts, progress indicators, dialogs, popovers, tooltips, toasts,
breadcrumbs, tabs, accordions, removable tags, cards, and a sortable table with
row selection. Examples respond to the global light/dark appearance setting.
Form showcase
src/components/form-examples/ contains lazily loaded examples of text, password,
email, URL, telephone, search, multiline, number, checkbox, radio, switch, picker,
combo box, select box, segmented control, toggle buttons, slider, range slider,
date/time fields, date pickers, calendars, color controls, file selection, and drag
and drop. Layout controls demonstrate sizes, label positions, and disabled states.
Each field has its own named label/input grid. Side labels automatically fall
back to top labels when the form container is narrower than 560px, and restore
when sufficient space is available.
Submission uses native validation plus a custom username rule. The username
admin demonstrates a local business validation error. A successful submission
shows a data preview with the password masked; no data or files are uploaded.
Reset remounts the examples to clear both native inputs and controlled widget state.
Add pages to routeConfig in src/route-config.ts with a unique id, title,
absolute path, Component, and optional Icon. Use children for menu groups
and defaultExpanded to control their initial expansion. Menu groups do not
change page URLs. Set hidden: true to keep a route out of navigation, as with
the 404 page. Desktop, collapsed, and mobile menus all use this configuration.
When deploying in history mode, configure your host to serve index.html from
the configured base directory for application URLs so direct visits and refreshes
on nested routes work.
Currently, two official plugins are available:
- @vitejs/plugin-react uses Oxc
- @vitejs/plugin-react-swc uses SWC
React Compiler
The React Compiler is not enabled on this template because of its impact on dev & build performances. To add it, see this documentation.
Expanding the Oxlint configuration
If you are developing a production application, we recommend enabling type-aware lint rules by installing oxlint-tsgolint and editing .oxlintrc.json:
{
"$schema": "./node_modules/oxlint/configuration_schema.json",
"plugins": ["react", "typescript", "oxc"],
"options": {
"typeAware": true
},
"rules": {
"react/rules-of-hooks": "error",
"react/only-export-components": ["warn", { "allowConstantExport": true }]
}
}
See the Oxlint rules documentation for the full list of rules and categories.
