π A modern, production-ready React template for building MVPs quickly and efficiently.
This template provides everything you need to start building a React application with authentication, analytics, monitoring, and a complete design system - all configured and ready to go!
- React 19 - Latest React with modern features
- TypeScript 5.7 - Full type safety with strict configuration
- Vite 6 - Lightning-fast development and builds
- TanStack Router - Type-safe, file-based routing
- TanStack Query - Server state management with caching
- Tailwind CSS 4 - Modern styling with custom design system
- React Aria Components - Accessible UI primitives
- Storybook - Component documentation and testing
- Click the "Use this template" button at the top of this repository
- Choose "Create a new repository"
- Give your project a name (e.g.,
my-awesome-app
) - Choose if you want it public or private
- Click "Create repository from template"
# Replace 'your-username' and 'your-repo-name' with your actual values
git clone https://github.com/your-username/your-repo-name.git
cd your-repo-name
β οΈ Important: This project uses yarn as the package manager. Do not use npm.
yarn install
If you don't have yarn installed:
# macOS
brew install yarn
# Windows (using Chocolatey)
choco install yarn
# Or install globally with npm
npm install -g yarn
Copy the example environment file:
# macOS/Linux
cp .env.sample .env.local
# Windows (Command Prompt)
copy .env.sample .env.local
# Windows (PowerShell)
Copy-Item .env.sample .env.local
Your .env.local
file should look like this to get started:
# .env.local
VITE_API_URL="http://localhost:8000"
VITE_COGNITO_POOL_ID= # Leave empty for now
VITE_COGNITO_CLIENT_ID= # Leave empty for now
VITE_COGNITO_DOMAIN= # Leave empty for now
# Analytics (Leave empty - console logging works by default)
VITE_PUBLIC_POSTHOG_KEY=
VITE_PUBLIC_POSTHOG_HOST=
π Note: Analytics work out of the box using console logging. You don't need to configure PostHog or other services initially. When you're ready for production analytics, ask your team lead for the appropriate credentials.
yarn dev
Your app will be available at http://localhost:3000
β
Check that the development server started without errors
β
Visit http://localhost:3000 in your browser
β
Open browser developer tools (F12) - you should see analytics events in the console
β
Try navigating between pages
As we improve this template, you'll want to pull in those updates. Always use Pull Requests - never merge directly to main.
Add the original template as a remote source:
git remote add template https://github.com/original-username/mvp-frontend.git
git remote -v # Verify it was added
# 1. Fetch latest changes from template
git fetch template
# 2. Create a new branch for the update
git checkout -b update-template-$(date +%Y%m%d)
# 3. Merge template changes
git merge template/main --allow-unrelated-histories
# 4. Resolve any conflicts in VS Code (see below)
# 5. Test everything works
yarn dev
# 6. Push branch and create Pull Request
git push origin update-template-$(date +%Y%m%d)
Then create a Pull Request in GitHub and request review from your team lead.
When conflicts occur, VS Code will show them clearly:
- Open VS Code - conflicted files will be highlighted
- Click on conflicted files - VS Code shows a 3-way merge view
- Use VS Code's merge conflict UI:
- Click "Accept Current Change" (your project's version)
- Click "Accept Incoming Change" (template's version)
- Click "Accept Both Changes" (merge both)
- Or manually edit the result
Common conflicts and what to keep:
package.json
- Keep your project name, accept new dependenciesREADME.md
- Keep your project-specific content.env.local
- Keep your configuration values
# After resolving all conflicts in VS Code
git add .
git commit -m "Merge template updates - resolved conflicts"
git push origin update-template-$(date +%Y%m%d)
β οΈ Important: Don't merge the PR yourself! Your team lead should review and merge template updates.
All commands use yarn (never use npm with this project):
# Start development server (port 3000)
yarn dev
# Build for production
yarn build
# Preview production build locally
yarn serve
# Run tests
yarn test
# Run tests in watch mode
yarn test --watch
# Run component documentation
yarn storybook
# Type checking (find TypeScript errors)
npx tsc --noEmit
src/
βββ components/ # Reusable UI components
β βββ ui/ # Design system components (DON'T MODIFY,unless specfied)
β βββ layouts/ # Page layout components
βββ features/ # Feature-specific components
β βββ auth/ # Authentication components
βββ libs/ # Shared utilities and configurations
β βββ analytics/ # PostHog analytics setup
β βββ api/ # HTTP client configuration
β βββ query/ # React Query configuration
βββ routes/ # File-based routing
β βββ __root.tsx # Root layout (wraps all pages)
β βββ (authenticated)/ # Protected routes (require login)
β βββ (unauthenticated)/ # Public routes (login, signup)
βββ main.tsx # App entry point
- New pages: Add files to
src/routes/
- New components: Add to
src/components/
or feature folders - Business logic: Create new folders in
src/features/
src/components/ui/
- Design system componentssrc/libs/
- Core library configurationsvite.config.js
,tsconfig.json
- Build configurations
The design system is built on Tailwind CSS 4 with a two-tier token architecture configured in src/styles.css
. This system provides consistent styling across all components while remaining flexible for customization.
System Tokens - Foundation-level design decisions defined in the @theme
block:
- Raw color palettes (50-950 scales for each color family)
- Typography scales with font sizes and line heights
- Spacing, border radius, and layout primitives
Component Tokens - Higher-level semantic tokens that inherit from system tokens:
- Brand colors (
--color-brand-primary
,--color-brand-success
, etc.) - Surface styling (
--color-surface-background
,--radius-surface
) - Control styling (
--color-control-border
,--radius-control
)
The color system uses OKLCH color space for better perceptual uniformity and supports six semantic color families:
- Primary - Main brand color
- Accent - Secondary brand color
- Neutral - Text, borders, and backgrounds
- Success - Positive states and confirmations
- Warning - Cautionary messaging
- Danger - Errors and destructive actions
- Info - Informational content
Each color family includes full 50-950 scales designed to work seamlessly across both light and dark modes, covering 80% of typical color use cases. The scales provide semantic variants (text, border, muted, subtle, bold, inverse) that automatically adapt to theme changes.
Five distinct typography categories with consistent sizing:
- Metric - Large display numbers and statistics (2rem - 3.25rem)
- Heading - Page and section headers (2.25rem - 6rem)
- Title - Component and card titles (1.25rem - 2.5rem)
- Label - Form labels and UI text (0.75rem - 1.125rem)
- Paragraph - Body text and descriptions (0.75rem - 1.125rem)
All scales include matched line-height values for optimal readability and should not be modified unless absolutely necessary for brand requirements.
The design system integrates seamlessly with React Aria Components through component tokens:
- Surface components use
--color-surface-*
and--radius-surface
tokens - Interactive controls use
--color-control-*
and--radius-control
tokens - Button components inherit from
--radius-btn
(maps to control radius) - Layout components use standardized spacing through
--spacing-surface-*
tokens
For Non-Designers:
- Use Component Tokens First - Before reaching for system tokens, check if component tokens already provide what you need
- Modify System Tokens for Global Changes - Want a different primary color? Update the
--color-primary-*
scale - Create New Component Tokens - For new components, define semantic tokens that inherit from the system
- Avoid Hardcoded Values - Always reference design tokens rather than arbitrary CSS values
- Test Across Themes - Verify your changes work consistently across different theme configurations
Key Customization Points:
- Color families can be replaced by updating the OKLCH values in system tokens
- Component spacing and borders are controlled through surface and control token groups
- Layout behavior is managed through sidebar and surface padding variables
Typography Warning: The typography scales are carefully calibrated for readability and visual hierarchy. Modifying them can break the design system's consistency and should only be done for critical brand requirements.
The system is designed to maintain visual consistency even when customized, as component tokens automatically inherit changes from system tokens.
Feature folders group related components, hooks, and logic together.
Each feature should be self-contained with its own API calls, types, and components.
Example: src/features/auth/
contains login forms, auth hooks, and Cognito integration.
- Add new folders under
src/features/
for major app sections. Includecomponents/
,hooks/
, andapi/
subfolders as needed. - Keep feature-specific logic isolated from shared utilities in
src/libs/
.
- Create a
.tsx
file in the routes folder - TanStack Router will automatically scaffold the route structure. - Add
requireAuth
imported fromauth
feature in thebeforeLoad
for protected routes that need authentication. by default routes files insidesrc/routes/(authenticated)/
are protected.
- Add files in
src/routes/(authenticated)/
for protected pages requiring login. - Add files in
src/routes/(unauthenticated)/
for public pages like login/signup. See TanStack Router docs for complete file conventions.
- Use
builder()
with feature-based query keys and Zod schemas for type safety - Define
payload
andresponse
schemas for automatic request/response validation - Organize endpoints in feature folders (e.g.,
src/features/auth/api/endpoints.ts
)
// src/features/users/api/endpoints.ts
import { z } from "zod";
import { api } from "@/libs/api/api";
import { builder } from "@/libs/query/query-kit";
export const UserService = builder("users", {
getProfile: builder.query(
{
payload: z.object({ userId: z.string() }),
response: z.object({
id: z.string(),
name: z.string(),
email: z.string(),
}),
},
() => ({
fetcher: (payload) => api.get(`/users/${payload.userId}`),
})
),
});
- Use
builder.query()
for GET requests,builder.mutation()
for POST/PUT/DELETE - Use
builder.infiniteQuery()
for paginated data with automatic page management - Access hooks via
ServiceName.endpointName.useQuery()
oruseMutation()
- API errors are automatically structured with
status
andstatusText
properties - Use
getErrorMessage()
utility for consistent error display in UI - Errors integrate with toast notifications through the global error boundary
- Use
toPaginatedResponseSchema()
schema helper for standardized pagination structure - Built-in
paginatedParamsSchema
for page/perPage query parameters - Infinite queries handle
hasNext
/hasPrevious
logic automatically
- Keep API endpoints organized by feature with consistent naming conventions
- Always define both request and response Zod schemas for full type safety
- Use the
api
client for requests
The template includes analytics that work out of the box using PostHog's recommended [object] [verb] naming:
import { useAnalytics } from "@/libs/analytics";
function MyComponent() {
const analytics = useAnalytics();
const handleButtonClick = () => {
// PostHog best practice: [object] [verb] format
analytics.track("button clicked", {
location: "header",
text: "Sign Up",
});
// More examples:
analytics.track("user signed up", { method: "email" });
analytics.track("project created", { template: "react" });
analytics.track("page viewed", { page: "dashboard" });
};
return <button onClick={handleButtonClick}>Sign Up</button>;
}
What happens by default:
- Events are logged to console for development
- Clean [object] [verb] event naming should be followed
- No external service setup required initially
- IntelliSense shows best practices in JSDoc
When ready for production analytics, ask your team lead for:
- PostHog credentials (gets optimized $pageview events automatically)
- Other monitoring service credentials
Your team should already have these services configured - you just need the environment variables.
Solution: Install yarn globally
npm install -g yarn
- Check if port 3000 is already in use
- Try a different port:
yarn dev --port 3001
Run the type checker to see detailed errors:
yarn typecheck
- Fix any TypeScript errors first
- Check that all environment variables are set
- Check browser console (F12) - analytics events should appear there
- Verify the analytics service is initialized (check console messages)
- If using production analytics credentials, verify they're correct in
.env.local
- Always use yarn: Never mix npm and yarn in this project
- Environment variables: Never commit
.env.local
to git (it's already in .gitignore) - Package manager: The project is configured for yarn - using npm may cause issues
- Node version: Use Node 18+ for best compatibility
- VS Code Recommended: This template assumes VS Code for merge conflict resolution
- Junior Developers: Follow this README for setup, create PRs for template updates
- Team Leads: Review and merge template update PRs, manage production credentials
- Production Services: Team leads should provide analytics/monitoring credentials when ready
Happy coding! π If you run into issues, check the troubleshooting section above or create an issue in this repository.