A modern, accessibility-first React 19 application built with Vite 7 and TypeScript 5. This template enforces strict rules for accessibility (WCAG 2.2 AA), performance, and code quality.
π Fork-Friendly Setup: This template is designed to work out-of-the-box for forks! All advanced features (CodeQL, SonarCloud, GitHub Pages CI, JSDoc) are disabled by default and only run when you explicitly enable them. See .env.example for minimal setup instructions.
A compact, searchable wiki for quick project notes, operational runbooks, diagrams, and short HOWTOs.
Explore the full documentation, architecture, and deep technical notes for this project on DeepWiki:
β οΈ Note for Forks: The SonarCloud badges above are for the original repository. If you're not using SonarCloud, you can safely remove these badges (lines 3-7).
- There is a lite version available here modern-react-template-lite
- There is a mono repo version available here modern-monorepo-template
- βΏ Accessibility-first (WCAG 2.2 AA compliant)
- π¦Ύ Axe-core automated accessibility checks
- π Commitlint enforcing conventional commit messages
- π‘οΈ Global Error Boundary with custom fallback UI and reload/reset support
- π ESLint static analysis
- πͺ Husky pre-commit + commit-msg hooks
- π§Ή Knip unused code & dependency analysis (non-blocking, see CI)
- π Playwright for E2E browser testing
- π Prettier code formatting
- β¨ React 19 with the latest features
- π¨ Tailwind-like CSS utility classes in index.css
- π TanStack Query for server state management
- π§ TanStack Router for type-safe routing
- π Theming with light/dark mode and design tokens
- β‘ Vite 7 β Fast dev server and production build (used for local development, HMR, and building
dist/) - π§ͺ Vitest + React Testing Library unit testing and accessible queries
- π§ββοΈ Zod for data validation
- π« 404 Not Found Page accessible, customizable fallback for unmatched routes
- π‘οΈ CodeQL for advanced code scanning and security analysis
- π GitHub Pages deployment for app and docs
- π SonarCloud for continuous code quality analysis
- π TypeDoc for automated API documentation
See Feature Configuration for a canonical list of optional repository Actions variables (ENABLE_*) and detailed setup instructions for CodeQL, SonarCloud, GitHub Pages, and JSDoc.
By default, this repository treats CodeQL scans as opt-out to avoid heavy analysis running automatically on forks and CI. Use one of these methods to run CodeQL:
- Run manually: In GitHub, go to Actions β CodeQL β Run workflow. Ensure the
run_codeqlinput istrue. - Enable automated runs: Add a repository Variable or Secret named
ENABLE_CODEQLwith valuetrueunder Settings β Secrets and variables β Actions β Variables (or Secrets). When set totrue, scheduled/push/PR runs will be allowed.
This matches the workflow gating in .github/workflows/codeql.yml.
This template uses SonarCloud for continuous code quality and security analysis. Configuration is driven by environment variables so forks can set up their own SonarCloud projects without editing source files.
Setup Requirements (for your fork or repo):
- Sign up at SonarCloud
- Import your repository into SonarCloud and note the generated:
- Organization key (e.g.
my-org) - Project key (e.g.
my-org_modern-react-template)
- Add
SONAR_TOKENto your GitHub repository secrets (Project Settings β Security β Tokens in SonarCloud). - In your GitHub repository settings, add the following Actions secrets/variables:
SONAR_ORGANIZATIONβ your SonarCloud organization keySONAR_PROJECT_KEYβ your SonarCloud project keySONAR_TOKENβ the token from SonarCloud
- (Optional) Go to Settings β Variables β Actions in your GitHub repository and create a variable named
ENABLE_SONARCLOUDwith valuetrueto enable SonarCloud analysis. Set it tofalse(or remove it) to skip the SonarCloud job.
The sonar-project.properties file reads SONAR_ORGANIZATION and SONAR_PROJECT_KEY at analysis time, so no changes are required in the file when you fork this template.
View your project's quality metrics on the SonarCloud dashboard when analysis is enabled.
The template automatically deploys four entry points to GitHub Pages on every push to main:
- Main Landing Page β
https://asudbury.github.io/modern-react-template/ - Demo App β
https://asudbury.github.io/modern-react-template/app - API Documentation β
https://asudbury.github.io/modern-react-template/docs
Setup Requirements:
- Go to repository Settings β Pages
- Set Source to "GitHub Actions"
- Push to
mainbranch to trigger deployment
Important: Deployment only happens from the main branch. The workflow automatically configures proper base paths for asset loading.
This template uses a global error boundary to catch unexpected errors anywhere in the React component tree and display a user-friendly fallback UI instead of a blank screen or crash.
- Implemented using
react-error-boundary - Configured in
src/main.tsxwrapping the entire app - Custom fallback UI in
src/components/ErrorFallback/ErrorFallback.tsx - Users can reload the app or reset the error boundary from the fallback UI
Prerequisites:
- Node.js 20 or higher
- npm (comes with Node.js)
# Install dependencies
npm install
# Start development server
npm run devVisit http://localhost:5173 to see your application.
π΄ Forked this repo? See QUICKSTART.md for fork-specific setup instructions. All optional features (SonarCloud, GitHub Pages, etc.) are disabled by default and won't interfere with your fork.
This template uses TanStack Router for type-safe client-side routing. The router is configured in src/router.tsx and integrated into the app via App.tsx.
The template includes a Navigation component that uses TanStack Router's Link component for type-safe navigation:
import { Link } from '@tanstack/react-router';
<Link to="/" activeProps={{ className: 'active' }}>
Home
</Link>/- Home page (HomePage component)*(any unmatched path) β 404 Not Found page (NotFoundPage component)
This template includes a fully accessible, customizable 404 Not Found page for unmatched routes. The 404 page:
- Is automatically shown for any route that does not match a defined path
- Uses semantic HTML, design tokens, and is keyboard/screen reader accessible
- Provides a clear message and a link to return home
Customizing the 404 page:
- Edit
src/pages/NotFoundPage/NotFoundPage.tsxto change the message, add illustrations, or update the layout - The route is configured in
src/router.tsxwithpath: '*'
Demo: On the home page, click the "Demo 404 Not Found page" link to preview the 404 page in the app.
To add a new route, update src/router.tsx:
import { createRoute } from '@tanstack/react-router';
import { YourComponent } from './pages/YourComponent';
const yourRoute = createRoute({
getParentRoute: () => rootRoute,
path: '/your-path',
component: YourComponent,
});
// Add to routeTree
const routeTree = rootRoute.addChildren([
indexRoute,
yourRoute
]);TanStack Router provides full TypeScript autocomplete and type checking for routes:
import { Link, useNavigate } from '@tanstack/react-router';
// Link component with autocomplete
// Programmatic navigation
const navigate = useNavigate();
navigate({ to: '/' });For more details, see the TanStack Router documentation.
npm run dev- Start development servernpm run build- Build for production (no GitHub Pages side effects)npm run preview- Preview production build
npm run lint- Run ESLintnpm run lint:fix- Fix ESLint issuesnpm run prettier- Format code with Prettiernpm run knip- Analyze for unused files, exports, and dependencies (see below)- Conventional commits enforced via commitlint on
git commit
This template uses Knip to detect unused files, exports, and dependencies:
- Run
npm run kniplocally to see a report of unused code and dependencies - Knip runs automatically in CI (see the "Knip (Unused Code Analysis)" job)
- Knip is non-blocking: CI and deployments will never fail due to Knip findings; the report is uploaded as an artifact for maintainers to review
- Use Knip to keep your codebase clean and remove dead code as needed
Example:
npm run knip
# or in CI, download the knip-report artifact for detailsSee knip.toml for configuration details.
npm run test- Run unit tests in watch modenpm run test:unit- Run unit testsnpm run test:coverage- Run unit tests with coverage reportnpm run test:ui- Run tests with UInpm run test:e2e- Run E2E tests with Playwright
npm run docs- Generate both markdown and HTML documentationnpm run docs:md- Generate markdown documentation indocs/npm run docs:html- Generate HTML documentation indocs-html/
npm run update:gh-page-details- Injectpackage.jsonversion into a copy ofpublic/gh-pages-index.htmland write it todist/gh-pages-index.html(used for GitHub Pages landing page)npm run build:gh-pages- Build the app and, whenENABLE_GH_PAGES=true, generate GitHub Pages artifacts (includingdist/gh-pages-index.html)
npm run cleanup- Interactive script to remove optional features and customize the template to your needs
π§Ή Cleanup Tool: Use
npm run cleanupto interactively remove features you don't need (Playwright, commitlint, SonarCloud, TypeDoc, GitHub Pages, etc.). This helps you start with a minimal setup tailored to your project. See scripts/README.md for details.
modern-react-template/
βββ .github/
β βββ workflows/
β β βββ ci.yml # CI/CD pipeline
β β βββ codeql.yml # CodeQL security scanning (opt-in)
β β βββ sonarcloud.yml # SonarCloud analysis (opt-in)
β β βββ pages.yml # GitHub Pages deployment (opt-in)
β βββ copilot-instructions.md # Copilot coding guidelines
βββ .husky/
β βββ pre-commit # Pre-commit hooks
β βββ pre-commit-secrets # Pre-commit secrets hooks
βββ docs/ # Generated markdown docs (TypeDoc)
βββ docs-html/ # Generated HTML docs (TypeDoc)
βββ knip.toml # Knip configuration (unused code analysis)
βββ playwright/ # UI tests
βββ src/
β βββ components/ # Reusable UI components and samples
β β βββ Button/ # Button component (+ tests, stories, index)
β β βββ Navigation/ # Navigation bar
β β βββ ErrorFallback/ # Global error fallback for error boundary
β βββ pages/ # Route/page components
β βββ queries/ # Data fetching/mutations (TanStack Query)
β βββ schemas/ # Zod schemas and types
β βββ test/ # Test setup/mocks
β βββ App.tsx # Root app component
β βββ main.tsx # Entry point (includes error boundary)
β βββ router.tsx # Router config
β βββ index.css # Global styles
βββ .env.example # Environment variables template
βββ .gitignore # Git ignore rules
βββ .gitleaks.toml # Secret scanning config (Gitleaks)
βββ .gitleaksignore # Secret scanning ignore rules
βββ .prettierrc # Prettier configuration
βββ eslint.config.js # ESLint configuration
βββ package.json # Dependencies and scripts
βββ playwright.config.ts # Playwright configuration
βββ sonar-project.properties # SonarCloud configuration
βββ tsconfig.json # TypeScript configuration
βββ typedoc.json # TypeDoc markdown config
βββ typedoc.html.json # TypeDoc HTML config
βββ vite.config.ts # Vite configuration
βββ vitest.config.ts # Vitest configuration
This template generates comprehensive documentation in multiple formats:
The docs/ directory contains auto-generated markdown documentation from TypeDoc. This is committed to the repository and provides developer-friendly API documentation.
npm run docs:mdHTML documentation is automatically generated and deployed to GitHub Pages:
- API Docs: https://asudbury.github.io/modern-react-template/docs
- Demo App: https://asudbury.github.io/modern-react-template/app
This template ships with several concrete samples you can use as references:
- Home page layout:
src/pages/HomePage/HomePage.tsxdemonstrates accessible page structure and headings. - Reusable component + tests:
src/components/Button/includes the button implementation and unit tests - Data fetching utilities:
src/queries/fetch.tsandsrc/queries/mutate.tsshow how to use TanStack Query with Zod validation. - E2E + accessibility test:
playwright/homepage.spec.tsis a full Playwright + axe-core example for the home page. - Generated API docs:
docs/anddocs-html/contain TypeDoc output you can browse as living samples of the project APIs.
Husky enforces code quality on every commit:
- Format code with Prettier
- Run unit tests
- Lint with ESLint
- Build the project
If any of these checks fails, the commit is blocked and the corresponding
command's error output is shown in your terminal (for example ESLint errors
or failing tests). Fix the reported issues and re-run git commit.
Additionally, a Husky commit-msg hook runs commitlint to enforce
Conventional Commits for commit
messages. Example:
feat: add a new component
fix: handle invalid user IDs in updateUser
chore: configure commitlint for commit messages
Optional build steps for GitHub Pages are controlled via repository-level Actions variables, not committed to the repo. Configure them at:
https://github.com/asudbury/modern-react-template/settings/variables/actions
This template supports accessible theming with light and dark modes, powered by design tokens and utility classes in src/index.css.
- Light and dark mode support out of the box
- Uses CSS custom properties (design tokens) for colors, spacing, and typography
- Theme toggle button included (see
ThemeToggleButtoncomponent) - All components use tokenized styles for full theme compatibility
- The app automatically detects system theme preference and applies it
- Users can toggle theme manually using the theme toggle button in the UI
- To customize themes, edit
src/index.css
For more, see the ThemeToggleButton for reference.
- Every component is keyboard-navigable
- Screen reader friendly with proper ARIA attributes
- WCAG 2.2 AA compliant
- Color contrast ratios meet minimum requirements
- Automated accessibility testing with Axe
- No inline JSX handlers - Use
useCallbackor named functions - Named exports - No default exports for components
- Design tokens only - No hardcoded colors or spacing
- Strict TypeScript - All code must be fully typed
- Zod validation - All external data must be validated
- JSDoc documentation - All exported functions, components, and types must have JSDoc comments
All public APIs (exported functions, components, types) should optionally include JSDoc comments:
/**
* Button Component
*
* An accessible button component following WCAG 2.2 AA guidelines.
*
* @example
* ```tsx
* <Button variant="primary" onClick={handleClick}>
* Click me
* </Button>
* ```
*/
export function Button({ variant = 'primary', ...props }: ButtonProps) {
// Implementation
}- Unit tests - Use Vitest + React Testing Library
- Query by role - Use accessible queries (
getByRole,getByLabelText) - User events - Use
userEvent.setup(), neverfireEvent - E2E tests - Use Playwright with Axe accessibility checks
## Environment Variables
Create a `.env` file based on `.env.example`:
```bash
cp .env.example .env
All environment variables must be prefixed with VITE_ to be exposed to the client.
For local tooling and CI toggles, additional variables are defined in
.env.example (not exposed to the client), including:
SONAR_ORGANIZATION,SONAR_PROJECT_KEY,SONAR_TOKENβ SonarCloud configENABLE_SONARCLOUDβ enable/disable SonarCloud in CISKIP_COMMITLINTβ set totrueto temporarily skip commit message linting enforced by Husky + commitlint
The CI pipeline runs on every push and pull request:
- Lint - ESLint checks
- Format - Prettier checks
- Test - Unit tests with Vitest
- Build - Production build
- E2E - Playwright tests with Axe accessibility scans
This repository's GitHub Actions workflows cache npm and build artifacts to speed CI runs. Common ways to inspect and control caches:
- Inspect Actions job logs for cache messages like
Cache restored from key:(cache hit) orCache not found for input key:(cache miss). - To force-refresh caches, update
package-lock.json(recommended) so lockfile-based cache keys change, or temporarily change the workflow cache key (not recommended long-term). - Example cache keys used in workflows:
- npm cache:
${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} - Vite cache:
${{ runner.os }}-vite-${{ hashFiles('**/package-lock.json') }}-${{ hashFiles('**/vite.config.ts') }}
- npm cache:
If you want help verifying a cache hit/miss on a recent Actions run, tell me which run and I can point to the relevant log lines.
Husky runs the following checks on every commit:
- Format code with Prettier
- Run unit tests
- Lint with ESLint
- Build the project
If any check fails, the commit is blocked.
This repository includes local and CI secret scanning using gitleaks.
- Local npm scripts (defined in
package.json):
# Full repo scan
npm run secrets:scan
# Scan only staged changes (good for pre-commit hooks)
npm run secrets:scan-staged
# Create/update baseline report
npm run secrets:baseline- To enable blocking secret checks locally, add
npm run secrets:scan-stagedto your Huskypre-commithook (or run it manually before committing). CI still runs a full scan via thesecret-scanjob.
This template is designed to be extensible. See EXTENSIONS.md for comprehensive guides on:
- π¨ TypeDoc Custom Theming - Customize documentation appearance
- π Error Logging Frameworks - Sentry, LogRocket, Rollbar integration
- π Plug-and-Play Options - Radix UI, Headless UI, React Hook Form
- ποΈ Infrastructure as Code - AWS CDK, Terraform, Pulumi guides
- π οΈ Extensibility Scripts - Component generators and scaffolding tools
- βοΈ Cloud Deployments - AWS, Azure, GCP, Vercel, Netlify guides
- π‘ Additional Features - Authentication, i18n, analytics, monitoring
- Follow the coding conventions outlined in this README
- Write tests for all new features
- Ensure accessibility compliance
- Run all checks before committing
- Keep PRs small and focused
MIT

