Skip to main content
Stoneturner is Bun-first: a single Bun.serve() entry point hosts the HTTP routes, the MCP server, and the React SPA. Shared plumbing lives under src/core/, and each data source lives in its own folder under src/integrations/.

Project structure

src/
  core/
    db/              # Database connection, queries, and schemas (relational + vector)
    handlers/        # HTTP + MCP request handlers
    middleware/      # CORS middleware (note: directory is "middlware")
    models/          # Shared type definitions
    services/        # Embedding, vector indexing, MCP server, tools
  integrations/
    config-registry.ts   # Frontend UI config for all integrations
    sync-registry.ts     # Sync dispatch for all integrations
    gong/                 # Gong integration
      config.ts           # IntegrationConfig definition
      integration.ts      # Integration object (sync pipeline, delete)
      db/                 # Gong-specific schemas and queries
      models/             # Gong API response types
      sync-steps/         # Individual sync pipeline steps
  client/               # React SPA (monitoring + credential config)
  index.ts              # Bun.serve() entry point with all routes
The @/* import alias resolves to src/*.
The CORS middleware directory is actually named middlware/ (a typo carried in the codebase), not middleware/.

Runtime

  • A single Bun.serve() in src/index.ts defines the routes and runs HMR in dev, on port 9000.
  • Bun-first throughout: Bun.serve(), Bun.file, bunx. No express, vite, or webpack.
  • The one exception is the database: Turso/libSQL via Drizzle (@tursodatabase/database), not bun:sqlite.

Database

Stoneturner uses Turso/libSQL through drizzle-orm/tursodatabase/database, backed by a local stoneturner.db file. Vector tables use vector32() and vector_distance_cos().
TypeSchemas
RelationalintegrationCredential, syncTask, mdArtifacts
VectorcontentEmbedding, keyPointsEmbedding, questionsAnsweredEmbedding
Schema changes flow through Drizzle:
bun run generate   # schema → migration files (drizzle-kit generate)
bun run migrate    # apply pending migrations (drizzle-kit migrate)

MCP server

  • Streamable HTTP MCP mounted at /mcp.
  • Not wrapped in CORS middleware — MCP clients call it server-side.
  • JSON-RPC, with no batching and no SSE streams.
  • Exposes semantic_search, get_md_artifact_by_id, run_sql_query, get_integration_sources, and sync_source.

Frontend

  • React 19 + react-router-dom SPA, using shadcn/radix and Tailwind v4.
  • Entry: src/client/index.htmlfrontend.tsx.
  • Fetch targets are inlined at build time from process.env.BUN_PUBLIC_BACKEND_BASE_URL.
  • Built with bun-plugin-tailwind configured in build.ts and bunfig.toml.

Commands

CommandDescription
bun devRun the server with hot reload (bun --hot src/index.ts)
bun run buildBundle the frontend to dist/
bun startProduction server
bunx tsc --noEmitTypecheck
bun run generateGenerate migration files from schema
bun run migrateApply pending migrations