GitBucket.WTF Architecture

Overview

GitBucket.WTF is a self-hostable GitHub-style code hosting platform built with:

  • Monorepo: pnpm workspaces + Turbo
  • Frontend/Backend: Next.js 15 (App Router)
  • CLI: gib — git in a bucket, for server-less direct-to-storage workflows
  • Storage: pluggable via @gitbucket/storage — S3-compatible, Vercel Blob, or local filesystem
  • Engine: a single GitEngine (in @gitbucket/storage) powers both the web app and the CLI
  • Language: TypeScript

Project Structure

GitBucket.WTF/
├── apps/
│   ├── web/                # Next.js application (the platform)
│   │   ├── src/
│   │   │   ├── app/        # Next.js App Router (pages + API routes)
│   │   │   └── lib/        # Server utilities; git-service.ts is a thin
│   │   │                   #   shim that delegates to GitEngine
│   │   └── package.json
│   └── cli/                # @gitbucket/gib — the gib CLI
│       ├── src/
│       │   ├── commands/   # init/remote/push/pull/clone/status
│       │   ├── storage-from-url.ts  # URL → Storage adapter
│       │   ├── pack-sync.ts         # download bucket packs into .git
│       │   └── config.ts            # per-repo gib config (.git/gib/config.json)
│       └── test/           # integration tests that spawn the CLI binary
├── packages/
│   ├── entities/           # @gitbucket/entities — domain entities
│   │   └── src/            # user.ts, organization.ts, repository.ts, …
│   └── storage/            # @gitbucket/storage — shared git engine
│       └── src/
│           ├── storage.ts          # Storage interface
│           ├── adapters/           # S3 / Vercel Blob / local-FS
│           └── git-engine.ts       # storage-agnostic git ops + packs
├── docs/                   # Documentation (this directory)
└── .github/workflows/      # CI: type-check + test on every PR

Two clients, one engine

                     ┌───────────────────────┐
                     │   @gitbucket/storage  │
                     │                       │
                     │   Storage  + adapters │
                     │   GitEngine           │
                     └──────────┬────────────┘
                                │
                ┌───────────────┴───────────────┐
                ▼                               ▼
       ┌─────────────────┐             ┌────────────────┐
       │  apps/web       │             │  apps/cli      │
       │  (Next.js)      │             │  (gib binary)  │
       │                 │             │                │
       │  git-service.ts │             │  commands/*    │
       │  smart-HTTP     │             │  isomorphic-   │
       │  routes         │             │  git on local  │
       └────────┬────────┘             └────────┬───────┘
                │                               │
                └───────────────┬───────────────┘
                                ▼
                     ┌───────────────────────┐
                     │   Object storage      │
                     │   (S3 / Vercel Blob   │
                     │    / local FS)        │
                     └───────────────────────┘

A repo is just a key prefix in a bucket. Both clients read and write the same on-disk layout, so anything pushed via gib is visible to the web app and vice versa.

Data Storage

All data is stored in S3-compatible buckets. Entity records use @decoperations/s3worm directly; git data goes through @gitbucket/storage's Storage interface so any future adapter (Vercel Blob, local FS, future backends) works without touching git-handling code.

  • Entities: JSON documents in S3, organized by entity type
  • Git Data: Files stored in S3 following Git object model (future)
  • File Paths: Hierarchical organization by entity relationships

Entity Storage Patterns

  • users/{username}.json - User entities
  • organizations/{slug}.json - Organization entities
  • org-memberships/{orgId}/{userId}.json - Membership records
  • repositories/{orgId}/{slug}.json - Repository entities
  • branches/{repoId}/{branchName}.json - Branch entities
  • commits/{repoId}/{hash}.json - Commit entities
  • pull-requests/{repoId}/{number}.json - PR entities

API Routes

API routes follow RESTful conventions:

  • GET /api/orgs - List organizations
  • POST /api/orgs - Create organization
  • GET /api/orgs/:orgId - Get organization
  • GET /api/orgs/:orgId/repos - List repositories
  • POST /api/orgs/:orgId/repos - Create repository
  • GET /api/repos/:repoId/pulls - List pull requests
  • POST /api/repos/:repoId/pulls - Create pull request

Authentication

Currently placeholder authentication. TODO:

  • JWT token generation/validation
  • Password hashing (bcrypt)
  • Session management
  • OAuth integration (future)

Repository Pattern

Entities are managed through Repository instances created via createRepositories():

const repos = createRepositories();
const user = await repos.users.findById("user-id");
const orgs = await repos.organizations.findAll();

This provides a clean abstraction over S3 storage operations.

Next Steps

  1. Git Integration: Implement Git object storage and operations
  2. File Browsing: Build tree/blob viewing by branch/commit
  3. Diff Generation: Implement unified diffs for PRs and commits
  4. Authentication: Complete auth implementation
  5. Permissions: Implement role-based access control
  6. UI Components: Build React components for browsing, PRs, etc.