Repstack is built as a Progressive Web App (PWA) using React, TypeScript, and Vite. The architecture follows modern web development best practices with a focus on offline-first capabilities, type safety, and code quality.
- React 19 - UI library with latest features
- TypeScript - Type-safe JavaScript
- Vite - Fast build tool and dev server
- vite-plugin-pwa - PWA configuration and manifest generation
- Workbox - Service Worker lifecycle management
- Dexie.js - IndexedDB wrapper for local data storage
- dexie-react-hooks - React hooks for reactive database queries
- ESLint - JavaScript/TypeScript linting
- Prettier - Code formatting
- TypeScript strict mode - Enhanced type checking
Repstack/
├── public/ # Static assets served directly
│ ├── pwa-192x192.png # PWA icon (192x192)
│ ├── pwa-512x512.png # PWA icon (512x512)
│ ├── apple-touch-icon.png # iOS home screen icon
│ ├── icon.svg # Source icon (SVG)
│ ├── robots.txt # SEO robots file
│ └── vite.svg # Vite logo
│
├── src/ # Application source code
│ ├── components/ # Reusable UI components
│ ├── layouts/ # Layout components
│ │ ├── Layout.tsx # Main app layout with header/footer
│ │ └── Layout.css # Layout styles
│ ├── features/ # Feature-specific components
│ ├── pages/ # Page-level components
│ ├── hooks/ # Custom React hooks
│ │ └── useDatabase.ts # Database interaction hooks
│ ├── db/ # Database configuration
│ │ └── index.ts # Dexie schema and types
│ ├── lib/ # Utility functions
│ ├── styles/ # Global styles
│ ├── App.tsx # Root application component
│ ├── App.css # App-specific styles
│ ├── main.tsx # Application entry point
│ └── index.css # Global CSS reset and variables
│
├── index.html # HTML entry point
├── vite.config.ts # Vite configuration
├── tsconfig.json # TypeScript base configuration
├── tsconfig.app.json # TypeScript app configuration
├── tsconfig.node.json # TypeScript Node configuration
├── eslint.config.js # ESLint configuration
├── .prettierrc # Prettier configuration
├── .prettierignore # Prettier ignore patterns
├── package.json # Dependencies and scripts
└── .gitignore # Git ignore patterns
Decision: Use vite-plugin-pwa with Workbox for PWA capabilities.
Rationale:
- Provides offline-first functionality out of the box
- Automatic service worker generation
- Easy configuration with sensible defaults
- Works seamlessly with Vite's build process
Implementation:
- Service Worker caches all static assets
- Runtime caching for external resources (fonts, etc.)
- Manifest configured for installation on all platforms
Decision: Use IndexedDB via Dexie.js for all user data.
Rationale:
- No backend required for core functionality
- Data stays on user's device (privacy-first)
- Works completely offline
- Large storage capacity compared to localStorage
- Dexie provides cleaner API than raw IndexedDB
Schema:
- users: User profiles and preferences
- exercises: Exercise library (user-created)
- workouts: Workout logs with sets, reps, feedback
- mesocycles: Training blocks (4-6 week programs)Decision: Build with mobile-first approach using CSS flexbox/grid.
Rationale:
- Most users will access on mobile devices
- Easier to scale up than scale down
- Better performance on mobile
- Forces focus on essential features
Breakpoints:
- Mobile: < 640px
- Tablet: 641px - 1024px
- Desktop: > 1024px
Decision: Organize by feature with atomic design principles.
Structure:
components/- Reusable, generic components (buttons, inputs)features/- Feature-specific components (workout logger, exercise library)layouts/- Page layouts and structural componentspages/- Top-level page components
Rationale:
- Clear separation of concerns
- Easy to locate and modify features
- Promotes reusability
- Scales well as app grows
Decision: Use TypeScript in strict mode throughout.
Configuration:
strict: true- All strict checks enablednoImplicitAny: true- No implicit any types- Type-only imports where possible
Rationale:
- Catch errors at compile time
- Better IDE support and autocomplete
- Self-documenting code
- Easier refactoring
- Defines schema and models
- Handles IndexedDB interactions
- Provides type-safe API
- React hooks wrap database operations
- Provides reactive data with
useLiveQuery - Handles loading and error states
- Components consume hooks
- Display data to users
- Trigger database operations
Example Flow:
User Action → Component → Hook → Database → Reactive Update → Component Re-render
npm run dev- Starts Vite dev server with HMR
- PWA features enabled for testing
- Service Worker registers in development
npm run build- TypeScript compilation with strict checks
- Vite optimizes and bundles code
- Service Worker generated with all assets
- Manifest.json created
- Output in
dist/directory
npm run lint # Check for linting errors
npm run format # Format code with Prettier
npm run type-check # TypeScript type checking- Code splitting at route level
- Dynamic imports for large features
- Tree shaking of unused code
- Minification and compression
- Precache: All app shell assets (HTML, CSS, JS)
- Cache First: Static assets (images, fonts)
- Network First: API calls (future feature)
- Critical CSS inlined
- Lazy load non-critical components
- Optimize images (WebP with fallbacks)
- Minimize JavaScript bundle size
Targets:
- Initial load: < 3 seconds on 3G
- Time to interactive: < 5 seconds
- Bundle size: < 300KB gzipped
- All data stored locally on user's device
- No analytics or tracking by default
- Data export/import for portability
- Clear data deletion options
- TypeScript types at compile time
- Runtime validation for user inputs
- Sanitization of user-generated content
- HTTPS required for Service Worker
- Same-origin policy enforced
- Secure caching strategies
- ✅ PWA foundation
- ✅ Local data storage
- ✅ Responsive layout
- State management (Zustand or Context)
- Form validation library
- Component library expansion
- Routing (React Router)
- Optional cloud sync (SaaS layer)
- REST API integration
- Authentication system
- Multi-device sync
- Internationalization (i18n)
- Dark mode
- Advanced analytics
- Social features
- Follow Prettier configuration
- Use ESLint recommended rules
- Write meaningful commit messages
- Add TypeScript types for all functions
- One component per file
- Use functional components with hooks
- Props interface defined above component
- CSS modules or CSS-in-JS for styles
- Unit tests for business logic
- Integration tests for features
- E2E tests for critical paths
- Aim for >80% coverage