Skip to content

Project Structure

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 + formatting
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-breaker

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 /$slug redirects to /profesores/$slug via window.location.replace()
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 singleton
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-exports
packages/shared/src/
├── schemas/ # 33 Zod schema files
├── types/ # TypeScript type definitions
└── constants/ # Shared constants