Architecture & Tech Stack
TimeTiles is built with a modern, scalable tech stack focused on developer experience, performance, and maintainability. This page provides an overview of our architectural decisions and the technologies that power the platform.
๐๏ธ Architecture Overview
TimeTiles follows a full-stack monorepo architecture with clear separation of concerns:
- Frontend: Next.js app with React for interactive data exploration
- Backend: Payload CMS providing both API and admin interface
- Database: PostgreSQL with PostGIS for spatial data management
- Build System: Turbo monorepo with shared UI components
โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ
โ Frontend โ โ Backend โ โ Database โ
โ โ โ โ โ โ
โ โข Next.js 15 โโโโโบโ โข Payload CMS โโโโโบโ โข PostgreSQL โ
โ โข React 19 โ โ โข Node.js โ โ โข PostGIS โ
โ โข TypeScript โ โ โข TypeScript โ โ โข Spatial Index โ
โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ
๐ ๏ธ Core Technologies
Frontend Framework
Next.js 15 with Turbopack
- Why: Full-stack React framework with excellent DX and performance
- Features: App Router, Server Components, Turbopack bundler for faster builds
- Usage: Powers the main web application and all user-facing interfaces
React 19
- Why: Latest React with improved concurrent features and server components
- Features: Enhanced Suspense, automatic batching, server components
- Usage: Component library for all UI elements
State Management
React Query (TanStack Query)
- Why: Intelligent server state management with automatic caching
- Features: Background refetching, request deduplication, optimistic updates
- Usage: All API calls, data fetching, and server state synchronization
- Location:
/apps/web/lib/hooks/use-events-queries.ts
Zustand
- Why: Lightweight client state management without boilerplate
- Features: Simple API, TypeScript support, devtools integration
- Usage: UI state (modals, filters, map bounds)
- Location:
/apps/web/lib/store.ts
nuqs (Next.js URL State)
- Why: URL-first state management for filters and navigation
- Features: Type-safe URL parameters, server/client sync
- Usage: Search filters, pagination, shareable URLs
- Location:
/apps/web/lib/filters.ts
Backend & CMS
Payload CMS 3
- Why: Headless CMS with excellent TypeScript support and admin UI
- Features: Auto-generated types, flexible collections, built-in auth
- Usage: Content management, API generation, admin interface
- Location:
/apps/web/payload.config.ts
PostgreSQL 17 + PostGIS 3.5
- Why: Robust relational database with advanced spatial capabilities
- Features: ACID compliance, spatial indexing, complex queries
- Usage: Primary data store, geospatial queries, event storage
- Setup: Automated via Docker with spatial extensions
Data Visualization
MapLibre GL JS
- Why: High-performance WebGL-based mapping library
- Features: Vector tiles, smooth interactions, clustering
- Usage: Interactive map visualization, event clustering
- Location:
/apps/web/components/clustered-map.tsx
Apache ECharts
- Why: Comprehensive charting library with React integration
- Features: Interactive charts, theming, responsive design
- Usage: Histogram charts, data analysis visualizations
- Location:
/apps/web/components/event-histogram.tsx
Development Tools
TypeScript
- Why: Type safety, better DX, catch errors at compile time
- Features: Strict mode, auto-generated Payload types
- Usage: Entire codebase with strict type checking
Turbo (Monorepo)
- Why: Fast, incremental builds and task orchestration
- Features: Parallel builds, intelligent caching, workspace management
- Usage: Build system for apps and packages
- Location:
/turbo.json
ESLint + Prettier
- Why: Consistent code style and quality enforcement
- Features: TypeScript-aware rules, auto-formatting
- Usage: Enforced via git hooks and CI
๐ Data Flow Architecture
Server State (React Query)
// Centralized data fetching with intelligent caching
const { data: events, isLoading } = useEventsListQuery(filters, bounds);
// Automatic request deduplication and background updates
// Cache keys: ['events', 'list', { filters, bounds, limit }]
Benefits:
- Automatic caching by filter combinations
- Background refetching without blocking UI
- Request deduplication across components
- Optimistic updates for mutations
Client State (Zustand)
// UI state management
const isFilterDrawerOpen = useUIStore((state) => state.ui.isFilterDrawerOpen);
const mapBounds = useUIStore((state) => state.ui.mapBounds);
URL State (nuqs)
// Shareable, type-safe URL parameters
const [catalog, setCatalog] = useQueryState("catalog", parseAsString);
const [datasets, setDatasets] = useQueryState("datasets", parseAsArrayOf(parseAsString));
๐ Data Processing Pipeline
Import System Flow
File Upload โ Parsing โ Coordinate Detection โ Geocoding โ Event Creation
โ โ โ โ โ
Validation Schema Location Google Maps Database
Analysis Detection / OSM APIs Storage
Technologies:
- CSV/Excel Parsing: Built-in Node.js libraries
- Geocoding: Google Maps API with OpenStreetMap fallback
- Progress Tracking: React Query polling with automatic termination
- Batch Processing: Queue-based system with Payload jobs
Real-time Updates
- Progress Polling: React Query automatically polls import progress
- Cache Invalidation: Smart invalidation when data changes
- Background Sync: Stale data refreshes without user intervention
๐จ UI Component Architecture
Design System
Tailwind CSS
- Why: Utility-first CSS with excellent DX and performance
- Features: JIT compilation, custom design tokens, responsive design
- Usage: All styling throughout the application
Shared UI Package (/packages/ui
)
- Why: Consistent components across the monorepo
- Features: Reusable components, theme system, TypeScript definitions
- Usage: Charts, buttons, forms, layout components
Theme Management
// Dark/light theme support with system preference detection
const { theme, setTheme } = useTheme();
๐งช Testing Strategy
Vitest
- Why: Fast, Vite-powered testing with excellent TypeScript support
- Usage: Unit tests, component tests, utility testing
- Location:
/apps/web/tests/
Playwright
- Why: Reliable end-to-end testing across browsers
- Usage: Integration tests, user workflow validation
- Location:
/apps/web/tests/e2e/
Testing Patterns:
- Unit: Individual functions and components
- Integration: API endpoints with test database
- E2E: Complete user workflows
๐ข Deployment & Infrastructure
Docker
- Why: Consistent environments and easy deployment
- Usage: PostgreSQL, development environment
- Location:
/docker-compose.yml
Make
- Why: Simple, cross-platform build automation
- Usage: Development shortcuts, database management
- Location:
/Makefile
๐ Performance Optimizations
Frontend Performance
- Turbopack: Next.js bundler for faster builds
- Server Components: Reduced JavaScript bundle size
- React Query Caching: Minimize redundant API calls
- Map Clustering: Efficient rendering of large datasets
- Debounced Interactions: Prevent excessive API calls during map panning
Database Performance
- PostGIS Indexing: Spatial indexes for fast geospatial queries
- Query Optimization: Efficient filtering and aggregation
- Connection Pooling: Managed by Payload CMS
Build Performance
- Turbo Caching: Incremental builds and task parallelization
- TypeScript Project References: Faster type checking
- Import Optimization: Tree shaking and code splitting
๐ Security & Data Privacy
- Input Validation: Comprehensive validation at API boundaries
- Rate Limiting: Public API protection
- SQL Injection Prevention: Parameterized queries via Payload
- CORS Configuration: Controlled cross-origin access
- File Upload Security: Type validation and size limits
๐ฏ Key Design Decisions
Why This Stack?
- Developer Experience: TypeScript everywhere, hot reloading, type safety
- Performance: React Query caching, PostGIS spatial indexing, Turbopack
- Scalability: Monorepo architecture, component reusability
- Maintainability: Strong typing, consistent patterns, automated testing
- User Experience: Real-time updates, smooth interactions, responsive design
Trade-offs Made
- Complexity vs Features: Rich feature set requires sophisticated state management
- Bundle Size vs Functionality: Comprehensive mapping and charting libraries
- Learning Curve vs Productivity: Advanced patterns for better long-term maintenance
๐ Further Reading
- TanStack Query Documentation (opens in a new tab)
- Payload CMS Documentation (opens in a new tab)
- Next.js App Router (opens in a new tab)
- PostGIS Documentation (opens in a new tab)
- MapLibre GL JS (opens in a new tab)
๐ง Local Development Setup
For detailed setup instructions, see Getting Started.