VTS Basic is a production-ready React application that combines modern web technologies with best practices for performance, accessibility, and developer experience. Built with TanStack Start, it provides a solid foundation for building fast, accessible web applications.
- Framework: TanStack Start with SSR and type-safe routing
- Styling: Tailwind CSS + DaisyUI with theme switching
- State Management: TanStack Query for server state
- Language: TypeScript for type safety
- Runtime: Bun for fast development and builds
- PWA Support: Service Worker with offline capabilities and intelligent caching
- Accessibility: WCAG 2.1 AA compliant with keyboard navigation and screen reader support
- Toast Notifications: User feedback with theme-aware notifications
- Loading States: Shimmer-animated skeletons for better perceived performance
- Theme Switching: Multiple DaisyUI themes with persistent selection
- Virtual Scrolling: Efficient rendering of large country lists
- Optimized Images: Lazy loading and caching for flag images
- API Client: Centralized HTTP client with retry logic and error handling
- Service Worker: Advanced caching strategies (NetworkFirst, StaleWhileRevalidate, CacheFirst)
- Architecture Decision Records: Documented technical decisions in
docs/rationale/ - Comprehensive Testing: Unit tests with Vitest (86%+ coverage)
- E2E Testing: Playwright for browser automation
- Build Validation: Automatic asset validation to catch deployment issues
- Docker Support: Multi-stage builds with Rust proxy server
- Rust Proxy: High-performance proxy server for static assets and API requests
- Docker Deployment: Containerized with multi-stage builds
- Metrics: Prometheus-compatible metrics endpoint
- Error Handling: Centralized error handling with retry logic
- Documentation Index - Central documentation hub
- Architecture Decision Records - Technical decisions and rationale
- Docker Quick Start - Quick reference for Docker commands
- Docker Deployment Guide - Complete guide for building and deploying with Docker
- Build Validation - Automatic asset validation after builds
- The file
docs/design_iterator.mdis credited to EveryInc — original source: https://github.com/EveryInc/claude_commands/blob/main/agents/design-iterator.md
- Install dependencies:
bun install
- Start the dev server:
bun run dev
- Open http://localhost:3000 (or the port shown in your terminal).
Use these from the project root (vts-basic).
- Start dev server:
bun run dev
- Build for production:
bun run build
- Build production assets (Vite + Rust proxy):
bun run build:prod
- Validate build assets:
bun run validate
- Serve production build:
bun run serve:prod
- Build and serve production:
bun run start:prod
- Run tests (Vitest):
bun run test
- Lint / format (Biome or configured tooling):
bun run lint
bun run format
The project includes a build validation script (validate-build.js) that checks for asset hash mismatches after building. This ensures that all asset references in the server manifest match the actual files in the dist/client directory.
bun run validate
The script will:
- Check that all assets referenced in manifest files exist
- Identify missing assets and suggest similar files
- Exit with an error if any mismatches are found
Note: The build:prod script automatically runs validation after building. If validation fails, the build process will stop before compiling the Rust proxy.
- Asset references in
dist/server/assets/*-manifest*.jsfiles - Actual files in
dist/client/assets/ - JavaScript, CSS, and other static assets
If you see validation errors, try:
- Clean build:
rm -rf dist .tanstack node_modules/.cache && bun run build - Reinstall dependencies:
rm -rf node_modules && bun install && bun run build
The project includes a Rust-based proxy server (proxy/) that serves static assets and proxies requests to the Bun server in production. This architecture provides:
- Efficient static file serving
- Request proxying to the Bun SSR server on port 8081
- Production-ready performance
In development, you typically don't need the proxy - just use bun run dev.
For production:
- Build everything:
bun run build:prod- Builds the Vite frontend
- Compiles the Rust proxy in release mode
- Run both servers:
bun run serve:prod- Bun server runs on port 8081 (SSR)
- Rust proxy runs on port 3000 (public-facing)
Access the application at http://localhost:3000.
A multi-stage Dockerfile is included for containerized deployments:
docker build -t vts-basic:latest .
docker run -p 3000:3000 -p 8081:8081 vts-basic:latest
src/— application sourcesrc/pages/— page-level components:Home.tsx,about/,country/, error pagessrc/components/— shared UI (if present)src/routes/— TanStack Router file-based routes (if applicable)
proxy/— Rust proxy serverproxy/src/main.rs— main proxy server implementationproxy/Cargo.toml— Rust dependencies
public/manifest.json— PWA manifest, updated to "VTS Basic"
- Tailwind CSS is the utility layer.
- DaisyUI provides theme variables and component classes.
- A theme switcher is included in the app header so you can preview different DaisyUI themes. Selecting a theme toggles DaisyUI's theme classes (client-side).
If you'd like to persist a theme across sessions, you can:
- Store the selected theme in
localStorageand read it on app startup. - Apply the theme class to the
htmlorbodyelement before React hydrates to avoid flash of un-themed UI.
The Countries page uses TanStack Query (@tanstack/react-query) to fetch live country data from the REST Countries API. Key patterns to follow:
- Create a
QueryClientand wrap the app withQueryClientProvider(already configured). - Use
useQueryfor fetching and caching. - Present loading, error, and empty states for a robust UX.
We use TanStack Router with a small, focused set of routes:
/— Home / components showcase/about— About and usage guidance/country— Dynamic country listing (search, filter, sort)
Routes are typically file-based (see src/routes if used) and the root layout includes the theme switcher and top navigation.
VTS Basic is built with accessibility as a core principle, meeting WCAG 2.1 AA standards.
- Skip Link: Press
Tabon any page to reveal a "Skip to main content" link - Focus Indicators: Clear visual indicators for all interactive elements
- Tab Order: Logical tab order throughout the application
- Keyboard Shortcuts: All functionality accessible via keyboard
- Semantic HTML: Proper use of HTML5 semantic elements (
<main>,<nav>,<header>) - ARIA Labels: Descriptive labels for navigation regions
- Landmark Regions: Screen readers can navigate by landmarks
- Alt Text: All images have descriptive alt text
- High Contrast: Support for
prefers-contrast: highmedia query - Focus Visible: Enhanced focus indicators for keyboard users
- Color Contrast: All text meets WCAG AA contrast requirements
- Theme Support: Multiple themes with accessible color combinations
- Reduced Motion: Respects
prefers-reduced-motionsetting - Animations: Can be disabled for users with vestibular disorders
- Transitions: Minimal or instant transitions when motion is reduced
# Test with keyboard navigation
# - Press Tab to navigate
# - Press Enter/Space to activate
# - Press Escape to close modals
# Test with screen reader (macOS)
# - Enable VoiceOver: Cmd + F5
# - Navigate by landmarks: Ctrl + Option + U
# - Navigate by headings: Ctrl + Option + Cmd + H- Keep changes small and documented.
- Add new components under
src/componentsand pages undersrc/pages. - Follow Tailwind and DaisyUI patterns for consistent theming.
- Run the linter/formatter before creating PRs:
bun run lint
bun run format
- Styles don't show up: Confirm Tailwind is compiling and the dev server is running
- Blank page: Check browser console for runtime errors (missing env vars, failed fetches)
- Network/CORS errors: Usually transient — verify connectivity and external API availability
-
Asset validation failures: If
bun run validatefails with missing asset errors:- Clean build artifacts:
rm -rf dist .tanstack node_modules/.cache - Rebuild:
bun run build - Validate again:
bun run validate
If the issue persists, try reinstalling dependencies:
rm -rf node_modules && bun install && bun run build - Clean build artifacts:
-
CSS 404 errors in Docker: If you see "styles-XXX.css net::ERR_ABORTED 404" errors:
- Stop and remove the container:
docker stop vts-basic-app && docker rm vts-basic-app - Clean local build artifacts:
rm -rf dist .tanstack node_modules/.cache - Rebuild fresh:
docker build --pull --no-cache -t vts-basic:latest . - Run again:
./run_on_local_docker.sh
The
build:prodscript includes validation to catch these issues before deployment. - Stop and remove the container:
-
Old content showing: Service Worker may be caching old assets
- Open DevTools → Application → Service Workers
- Click "Unregister" for the service worker
- Hard refresh:
Cmd+Shift+R(Mac) orCtrl+Shift+R(Windows/Linux)
-
Offline mode not working:
- Check that Service Worker is registered (DevTools → Application → Service Workers)
- Verify you're using HTTPS or localhost (Service Workers require secure context)
- Check browser console for Service Worker errors
-
Toasts not appearing:
- Check that
<Toaster />is rendered in__root.tsx - Verify
react-hot-toastis installed:bun install react-hot-toast - Check browser console for errors
- Check that
-
Toasts appear in wrong position:
- Position is set to
bottom-leftin__root.tsx - Modify the
positionprop on<Toaster />to change location
- Position is set to
-
Skip link not appearing:
- Press
Tabkey to focus the skip link - It's visually hidden until focused (this is intentional)
- Press
-
Focus indicators not visible:
- Check that
focus-visiblestyles are loaded fromstyles.css - Verify you're using keyboard navigation (Tab key), not mouse clicks
- Check that
- The app is intentionally minimal and ready to be extended.
- Manifest and branding were updated to "VTS Basic". Update
public/logo192.pngandlogo512.pngif you want custom icons. - Consider adding tests for page-level behavior (loading / error UI) and components.