Tech Stack — Current Implementation
Status: Canonical Last Updated: 2026-05-11 Verification: Run
grep -r "from " apps/frontend/package.jsonto verify versions
Related specs
- Data Model — The schema defined here underpins all tech decisions
- Booking Flow — Uses Convex queries and mutations
- Admin Dashboard — Staff auth and role-based access
- Public Pages — Frontend routing and components
Core Stack
| Layer | Technology | Version | Notes |
|---|---|---|---|
| Frontend | Next.js 16 | ^16.x | App Router, Turbopack |
| Styling | Tailwind CSS | v4 | CSS variables, tailwindcss-animate |
| Backend | Convex | ^1.37.x | PostgreSQL, real-time |
| Auth | Clerk | ^5.x | Staff auth, guest OAuth |
| i18n | paraglide-js | ^2.x | en + vi locales |
| Forms | React Hook Form + Zod | latest | Per-component validation |
| State | React localState + BookingContext | — | Booking uses convexQuery bindings |
| Icons | Lucide React | ^0.4.x | Never emoji |
| Animation | tailwindcss-animate | ^1.x | Fades, slides, zoom |
Package Locations
- Frontend:
apps/frontend/package.json - Backend (Convex):
packages/backend/package.json
Key Paths
apps/frontend/
├── app/
│ ├── [locale]/ # en, vi locales
│ │ ├── (landing)/ # Public pages
│ │ │ ├── page.tsx # Homepage
│ │ │ ├── about/
│ │ │ ├── artists/
│ │ │ ├── schedule/
│ │ │ ├── reviews/
│ │ │ ├── wall/
│ │ │ ├── experiences/ # french-mentalist, dinner-theater, our-evening
│ │ │ └── inquiry/ # contact, venue-rental, workshops, private-events, artist-proposal, host-an-event
│ │ └── dashboard/ # Admin/staff routes
│ │ ├── admin/ # Admin panel
│ │ ├── pos/ # POS views
│ │ ├── checkin/
│ │ ├── events/
│ │ ├── experiences/
│ │ ├── reservations/
│ │ ├── inquiries/
│ │ └── event-payments/
│ └── layout.tsx
├── components/
│ ├── booking/ # Booking flow components
│ ├── home/ # Homepage sections
│ ├── marketing/ # Landing page sections
│ ├── layout/ # Header, Footer
│ └── ui/ # shadcn/ui primitives
└── lib/
├── hooks/ # Custom hooks
├── utils/ # Utilities
├── data/ # Static data
└── schemas/ # Zod schemas
packages/backend/convex/
├── schema.ts # All tables
├── domains/ # Queries + mutations by domain
│ ├── experiences.ts
│ ├── events.ts
│ ├── reservations.ts
│ ├── addons.ts
│ ├── profiles.ts
│ ├── checkins.ts
│ ├── notifications.ts
│ ├── crm.ts
│ ├── forms.ts
│ ├── analytics.ts
│ ├── payments.ts
│ ├── minigames.ts
│ └── storage.ts
├── functions/
│ ├── events.ts
│ ├── eventReservations.ts
│ └── scheduled.ts
├── http/
│ ├── onepay.ts
│ ├── onepayReturn.ts
│ ├── tickets.ts
│ └── gift_card.ts
├── lib/
│ ├── auth.ts
│ ├── experiencesData.ts
│ ├── onepay/
│ └── env.ts
└── crons.tsConvex API Pattern
All frontend calls use api.domains.<domain>.<operation>:
import { useQuery, useMutation } from "convex/react";
import { api } from "~/convex/_generated/api";
// Queries
const experiences = useQuery(api.domains.experiences.listActive);
const upcomingEvents = useQuery(api.domains.events.upcomingForExperience, {
experienceId,
limit,
});
// Mutations
const createReservation = useMutation(api.domains.reservations.createPending);
const updateStatus = useMutation(api.domains.events.updateStatus);Design System
See apps/frontend/DESIGN.md for complete design tokens and component library.
Key tokens:
--color-gold: #c5a059— Primary brand--color-background: #0a0a0f— Dark background--color-foreground: #ededed— Body text--color-surface: #16161a— Card backgrounds