Project Structure
Monorepo Layout
Section titled “Monorepo Layout”PinTeach is a Turborepo + Bun workspaces monorepo with 3 packages + 3 apps:
pinteach/├── apps/│ ├── api/ # Fastify backend (port 3001)│ ├── web/ # React SPA (port 3737)│ ├── pinteach-web/ # Astro SSR public site (port 3939)│ └── docs/ # This documentation site (Astro + Starlight)├── packages/│ ├── shared/ # Zod schemas + TypeScript types│ ├── db/ # Drizzle ORM + migrations│ └── email-templates/ # React Email (15 templates)├── turbo.json├── docker-compose.yml # PostgreSQL (5433) + Redis (6379)└── biome.json # Linting + formattingBackend (apps/api/)
Section titled “Backend (apps/api/)”apps/api/src/├── index.ts # Server entry + BullMQ workers init├── app.ts # Fastify factory (cors, cookie, rate-limit, auth)├── plugins/│ ├── auth.ts # Session auth plugin│ └── audit-context.ts # IP, UA, requestId decorator├── routes/│ ├── auth/ # Google OAuth, magic links, /me│ ├── public/ # Profiles, services, booking, reviews│ ├── student/ # Student portal│ ├── teacher/ # 34 sub-route files│ └── webhooks/ # Stripe webhook├── services/ # 56 business logic services│ ├── auth/ # google-oauth, magic-link, session│ ├── billing/ # credit-ledger, enrollment, stripe│ ├── google/ # calendar, drive, drive-copy│ ├── notifications/ # email sending│ ├── policy/ # contract, legal-document, policy-engine│ ├── privacy/ # GDPR export, erasure│ ├── reviews/ # review, review-request, review-settings│ ├── scheduling/ # session, slot-engine, availability, etc.│ ├── audit/ # audit-service│ └── teacher/ # dashboard, insights, payments, etc.├── jobs/ # 9 BullMQ workers└── lib/ # errors, env, rate-limiter, circuit-breakerPublic Site (apps/pinteach-web/)
Section titled “Public Site (apps/pinteach-web/)”Astro 5 SSR site for public-facing pages with full SEO (Open Graph, Schema.org, dynamic sitemap). Uses @astrojs/node adapter and Tailwind CSS 4. Zero client-side JavaScript — pure HTML + CSS.
apps/pinteach-web/src/├── pages/│ ├── profesores/│ │ ├── [slug].astro # Teacher profile (SSR, config-driven layout)│ │ └── index.astro # Teacher directory (filters + compatibility quiz)│ ├── index.astro # Placeholder landing│ ├── 404.astro # Not found│ ├── sitemap.xml.ts # Dynamic sitemap from API│ └── robots.txt.ts├── components/│ ├── BaseHead.astro # SEO meta tags, OG, Twitter, fonts│ ├── ProfileHead.astro # Schema.org structured data│ ├── Footer.astro│ ├── profile/ # 20 section components│ │ ├── HeroSection.astro # Avatar, name, SuperTutor, headline, bio│ │ ├── VideoSection.astro # YouTube/Vimeo embed│ │ ├── ServicesSection.astro # Grouped service cards + booking CTA│ │ ├── ReviewsSummary.astro # Stats + reviews + distribution bars│ │ ├── FaqSection.astro # Native <details>/<summary>│ │ └── ... # Specialties, Languages, Certs, Education, etc.│ └── directory/│ ├── TeacherCard.astro # Card for directory grid│ ├── CompatibilityQuiz.astro # 5-question quiz (HTML form, no JS)│ └── FilterSidebar.astro # Search, specialty, language, price filters├── layouts/│ └── BaseLayout.astro # HTML shell + head + footer├── lib/│ ├── api.ts # Server-side fetchApi<T>()│ ├── format.ts # formatPrice(), timeAgo()│ └── video.ts # getYouTubeEmbedUrl()├── types.ts # PublicTeacherProfile, DirectoryTeacher, etc.└── styles/ └── global.css # Tailwind CSS 4 @theme (same palette as web)Key details:
- Port: 3939 (api=3001, web=3737, docs=3838)
- Profile layout is config-driven via
normalizeLayout()from@pinteach/shared - Cache-Control:
public, s-maxage=300, stale-while-revalidate=600 - React SPA
/$slugredirects to/profesores/$slugviawindow.location.replace()
Frontend (apps/web/)
Section titled “Frontend (apps/web/)”apps/web/src/├── main.tsx├── router.tsx # 30 routes with lazy loading├── routes/│ ├── __root.tsx│ ├── auth/ # student-login, verify│ ├── public/ # booking, profile, services│ ├── student/ # student portal pages│ └── teacher/ # 14 teacher pages├── components/│ ├── ui/ # 25 reusable components│ ├── calendar/ # week-grid, event-detail, agenda│ ├── kanban/ # board, column, card (dnd-kit)│ ├── materials/ # Drive-style file browser (13 files)│ ├── reviews/ # review cards, forms, import│ ├── widgets/ # booking/storefront/reviews configs│ ├── storefront/ # public service cards, booking│ ├── services/ # service-wizard (3D picker)│ ├── command-palette/ # Cmd+K + shortcut help│ └── layout/ # teacher-sidebar├── hooks/│ ├── mutations/ # 11 optimistic mutation hooks│ └── ... # use-auth, use-theme, etc.└── lib/ ├── api.ts # Fetch wrapper ├── i18n.ts # react-i18next setup └── shortcuts/ # ShortcutRegistry singletonDatabase (packages/db/)
Section titled “Database (packages/db/)”packages/db/src/├── schema/ # 55 schema files (one per table)├── migrations/ # 56 SQL migrations (0000-0055)├── lib/│ └── soft-delete.ts # notDeleted() helper├── seed.ts # Development seed data└── index.ts # DB connection + re-exportsShared (packages/shared/)
Section titled “Shared (packages/shared/)”packages/shared/src/├── schemas/ # 33 Zod schema files├── types/ # TypeScript type definitions└── constants/ # Shared constants