> ## Documentation Index
> Fetch the complete documentation index at: https://docs.8space.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Monorepo Structure

> Workspace organization and package architecture

8Space uses npm workspaces to manage a monorepo with two main packages: the landing page and the core application.

## Root Configuration

```json packages/package.json theme={null}
{
  "name": "8space-monorepo",
  "private": true,
  "workspaces": [
    "packages/*"
  ],
  "scripts": {
    "dev": "node scripts/dev-all.mjs",
    "dev:all": "node scripts/dev-all.mjs",
    "dev:landing": "npm run dev -w packages/landing",
    "dev:app": "npm run dev -w packages/app",
    "build:landing": "npm run build -w packages/landing",
    "build:app": "npm run build -w packages/app"
  }
}
```

## Package Overview

<CardGroup cols={2}>
  <Card title="packages/landing" icon="globe">
    Marketing site built with Next.js 15

    **Tech Stack:**

    * Next.js 15.5.9 with App Router
    * React 19
    * Tailwind CSS + DaisyUI
    * MDX for content pages
    * Supabase Auth integration
  </Card>

  <Card title="packages/app" icon="grid-2">
    Main SaaS application built with Vite

    **Tech Stack:**

    * React 19 with TypeScript
    * Vite 7 for build tooling
    * TanStack Query for data fetching
    * Radix UI primitives
    * Supabase client
  </Card>
</CardGroup>

## Application Structure

<Tabs>
  <Tab title="packages/app">
    ```
    packages/app/
    ├── src/
    │   ├── components/
    │   │   ├── app/          # Application-specific components
    │   │   ├── auth/         # Authentication components
    │   │   └── ui/           # Reusable UI components
    │   ├── domain/
    │   │   ├── repositories/ # Repository pattern implementations
    │   │   │   ├── interfaces.ts   # Repository interfaces
    │   │   │   ├── supabase.ts     # Supabase implementation
    │   │   │   └── index.ts
    │   │   └── types.ts      # Domain types and interfaces
    │   ├── hooks/            # React hooks
    │   ├── integrations/
    │   │   └── supabase/     # Supabase client configuration
    │   ├── lib/              # Utility libraries
    │   ├── utils/            # Helper functions
    │   └── views/            # Page-level components
    ├── supabase/
    │   └── migrations/       # Database migrations (SQL)
    ├── package.json
    ├── vite.config.ts
    └── tsconfig.json
    ```
  </Tab>

  <Tab title="packages/landing">
    ```
    packages/landing/
    ├── app/                  # Next.js App Router
    │   ├── (marketing)/      # Marketing pages
    │   ├── api/              # API routes
    │   └── layout.tsx
    ├── components/
    │   ├── ui/               # UI components
    │   └── sections/         # Page sections
    ├── lib/                  # Utilities
    ├── public/               # Static assets
    ├── styles/
    ├── package.json
    ├── next.config.mjs
    └── tsconfig.json
    ```
  </Tab>

  <Tab title="Database">
    ```
    packages/app/supabase/migrations/
    ├── 20260212220000_init_gantt_mvp.sql
    ├── 20260213220000_auto_join_new_users.sql
    ├── 20260213220100_handle_new_user_google_compat.sql
    ├── 20260216220000_fix_create_project_trigger_conflict.sql
    └── 20260217143000_multi_tenant_onboarding.sql
    ```
  </Tab>
</Tabs>

## Domain Layer Architecture

The `packages/app/src/domain/` directory contains the core business logic:

### Repository Interfaces

```typescript packages/app/src/domain/repositories/interfaces.ts theme={null}
export interface TenantRepository {
  listTenants(userId: string): Promise<Tenant[]>;
  createTenantWithOwner(name: string, preferredSlug?: string): Promise<Tenant>;
}

export interface ProjectRepository {
  listProjects(userId: string, tenantSlug: string): Promise<Project[]>;
  createProjectWithDefaults(tenantSlug: string, input: CreateProjectInput): Promise<Project>;
  getProjectMembers(projectId: string): Promise<ProjectMember[]>;
  listWorkflowColumns(projectId: string): Promise<WorkflowColumn[]>;
  updateProjectSettings(projectId: string, input: Pick<Project, 'name' | 'description'>): Promise<Project>;
}

export interface TaskRepository {
  listTasks(projectId: string): Promise<Task[]>;
  listDependencies(projectId: string): Promise<TaskDependency[]>;
  createTask(input: CreateTaskInput): Promise<Task>;
  updateTaskInline(input: UpdateTaskInlineInput): Promise<Task>;
  moveTask(taskId: string, toColumnId: string, newRank: number): Promise<Task>;
  reorderTasks(projectId: string, orderedTaskIds: string[]): Promise<void>;
  setTaskDependencies(projectId: string, successorTaskId: string, predecessorTaskIds: string[], type?: DependencyType): Promise<void>;
  deleteTask(taskId: string): Promise<void>;
}

export interface DashboardRepository {
  getProjectMetrics(projectId: string, rangeDays: number): Promise<ProjectMetrics>;
}
```

### Type System

<Tip>
  All domain types are defined in `packages/app/src/domain/types.ts` to ensure consistency across the application.
</Tip>

```typescript packages/app/src/domain/types.ts theme={null}
export type ProjectRole = 'owner' | 'editor' | 'viewer';
export type TenantRole = 'owner' | 'admin' | 'member';
export type TaskPriority = 'p0' | 'p1' | 'p2';
export type WorkflowColumnKind = 'backlog' | 'todo' | 'in_progress' | 'done' | 'custom';
export type DependencyType = 'FS';

export interface Project {
  id: string;
  tenantId: string;
  name: string;
  description?: string | null;
  createdBy: string;
  createdAt: string;
  archivedAt?: string | null;
  role: ProjectRole;
}

export interface Task {
  id: string;
  projectId: string;
  title: string;
  statusColumnId: string;
  assignees: UserProfile[];
  dueDate?: string | null;
  startDate?: string | null;
  priority: TaskPriority;
  orderRank: number;
  description?: string | null;
  tags: TaskLabel[];
  checklist: TaskChecklistItem[];
  attachments: TaskAttachment[];
  estimate?: number | null;
  completedAt?: string | null;
  isMilestone: boolean;
  createdAt: string;
  updatedAt: string;
}
```

## Component Organization

### Application Components

Located in `packages/app/src/components/app/`:

* Kanban board components
* Gantt chart components
* Task detail panels
* Project settings
* Team management

### UI Components

Located in `packages/app/src/components/ui/`:

* Button, Input, Dialog (Radix UI wrappers)
* Form components
* Layout components
* Theme-aware components with `next-themes`

### Authentication Components

Located in `packages/app/src/components/auth/`:

* Login/signup forms
* OAuth provider buttons
* Protected route wrappers

## Dependency Management

<AccordionGroup>
  <Accordion title="Shared Dependencies">
    Both packages share common dependencies:

    ```json theme={null}
    "@supabase/supabase-js": "^2.95.3"
    "@radix-ui/react-slot": "^1.2.4"
    "tailwind-merge": "^3.4.0"
    "class-variance-authority": "^0.7.1"
    "clsx": "^2.1.1"
    ```

    These are installed at the workspace root and shared across packages.
  </Accordion>

  <Accordion title="App-Specific Dependencies">
    ```json packages/app/package.json theme={null}
    "@tanstack/react-query": "^5.90.21"
    "@tanstack/react-query-devtools": "^5.91.3"
    "@dnd-kit/core": "^6.3.1"
    "@dnd-kit/sortable": "^10.0.0"
    "date-fns": "^4.1.0"
    "react-router-dom": "^7.13.0"
    ```
  </Accordion>

  <Accordion title="Landing-Specific Dependencies">
    ```json packages/landing/package.json theme={null}
    "next": "15.5.9"
    "@mdx-js/loader": "^2.3.0"
    "@mdx-js/react": "^2.3.0"
    "framer-motion": "^12.34.0"
    "stripe": "^13.11.0"
    "resend": "^6.0.0"
    ```
  </Accordion>
</AccordionGroup>

## Build Configuration

### Vite Configuration (App)

The main application uses Vite for fast development and optimized production builds:

```typescript packages/app/vite.config.ts theme={null}
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import path from 'path'

export default defineConfig({
  plugins: [react()],
  resolve: {
    alias: {
      '@': path.resolve(__dirname, './src'),
    },
  },
})
```

### Next.js Configuration (Landing)

The landing page uses Next.js with MDX support:

```javascript packages/landing/next.config.mjs theme={null}
import createMDX from '@next/mdx'

const withMDX = createMDX({
  extension: /\.mdx?$/,
})

export default withMDX({
  pageExtensions: ['js', 'jsx', 'ts', 'tsx', 'md', 'mdx'],
})
```

## Development Scripts

<CodeGroup>
  ```bash Development theme={null}
  # Start all services
  npm run dev

  # Start individual packages
  npm run dev:app
  npm run dev:landing
  ```

  ```bash Production Build theme={null}
  # Build all packages
  npm run build:app
  npm run build:landing
  ```

  ```bash Workspace Commands theme={null}
  # Install dependency in specific workspace
  npm install <package> -w packages/app

  # Run script in specific workspace
  npm run <script> -w packages/landing
  ```
</CodeGroup>

## Migration Management

Database migrations are stored in `packages/app/supabase/migrations/` with timestamp-based naming:

```
[YYYYMMDDHHMMSS]_[description].sql
```

<Steps>
  <Step title="Create Migration">
    ```bash theme={null}
    supabase migration new <description>
    ```
  </Step>

  <Step title="Write SQL">
    Add table definitions, functions, and policies
  </Step>

  <Step title="Apply Locally">
    ```bash theme={null}
    supabase db reset
    ```
  </Step>

  <Step title="Deploy">
    ```bash theme={null}
    supabase db push
    ```
  </Step>
</Steps>

## Best Practices

<CardGroup cols={2}>
  <Card title="Type Safety" icon="shield-check">
    * Use TypeScript strict mode
    * Define types in `domain/types.ts`
    * Generate types from database schema
  </Card>

  <Card title="Code Organization" icon="folder-tree">
    * Keep domain logic in `domain/`
    * Separate UI from business logic
    * Use repository pattern for data access
  </Card>

  <Card title="State Management" icon="rotate">
    * Use TanStack Query for server state
    * React Context for UI state
    * URL state for navigation
  </Card>

  <Card title="Testing" icon="flask">
    * Mock repositories for unit tests
    * Integration tests with test database
    * E2E tests for critical paths
  </Card>
</CardGroup>

## Next Steps

<Card title="Database Schema" icon="database" href="/architecture/database-schema">
  Explore the PostgreSQL schema and table relationships
</Card>
