A modern, production-ready boilerplate for building React applications with TypeScript, Vite, TanStack Router, TanStack Query, React Hook Form, Zod, Shadcn UI, and more.
npm install dialog-webappA modern, production-ready React application built with TypeScript, Vite, TanStack Router, TanStack Query, React Hook Form, Zod, Shadcn UI, and i18n support.
``bash`
npm install
npm run dev
Open http://localhost:5173 in your browser.
You can also scaffold a new project from this template:
`bash`
npx dialog-webapp my-app
cd my-app
npm run dev
- β‘ Vite - Fast build tool and dev server
- βοΈ React 19 - Latest React with TypeScript
- π― TanStack Router - Type-safe, file-based routing with conditional layouts
- π TanStack Query - Data fetching and caching
- π React Hook Form - Performant forms with Zod validation
- β
Zod - TypeScript-first schema validation
- π¨ Shadcn UI - Accessible component library (Radix UI + Tailwind)
- π i18n - Internationalization with react-i18next (English, Dutch)
- π Dark Mode - Theme toggle with system preference support (usehooks-ts)
- π
Tailwind CSS - Utility-first styling
- π§Ή Biome - Formatter and linter
- πͺ Husky - Git hooks, Commitlint, lint-staged
- π
date-fns - Date utilities
- π Sonner - Toast notifications
- π Axios - HTTP client
- Node.js 24+ and npm
1. Clone the repository and install dependencies:
`bash`
npm install
2. Start the dev server:
`bash`
npm run dev
3. Open http://localhost:5173.
| Script | Description |
| ---------------- | ------------------------------ |
| npm run dev | Start development server |npm run build
| | Type-check and production build|npm run preview
| | Preview production build |npm run lint
| | Run Biome linter |npm run lint:fix
| | Fix lint issues |npm run format
| | Format with Biome |npm run format:check
| | Check formatting |npm run check
| | Run all Biome checks |npm run check:fix
| | Fix format and lint |npm run registry:build
| | Build shadcn registry (outputs to public/r/) |
This project can publish feature blocks via the shadcn registry, so other apps can install them with the shadcn CLI.
- Registry name: dialog-ui-block-registry (see registry.json).features-login
- Block: β login feature (form, hooks, components), routes (login.tsx, forgot-password.tsx), and lib files (axios, local-storage, notify, utils, constants).
Generate the registry JSON files (used when serving or publishing the registry):
`bash`
npm run registry:build
- Reads registry.json and writes one JSON file per block into public/r/ (e.g. public/r/features-login.json).shadcn
- Requires the CLI (devDependency).
1. Run the build above, then start the app:
`bash`
npm run registry:build
npm run dev
2. The registry is served at the app origin, for example:
- Index: http://localhost:5173/r/registry.jsonhttp://localhost:5173/r/features-login.json
- Login block:
From a project that already has shadcn set up (e.g. components.json and Tailwind):
`bash`
npx shadcn@latest add https://
Example with a deployed URL:
`bash`
npx shadcn@latest add https://your-app.vercel.app/r/features-login.json
The CLI will add the login feature files, routes, lib, and constants, and install any missing npm dependencies. After installing, set VITE_API_BASE_URL and adjust auth redirect URLs if needed (see the blockβs docs in registry.json).
1. Edit registry.json: add or update items (name, type, files, registryDependencies, dependencies, etc.). See the registry schema and registry item schema.npm run registry:build
2. Run so public/r/ is updated.
3. Re-serve or redeploy so the new or updated JSON is available at the registry URL.
To keep blocks isolated and safe to consume in other repos (fewer conflicts, predictable installs), follow these guidelines. See also .cursor/rules/registry-block-feature.mdc.
| Principle | Recommendation |
| --------- | -------------- |
| Self-contained | Put everything the block needs under one feature dir (e.g. src/features/login/). Ship any shared lib/constants the feature uses inside the block (e.g. src/lib/axios.ts, src/constants/index.ts) so the consumer gets a complete set of files. |./validations
| Imports within the block | Use relative imports between files inside the feature (e.g. , ./hooks/use-post-login.mutation). Use @/ only for shared app surface (e.g. @/components/ui, @/lib/utils) that you also list as registry/npm deps or ship in the block. |registryDependencies
| Declare all deps | In registry.json: list every shadcn component in , every npm package in dependencies. In the block docs, list env vars (e.g. VITE_API_BASE_URL) and any consumer-provided modules (e.g. βreplace @/lib/axios with your API client if neededβ). |src/features/login/
| Stable, unique targets | Use fixed target paths (e.g. , src/routes/login.tsx, src/lib/axios.ts) so the same block always installs to the same place. Use registry:file for routes/config so the CLI writes to the specified path regardless of framework. |login
| Avoid naming clashes | Use a clear, namespaced feature name (e.g. , auth-login). If the consumer already has a conflicting path, they must resolve it (e.g. install once, or adapt paths manually). Document in docs when a block overwrites or depends on specific paths. |src/routes/login.tsx
| No hidden app coupling | Donβt rely on app-only layout, root route, or env that the block doesnβt ship or document. Optional: ship a minimal route file (e.g. ) and document that the consumer may need to wire it into their router or sidebar logic. |
Rules live in .cursor/rules/. Reference a rule with @.cursor/rules/[filename] so Cursor follows the conventions.
| Rule | Purpose |
|------|--------|
| translation-i18n.mdc | How to add and structure translations β group keys by feature, update both locale files |tanstack-query-hooks.mdc
| | How to create TanStack Query hooks β basic query, infinite query (pagination), mutation |feature-structure.mdc
| | How to create a new feature β directory layout, public API, decomposed components |form-and-validation.mdc
| | Form and validation structure β React Hook Form, Zod, validations.ts, i18n (login-style) |page-and-routes.mdc
| | How to create a new page and route β file-based routing, layout, sidebar visibility |registry-block-feature.mdc
| | How to structure features as isolated shadcn registry blocks β build and consume without conflicts |
π Translation (i18n)
``
Create a new translation for feature sidebar with this @.cursor/rules/translation-i18n.mdc
π TanStack Query hooks
``
Add an infinite query for posts list with this @.cursor/rules/tanstack-query-hooks.mdc
π New feature
``
Create a new feature settings following @.cursor/rules/feature-structure.mdc
π Form and validation
``
Add a contact form for the feedback feature with this @.cursor/rules/form-and-validation.mdc
π New page and route
``
Create a new settings page at /settings with this @.cursor/rules/page-and-routes.mdc
- Biome for formatting and linting.
- Husky for git hooks; Commitlint (conventional commits) and lint-staged for pre-commit checks.
Create a .env in the project root. Only variables prefixed with VITE_ are exposed to the client (see Vite env docs).
| Variable | Description |
| -------- | ----------- |
| VITE_API_BASE_URL | API base URL for axios. Defaults to http://localhost:3000/api if unset. |VITE_APP_SIDEBAR_ENABLED
| | Set to 'true' to show the app sidebar in the dashboard layout; otherwise the layout renders without sidebar. |
Example .env:
`env`
VITE_API_BASE_URL=https://api.dialog.hellotoms.com
VITE_APP_SIDEBAR_ENABLED=true
- @/ is an alias for src/ (see vite.config.ts and tsconfig.app.json).
Theme is controlled via DarkModeProvider and the shared dark mode toggle. In components:
`tsx
import { useDarkMode } from '@/hooks/utilities/use-dark-mode';
function MyComponent() {
const { isDarkMode, toggle, enable, disable } = useDarkMode();
// ...
}
`
- Pre-commit: lint-staged (format and lint staged files).
- Commit-msg: Commitlint enforces Conventional Commits (e.g. feat:, fix:, docs:).
| Route | Description |
| ----- | ----------- |
| / | Home; project selection dialog (no sidebar). |/login
| | Login form (no sidebar). |/signup
| | Sign up form (no sidebar). |/forgot-password
| | Forgot password form (no sidebar). |/:project_code
| | Dashboard layout; shows app sidebar when VITE_APP_SIDEBAR_ENABLED=true, otherwise content only. |/:project_code/cockpit` | Cockpit page under the dashboard layout. |
|
MIT