A production-ready full-stack React application template with integrated Express server, featuring React Router 6 SPA mode, TypeScript, Vitest, Zod and modern tooling.
While the starter comes with a express server, only create endpoint when strictly neccesary, for example to encapsulate logic that must leave in the server, such as private keys handling, or certain DB operations, db...
- Frontend: React 18 + React Router 6 (spa) + TypeScript + Vite + TailwindCSS 3
- Backend: Express server integrated with Vite dev server
- Testing: Vitest
- UI: Radix UI + TailwindCSS 3 + Lucide React icons
client/ # React SPA frontend
├── pages/ # Route components (Index.tsx = home)
├── components/ui/ # Pre-built UI component library
├── App.tsx # App entry point and with SPA routing setup
└── global.css # TailwindCSS 3 theming and global styles
server/ # Express API backend
├── index.ts # Main server setup (express config + routes)
└── routes/ # API handlers
shared/ # Types used by both client & server
└── api.ts # Example of how to share api interfaces
The routing system is powered by React Router 6:
client/pages/Index.tsxrepresents the home page.- Routes are defined in
client/App.tsxusing thereact-router-domimport - Route files are located in the
client/pages/directory
For example, routes can be defined with:
import { BrowserRouter, Routes, Route } from "react-router-dom";
<Routes>
<Route path="/" element={<Index />} />
{/* ADD ALL CUSTOM ROUTES ABOVE THE CATCH-ALL "*" ROUTE */}
<Route path="*" element={<NotFound />} />
</Routes>;- Primary: TailwindCSS 3 utility classes
- Theme and design tokens: Configure in
client/global.css - UI components: Pre-built library in
client/components/ui/ - Utility:
cn()function combinesclsx+tailwind-mergefor conditional classes
// cn utility usage
className={cn(
"base-classes",
{ "conditional-class": condition },
props.className // User overrides
)}- Development: Single port (8080) for both frontend/backend
- Hot reload: Both client and server code
- API endpoints: Prefixed with
/api/
GET /api/ping- Simple ping apiGET /api/demo- Demo endpoint
Import consistent types in both client and server:
import { DemoResponse } from '@shared/api';Path aliases:
@shared/*- Shared folder@/*- Client folder
npm run dev # Start dev server (client + server)
npm run build # Production build
npm run start # Start production server
npm run typecheck # TypeScript validation
npm test # Run Vitest testsOpen client/global.css and tailwind.config.ts and add new tailwind colors.
- Optional: Create a shared interface in
shared/api.ts:
export interface MyRouteResponse {
message: string;
// Add other response properties here
}- Create a new route handler in
server/routes/my-route.ts:
import { RequestHandler } from "express";
import { MyRouteResponse } from "@shared/api"; // Optional: for type safety
export const handleMyRoute: RequestHandler = (req, res) => {
const response: MyRouteResponse = {
message: 'Hello from my endpoint!'
};
res.json(response);
};- Register the route in
server/index.ts:
import { handleMyRoute } from "./routes/my-route";
// Add to the createServer function:
app.get("/api/my-endpoint", handleMyRoute);- Use in React components with type safety:
import { MyRouteResponse } from '@shared/api'; // Optional: for type safety
const response = await fetch('/api/my-endpoint');
const data: MyRouteResponse = await response.json();- Create component in
client/pages/MyPage.tsx - Add route in
client/App.tsx:
<Route path="/my-page" element={<MyPage />} />- Standard:
npm run build+npm start - Binary: Self-contained executables (Linux, macOS, Windows)
- Cloud Deployment: Use either Netlify or Vercel via their MCP integrations for easy deployment. Both providers work well with this starter template.
- Single-port development with Vite + Express integration
- TypeScript throughout (client, server, shared)
- Full hot reload for rapid development
- Production-ready with multiple deployment options
- Comprehensive UI component library included
- Type-safe API communication via shared interfaces