Appearance
🔄 Synced from
castyou-frontend/docs/ARCHITECTURE.md— edit it there, not here.
CastYou Frontend — Architecture
Overview
The CastYou frontend is a pnpm monorepo managed with Turborepo. It contains two apps and a shared design system package.
castyou-frontend/
├── apps/
│ ├── landing/ # Next.js 15 (App Router) — public marketing site
│ └── app/ # React 18 + Vite — authenticated product app
└── packages/
├── design-system/ # Tailwind + Radix UI component library
└── tsconfig/ # Shared TypeScript configurationsApps
@castyou/landing — Next.js 15 (App Router)
The public-facing marketing site at castyou.app (and www.castyou.app). Responsibilities:
- SEO-optimised landing pages (SSR/SSG)
- Sign-up funnels directing users to
i.castyou.app - Blog, pricing, about pages
- Social sharing and OG metadata
Port: 3002
@castyou/app — React 18 + Vite + React Query
The authenticated product application at i.castyou.app. Responsibilities:
- Talent / producer dashboards
- Discover feed (AI-powered talent cards with swipe UX)
- Job posting and management
- Profile editor
- Demo reel builder
- Group management
Port: 3001
Packages
@castyou/design-system
The single source of truth for all UI. Both apps import from here — no local component duplication.
Contents:
- Tokens (
src/tokens/) — colors, spacing, typography, radius as TypeScript constants + Tailwind config extension - Components (
src/components/ui/) — Button, Input, Badge, Card, Avatar, and more - Utilities (
src/utils/cn.ts) —cn()helper mergingclsx+tailwind-merge - Tailwind config (
tailwind.config.ts) — extends base config; consumer apps spread this and add their owncontentpaths
Consumers use it via workspace protocol:
json
"@castyou/design-system": "workspace:*"@castyou/tsconfig
Shared TypeScript base config (base.json) extended by all apps and packages to ensure consistent compiler settings.
Tech Stack
| Concern | Choice | Reason |
|---|---|---|
| Monorepo tooling | pnpm workspaces + Turborepo | Fast installs, parallel task pipelines, build caching |
| Landing | Next.js 15 App Router | SSR/SSG for SEO; React Server Components |
| App | React 18 + Vite | Fast HMR, SPA suited for rich interactive dashboard |
| Data fetching | TanStack Query v5 | Server-state management, caching, background refetch |
| GraphQL client | graphql-request | Lightweight; pairs naturally with React Query |
| State (client) | Zustand | Minimal global state (auth, UI preferences) |
| Routing (app) | React Router v6 | Client-side routing with lazy-loaded routes |
| Styling | Tailwind CSS v3 | Utility-first; shared via design-system package |
| Components | Radix UI primitives | Accessible headless components wrapped by design-system |
| Form variants | class-variance-authority | Type-safe variant API for design-system components |
Data Flow (App)
User interaction
→ React component (page or feature component)
→ useQuery / useMutation (TanStack Query)
→ gqlClient.request() (graphql-request)
→ CastYou Backend GraphQL API
→ Response cached in QueryClient
→ Component re-renders with fresh dataGlobal state (auth tokens, user session) lives in Zustand (src/stores/auth.ts). Server state lives in React Query cache — never duplicated in Zustand.
Authentication Flow (App)
- User submits login form →
Mutation.loginresolves on backend accessTokenstored inlocalStorage(key:castyou_access_token); user object persisted in ZustandgqlClientreads the token fromlocalStorageon every request via a dynamic headers functionProtectedRouteinApp.tsxredirects unauthenticated users to/login- On token expiry, the 401 response triggers a token refresh or redirects to login
Adding a New Page (App)
- Create
src/pages/<domain>/<PageName>.tsx - Add a lazy import and
<Route>insrc/App.tsx - Add any GraphQL queries/mutations to
src/lib/queries/<domain>.ts - Wrap data fetching in a custom hook
src/hooks/use<Domain>.ts
Adding a New Design System Component
- Create
packages/design-system/src/components/ui/<Component>.tsx - Export it from
packages/design-system/src/index.ts - Both apps get it immediately via the workspace symlink
Build Pipeline (Turborepo)
turbo build
→ @castyou/tsconfig (no-op, config only)
→ @castyou/design-system (tsc typecheck)
→ @castyou/landing (next build) ─┐ parallel
→ @castyou/app (vite build) ─┘turbo.json declares "dependsOn": ["^build"] so packages always build before the apps that consume them.