Skip to main content
Better Skills is built as a modern monorepo with three main applications sharing common packages.

High-level overview

Architecture principles

Type Safety

End-to-end type safety from database to UI using TypeScript, Drizzle, and tRPC.

Monorepo Structure

Shared code in packages, apps as thin integration layers.

API-First Design

All business logic exposed through tRPC procedures.

Modern Stack

Bun runtime, Next.js, Hono, and serverless-ready architecture.

System components

Applications

Web App (apps/web)

  • Framework: Next.js 16 with React 19
  • Port: 3001
  • Purpose: Authenticated web console for managing skills and graph
  • Key features:
    • Skill browser and editor
    • Graph visualization with D3
    • Account management
    • OAuth authentication
The web app uses Next.js App Router with React Server Components.

Server (apps/server)

  • Framework: Hono
  • Port: 3000
  • Purpose: API host for Better Auth and tRPC endpoints
  • Endpoints:
    • /api/auth/* - Better Auth routes
    • /trpc/* - tRPC router
Hono is a lightweight, fast web framework designed for edge runtimes.

CLI (apps/cli)

  • Framework: Native Bun with @clack/prompts
  • Purpose: Command-line interface for skill management
  • Key features:
    • Interactive prompts
    • Local skill editing
    • tRPC client for server communication

Shared packages

API (packages/api)

  • Purpose: tRPC router and business logic
  • Exports:
    • AppRouter type (shared with clients)
    • tRPC procedures for skills, mentions, links
  • Key concepts:
    • Procedures are the API “endpoints”
    • Context provides auth and database access
    • All domain logic lives here
// Example procedure
export const appRouter = router({
  skill: {
    list: protectedProcedure
      .query(({ ctx }) => {
        return ctx.db.query.skills.findMany({
          where: eq(skills.userId, ctx.user.id)
        });
      }),
  },
});

Auth (packages/auth)

  • Purpose: Better Auth configuration and adapter
  • Features:
    • Google and GitHub OAuth
    • Session management
    • Drizzle adapter for user storage
    • Default skills sync

Database (packages/db)

  • Purpose: Drizzle ORM schema and migrations
  • Exports:
    • Database schema definitions
    • Drizzle client instance
    • Query helpers
  • Tables:
    • Users, accounts, sessions (Better Auth)
    • Skills and skill metadata
    • Graph links and mentions

Environment (packages/env)

  • Purpose: Typed runtime environment validation
  • Exports:
    • @better-skills/env/server
    • @better-skills/env/web
    • @better-skills/env/cli
  • Technology: Zod schemas with T3 Env

Config (packages/config)

  • Purpose: Shared TypeScript configuration
  • Exports: Base tsconfig.json for all packages

Markdown (packages/markdown)

  • Purpose: Markdown parsing and mention extraction
  • Features:
    • Extract @mention syntax from markdown
    • Sync auto-generated links
    • Preserve manual vs. auto-generated link metadata

Data flow

Skill creation flow

1

User creates skill

From web UI or CLI, user submits skill content.
2

tRPC mutation

Client calls skill.create procedure with content.
3

Business logic

packages/api validates and processes the skill:
  • Parse markdown for mentions
  • Validate mention ownership
  • Create skill record
4

Database write

Drizzle ORM writes to PostgreSQL via packages/db.
5

Auto-link sync

syncAutoLinksForSources creates graph edges for mentions.
6

Response

tRPC returns the created skill to the client.

Authentication flow

1

User initiates OAuth

Clicks “Sign in with Google” in web app.
2

Better Auth redirect

Redirects to Google OAuth consent screen.
3

OAuth callback

Google redirects to http://localhost:3000/api/auth/callback/google.
4

Session creation

Better Auth:
  • Creates or updates user in database
  • Creates session
  • Sets session cookie
5

Client session

Web app reads session and hydrates auth state.

Request lifecycle

tRPC request

Client Request

Hono Server (apps/server)

tRPC Adapter (@hono/trpc-server)

tRPC Context (auth + db)

Procedure (packages/api)

Business Logic

Drizzle Query (packages/db)

PostgreSQL

Response to Client

Better Auth request

Client Request

Hono Server (apps/server)

Better Auth Handler

Drizzle Adapter (packages/auth)

PostgreSQL

Session Cookie Response

Build system

Better Skills uses Turborepo for efficient builds:

Build pipeline

turbo.json
{
  "tasks": {
    "build": {
      "dependsOn": ["^build"],
      "outputs": ["dist/**", ".next/**"]
    }
  }
}
  • Builds run in topological order (dependencies first)
  • Outputs are cached locally and remotely
  • Only changed packages rebuild

Dependency graph

web → api → db → env
         → auth → db → env
         → markdown
server → api → ...
cli → api → ...

Deployment architecture

Production setup

Deployment targets

ComponentPlatformURL
WebVercelhttps://better-skills.dev
ServerVercel (or any Node.js host)https://api.better-skills.dev
DatabaseNeonManaged PostgreSQL
CLIGitHub ReleasesInstalled via curl script

Key design decisions

Why Bun?

  • Fast: 3-4x faster than Node.js for common tasks
  • All-in-one: Runtime, bundler, package manager
  • Native TypeScript: No transpilation needed
  • Modern APIs: Web-standard APIs (fetch, etc.)

Why monorepo?

  • Code sharing: Packages used by multiple apps
  • Type safety: Shared types across all apps
  • Atomic changes: Update API and clients in one PR
  • Developer experience: Single repo, single install

Why tRPC?

  • Type safety: End-to-end types from server to client
  • No codegen: Types derived directly from router
  • Simple: Just TypeScript functions
  • Framework agnostic: Works with Next.js, CLI, React Native

Why Drizzle?

  • TypeScript-first: Schema as code
  • Lightweight: No overhead, generates clean SQL
  • Migrations: Built-in migration system
  • Type-safe queries: Full IntelliSense for queries

Security considerations

  • OAuth-only (no passwords stored)
  • Session cookies with secure flags
  • CSRF protection via Better Auth
  • All tRPC procedures check user context
  • Skills owned by users (no cross-user access)
  • Mention validation ensures same-owner references
  • All inputs validated with Zod schemas
  • Environment variables validated at startup
  • SQL injection prevented by Drizzle ORM
  • CORS_ORIGIN whitelist in server config
  • Credentials included for cookie-based auth

Next steps

Monorepo Structure

Deep dive into workspace organization

Tech Stack

Explore technologies in detail

Development Setup

Get started with development

Database Setup

Configure your database

Build docs developers (and LLMs) love