Appearance
Monorepo Structure
Overview
Jubiloop uses Turborepo to manage its monorepo structure, enabling efficient code sharing, consistent tooling, and optimized build pipelines across all applications and packages.
Project Structure
jubiloop/
├── apps/ # Application workspaces
│ ├── server/ # AdonisJS API backend
│ ├── webapp/ # React frontend webapp
│ ├── marketing/ # Next.js marketing website
│ └── ui-prototype/ # React design prototype (lab.jubiloop.localhost)
├── packages/ # Shared packages
│ ├── auth-client/ # Auth & org client (Better Auth + TanStack Query hooks)
│ ├── eslint-config/ # Shared ESLint configuration
│ ├── logger/ # @jubiloop/logger — Structured logging, adaptor pattern
│ ├── shared-types/ # Shared API envelopes and error-code constants
│ ├── typescript-config/ # Shared TypeScript configuration
│ ├── ui/ # Shared UI components library
│ └── vitest-config/ # Shared Vitest testing configuration
├── infra/ # Infrastructure configurations
│ ├── local_dev/ # Local development setup
│ └── deploy/ # Deployment configurations
├── docs/ # Documentation
├── playwright-framework/ # Cross-app Playwright browser tests
└── turbo.json # Turborepo configurationDirectory Explanations
Applications (/apps)
The apps directory contains all deployable applications in the monorepo:
Server (/apps/server)
- Purpose: Backend API server providing all business logic and data management
- Framework: AdonisJS with TypeScript
- Key Features:
- RESTful API endpoints
- Authentication and authorization
- Database migrations and models
- Rate-limited HTTP routes
- Structure:
server/ ├── app/ │ ├── controllers/ # Request handlers │ ├── models/ # Database models │ ├── middleware/ # HTTP middleware │ └── validators/ # Input validation ├── config/ # Application configuration ├── database/ │ ├── migrations/ # Database migrations │ └── seeders/ # Database seeders └── start/ # Application bootstrap files
Web Application (/apps/webapp)
- Purpose: Main user-facing web application
- Framework: React with Vite
- Key Features:
- Single-page application (SPA)
- Type-safe routing with TanStack Router
- Better Auth and TanStack Query-backed server state
- API integration with TanStack Query
- App-owned
globals.csswrapper and Tailwind source scan - Tailwind processing through the shared UI PostCSS configuration
- Structure:
webapp/ ├── src/ │ ├── components/ # React components │ ├── routes/ # Application routes │ ├── hooks/ # Custom React hooks │ ├── contexts/ # App-level React contexts │ ├── lib/api/ # Auth setup and Tuyau clients │ └── utils/ # Utility functions └── public/ # Static assets
Marketing Site (/apps/marketing)
- Purpose: Public-facing marketing website
- Framework: Next.js with TypeScript
- Key Features:
- Next.js server and static rendering through OpenNext
- SEO optimization
- Blog/content management
- App-owned
globals.csswrapper and Tailwind source scan - Tailwind processing through the shared UI PostCSS configuration
- Structure:
marketing/ ├── src/ │ ├── app/ # Next.js App Router │ ├── components/ # React components │ └── utils/ # Utility functions ├── src/sanity/ # Sanity schemas, queries, and client └── public/ # Static assets
Browser Tests (/playwright-framework)
- Purpose: Cross-app browser regression and visual behavior checks
- Framework: Playwright
- Key Features:
- Authenticated and public user flows
- Shared fixtures, page objects, and route mocks
- A typography project for local font origins and blocked-font responsive reflow
- Targeted command:
pnpm --filter @jubiloop/playwright-framework test --project=typography
Shared Packages (/packages)
The packages directory contains shared code and configurations used across applications:
ESLint Config (/packages/eslint-config)
- Centralized ESLint rules and configurations
- Ensures consistent code style across all applications
- Extends popular configs with custom rules
TypeScript Config (/packages/typescript-config)
- Shared TypeScript compiler configurations
- Different configs for different environments:
base.json: Common settingsnextjs.json: Next.js application settingsreact-library.json: React library settings
Auth Client (/packages/auth-client)
- Authentication and organization client for frontend apps
- Wraps Better Auth with TanStack Query hooks
- Handles: sign-in/up/out, session management, organization CRUD, member management
- General API calls (events, health, etc.) use Tuyau — not this package
- Features:
- Better Auth client factory with organization plugin
- Pre-configured TanStack Query hooks for auth and org operations
- Cache-first session queries for route guards
- Centralized query keys (
defaultQueryKeys) - TypeScript interfaces for type safety
UI Package (/packages/ui)
- Shared component library using shadcn/ui
- Semantic design tokens, Tailwind mappings, base rules, and shared utilities
- Public stylesheet and PostCSS configuration exports
- Style contract validation for tokens, contrast, source boundaries, and exports
- Common UI utilities and helpers
- Benefits:
- Consistent design system
- Reduced duplication
- Centralized component updates
Vitest Config (/packages/vitest-config)
- Shared testing configuration
- Common test utilities and helpers
- Consistent testing patterns
Infrastructure (/infra)
Local Development (/infra/local_dev)
- Docker Compose setup for local services
- Includes PostgreSQL, Redis, and Caddy
- HTTPS certificate generation scripts
- Simplified local environment setup
Deployment (/infra/deploy)
- Production deployment configurations
- Terraform infrastructure as code
- Ansible playbooks for server configuration
- GitHub Actions workflows
- Environment management scripts
Documentation (/docs)
- Architecture documentation
- API documentation
- Development guides
- Deployment procedures
How the Monorepo is Organized
Workspace Management
The monorepo uses pnpm workspaces as defined in pnpm-workspace.yaml:
yaml
packages:
- 'apps/*'
- 'packages/*'
- 'playwright-framework'
- 'docs'This configuration makes the apps, shared packages, browser tests, and VitePress site addressable through pnpm filters and the workspace protocol.
Dependency Management
Internal Dependencies: Packages can depend on each other
json{ "dependencies": { "@jubiloop/ui": "workspace:*", "@jubiloop/eslint-config": "workspace:*" } }External Dependencies: Managed at workspace level
- Shared versions are centralized in the
catalog:section ofpnpm-workspace.yaml pnpm-lock.yamlrecords the resolved dependency graph
- Shared versions are centralized in the
Build Pipeline
Turborepo manages the build pipeline with:
- Task orchestration: Defines task dependencies
- Intelligent caching: Skips unchanged builds
- Parallel execution: Runs independent tasks concurrently
Example turbo.json configuration:
json
{
"tasks": {
"build": {
"dependsOn": ["^build"],
"inputs": ["$TURBO_DEFAULT$", ".env*"],
"outputs": [".next/**", "!.next/cache/**", "dist/**", "build/**"]
},
"dev": {
"cache": false,
"persistent": true
},
"test": {
"dependsOn": ["transit", "@jubiloop/vitest-config#build"],
"outputs": ["coverage.json"]
},
"transit": {
"dependsOn": ["^transit"]
}
}
}Turborepo Benefits
1. Incremental Builds
- Only rebuilds what has changed
- Caches build outputs
- Dramatically faster CI/CD pipelines
2. Task Scheduling
- Understands task dependencies
- Runs tasks in optimal order
- Maximizes parallelization
3. Remote Caching
- Share build cache across team
- Faster onboarding for new developers
- Reduced CI/CD costs
4. Dependency Graph Awareness
- Understands package relationships
- Runs affected tests only
- Prevents circular dependencies
5. Developer Experience
- Single command to run all apps:
pnpm run dev - Consistent tooling across projects
- Simplified configuration management
6. Code Sharing
- Share types between frontend and backend
- Reuse UI components across apps
- Centralized business logic
7. Atomic Changes
- Change API and client in same commit
- Ensure compatibility across apps
- Simplified code reviews
Best Practices
1. Package Organization
- Keep packages focused and single-purpose
- Document package APIs clearly
- Version internal packages together
2. Dependency Management
- Minimize external dependencies
- Keep shared dependencies at root
- Use workspace protocol for internal deps
3. Build Optimization
- Configure proper cache outputs
- Use cache-friendly file structures
- Leverage remote caching in CI/CD
4. Development Workflow
- Use filters to work on specific apps:
pnpm --filter webapp dev - Run targeted tests:
pnpm exec turbo test --filter=server - Smoke-test the source-consumed UI stylesheet:
pnpm --filter @jubiloop/ui test
5. Code Sharing Guidelines
- Share types and interfaces liberally
- Be cautious with shared business logic
- Keep UI components generic and configurable
Common Commands
bash
# Development
pnpm run dev # Start all applications
pnpm --filter webapp dev # Start the webapp only
pnpm --filter marketing dev # Start the marketing site only
# Building
pnpm run build # Build everything
pnpm exec turbo build --filter=server # Build specific app
pnpm exec turbo build --filter=...webapp # Build app and dependencies
# Testing
pnpm run test # Run all tests
pnpm --filter @jubiloop/playwright-framework test --project=typography
pnpm exec turbo test --affected # Test affected by changes
# Maintenance
pnpm install # Install all dependencies
pnpm exec turbo prune webapp # Extract app for deploymentRelated Documentation
- Architecture Overview - High-level system architecture
- Getting Started - Setup instructions
- Development Guide - Development workflow