ArchitectureMonorepo Structure

Monorepo Structure

A detailed look at the monorepo organization and package relationships.

Repository Layout

uwdsc-website-v3/
β”œβ”€β”€ .github/                # GitHub Actions
β”œβ”€β”€ apps/                   # Frontend applications
β”‚   β”œβ”€β”€ web/                # Main website and member applications
β”‚   β”œβ”€β”€ admin/              # Admin dashboard and CXC application/review
β”‚   └── docs/               # Documentation site
β”œβ”€β”€ packages/               # Shared packages
β”‚   β”œβ”€β”€ ui/                 # Design system (@uwdsc/ui)
β”‚   β”œβ”€β”€ common/             # Shared types and utils (@uwdsc/common)
β”‚   β”œβ”€β”€ server/             # Backend
β”‚   β”‚   β”œβ”€β”€ db/            # @uwdsc/db - Postgres, Supabase, BaseRepository, migrations
β”‚   β”‚   β”œβ”€β”€ core/          # @uwdsc/core - Shared services
β”‚   β”‚   └── admin/         # @uwdsc/admin - Admin-only services
β”‚   β”œβ”€β”€ eslint-config/      # ESLint configuration
β”‚   └── typescript-config/  # TypeScript configuration
β”œβ”€β”€ scripts/                # Tool scripts (migrate, ui-add, pull-secrets)
β”œβ”€β”€ package.json            # Root package configuration
β”œβ”€β”€ pnpm-workspace.yaml     # Workspace configuration
└── turbo.json              # Turborepo configuration

Apps

apps/web - Main Website

The primary UW Data Science Club website.

Purpose: Public-facing website with events, team info, and membership applications

Tech Stack:

  • Next.js 16 (App Router)
  • React 19
  • TypeScript
  • Tailwind CSS

Key Features:

  • Home page with events showcase
  • Team directory
  • Membership application system
  • Calendar integration
  • User authentication

Structure:

apps/web/
β”œβ”€β”€ app/                 # Next.js App Router
β”‚   β”œβ”€β”€ api/             # API routes
β”‚   β”œβ”€β”€ (auth)/          # Auth pages (login, register, etc.)
β”‚   β”œβ”€β”€ apply/           # Member application flow
β”‚   β”œβ”€β”€ calendar/        # Calendar page
β”‚   β”œβ”€β”€ passport/        # Member passport
β”‚   β”œβ”€β”€ team/            # Team directory
β”‚   β”œβ”€β”€ layout.tsx
β”‚   └── page.tsx         # Home
β”œβ”€β”€ components/          # React components
β”œβ”€β”€ constants/           # App constants
β”œβ”€β”€ contexts/           # React contexts
β”œβ”€β”€ hooks/               # React hooks
β”œβ”€β”€ lib/                 # Utilities, API client, services
β”œβ”€β”€ providers/           # React providers
└── public/              # Static assets

apps/admin - Admin App

Admin dashboard and CXC (AI hackathon) application and review system.

Purpose: Admin-only features: member management, CXC applications table, review interface, superadmin dashboard and leaderboard

Tech Stack: Next.js 16, React 19, TypeScript, Tailwind, @uwdsc/ui, @uwdsc/core, @uwdsc/admin, @uwdsc/db

Key Features:

  • Member listing and management
  • CXC application submissions table and details
  • Review interface with scoring
  • Superadmin dashboard (analytics, RSVP timeline) and review leaderboard

Structure:

apps/admin/
β”œβ”€β”€ app/                 # Next.js App Router
β”‚   β”œβ”€β”€ (admin)/         # Admin dashboard, applications, review, leaderboard
β”‚   β”œβ”€β”€ api/             # API routes
β”‚   β”œβ”€β”€ login/           # Login page
β”‚   └── unauthorized/    # Unauthorized page
β”œβ”€β”€ components/          # React components
β”œβ”€β”€ contexts/           # React contexts
β”œβ”€β”€ hooks/               # React hooks
β”œβ”€β”€ lib/                 # Utilities, API client, services
└── providers/           # React providers

apps/docs - Documentation

This documentation site.

Purpose: Developer documentation and guides

Tech Stack: Next.js 15 (Nextra-compatible), Nextra, MDX

Structure:

apps/docs/
β”œβ”€β”€ pages/               # Nextra/Pages Router (MDX docs)
β”‚   β”œβ”€β”€ architecture/
β”‚   β”œβ”€β”€ changelog/
β”‚   β”œβ”€β”€ guides/
β”‚   β”œβ”€β”€ packages/
β”‚   β”œβ”€β”€ _meta.js         # Section navigation
β”‚   └── ...
└── public/              # Static assets

Packages

packages/ui - Design System

Shared UI components built with shadcn/ui.

Exports: @uwdsc/ui

Contents:

  • Button, Card, Input, Select
  • Navigation Menu, Tabs
  • Dialog, Dropdown, Popover
  • Avatar, Badge, Progress
  • And more shadcn components

Dependencies: Radix UI primitives, Tailwind CSS, Framer Motion, Lucide React icons

Structure:

packages/ui/
└── src/
    β”œβ”€β”€ components/      # shadcn/ui components
    β”œβ”€β”€ hooks/           # useToast, useMobile, etc.
    β”œβ”€β”€ lib/             # utils (cn, etc.)
    └── styles/          # globals.css

packages/server/db - Database & Supabase (@uwdsc/db)

Database connection, Supabase clients, and base repository.

Exports: @uwdsc/db, @uwdsc/db/connection, @uwdsc/db/supabase, @uwdsc/db/baseRepository

Contents:

  • Postgres connection (postgres.js, Supabase Transaction Pooler)
  • createSupabaseBrowserClient, createSupabaseServerClient, createSupabaseMiddlewareClient
  • BaseRepository abstract class (repositories extend this and use protected sql)
  • Migrations (db-migrate; SQL files in src/migrations/)

Structure:

packages/server/db/
└── src/
    β”œβ”€β”€ config/          # connection.ts, supabase.ts, baseRepository.ts
    └── migrations/      # db-migrate SQL and runner

Run migrations from root: pnpm migrate, pnpm migrate:down, pnpm migrate:create, etc.

packages/server/core - Shared Backend (@uwdsc/core)

Shared services and repositories used by web and admin apps.

Exports: @uwdsc/core β€” service classes and singletons: profileService, applicationService, teamService; AuthService, ResumeService (create per-request in app lib/services.ts via createAuthService() / createResumeService())

Contents:

  • AuthService, ProfileService, ApplicationService, FileService, ResumeService, TeamService
  • Repositories (ProfileRepository, ApplicationRepository, AuthRepository, etc.) extending BaseRepository from @uwdsc/db
  • Types and utilities

Structure:

packages/server/core/
└── src/
    β”œβ”€β”€ repositories/    # ProfileRepository, ApplicationRepository, etc.
    β”œβ”€β”€ services/        # Auth, Profile, Application, File, Resume, Team
    └── utils/           # Shared utilities

Dependencies: @uwdsc/db, @uwdsc/common

packages/server/admin - Admin Backend (@uwdsc/admin)

Admin-only services (e.g. profile/member management for admin dashboard).

Exports: @uwdsc/admin β€” e.g. profileService for member listing/updates

Used by: apps/admin API routes only

Dependencies: @uwdsc/core, @uwdsc/db, @uwdsc/common

Structure:

packages/server/admin/
└── src/
    β”œβ”€β”€ repositories/    # Admin-specific data access
    └── services/       # Admin profile/member services

packages/eslint-config

Shared ESLint configuration.

Exports:

  • @uwdsc/eslint-config/base
  • @uwdsc/eslint-config/next
  • @uwdsc/eslint-config/react-internal

Purpose: Consistent code style across all packages

packages/typescript-config

Shared TypeScript configuration.

Exports:

  • @uwdsc/typescript-config/base.json
  • @uwdsc/typescript-config/nextjs.json
  • @uwdsc/typescript-config/react-library.json

Purpose: Consistent TypeScript settings

Workspace Configuration

pnpm-workspace.yaml

Defines which directories are part of the workspace:

packages:
  - "apps/*"
  - "packages/*"
  - "packages/server/*"

turbo.json

Configures Turborepo tasks (build order, caching, env):

{
  "tasks": {
    "build": {
      "dependsOn": ["^build"],
      "inputs": ["$TURBO_DEFAULT$", ".env*"],
      "outputs": [".next/**", "!.next/cache/**"]
    },
    "dev": { "cache": false, "persistent": true },
    "lint": { "dependsOn": ["^lint"] },
    "check-types": { "dependsOn": ["^check-types"] }
  }
}

Dependency Management

Internal Dependencies

Packages reference each other using workspace protocol:

{
  "dependencies": {
    "@uwdsc/ui": "workspace:*",
    "@uwdsc/core": "workspace:*",
    "@uwdsc/db": "workspace:*"
  }
}

Shared Dependencies

Common dependencies are installed once at the root:

  • React, Next.js
  • TypeScript
  • Tailwind CSS
  • ESLint, Prettier

App-Specific Dependencies

Apps can have their own unique dependencies:

  • apps/web: e.g. SWR, react-feather, babel-plugin-react-compiler
  • apps/admin: e.g. @tanstack/react-table, sonner

Build Order

Turborepo automatically determines build order:

  1. Config packages (eslint-config, typescript-config)
  2. packages/common (shared types/utils)
  3. packages/ui (design system)
  4. packages/server/db (connection, BaseRepository, migrations)
  5. packages/server/core (depends on db, common)
  6. packages/server/admin (depends on core, db, common)
  7. Apps (depend on ui, core, and optionally admin/db)

Import Paths

In Apps

// UI components
import { Button, Card } from "@uwdsc/ui";
 
// Shared backend (web and admin)
import { profileService, applicationService } from "@uwdsc/core";
import { createAuthService, createResumeService } from "@/lib/services"; // uses @uwdsc/db + @uwdsc/core
 
// Admin-only (admin app API routes)
import { profileService } from "@uwdsc/admin";
 
// Database / Supabase (when creating services)
import { createSupabaseServerClient } from "@uwdsc/db";

In Packages

// In @uwdsc/core or @uwdsc/admin
import { BaseRepository } from "@uwdsc/db/baseRepository";
import { sql } from "@uwdsc/db/connection";

Adding New Packages

1. Create Package Directory

mkdir -p packages/my-package/src
cd packages/my-package

2. Initialize package.json

{
  "name": "@uwdsc/my-package",
  "version": "0.0.1",
  "private": true,
  "main": "./src/index.ts",
  "types": "./src/index.ts"
}

3. Add to Dependencies

In consuming package/app:

{
  "dependencies": {
    "@uwdsc/my-package": "workspace:*"
  }
}

4. Install and Build

pnpm install
pnpm build

Best Practices

βœ… Do

  • Keep packages focused and single-purpose
  • Use workspace protocol for internal dependencies
  • Follow the dependency direction (apps β†’ packages)
  • Share common code in appropriate packages
  • Use TypeScript for type safety

❌ Don’t

  • Create circular dependencies
  • Have packages depend on apps
  • Duplicate code across packages
  • Mix different concerns in one package

Next Steps