Willi Krappen

pagebee.de

Multi-tenant SaaS that lets businesses tailor their website by chatting with an AI — per-tenant git repo, preview, Netlify deploy on approval.

pagebee.de

Key engineering call

A real git repo per tenant (not DB version strings). Revisions, rollbacks and previews become plain git operations — no custom version mechanism, no custom diff. Cost: more disk I/O, less trivial backup. Pays off the moment the first customer says 'this looked different yesterday'.

A non-technical owner says 'swap the hero photo and update opening hours to 8-18'. The orchestrator translates that into tool calls against the customer's own git repo, commits on a draft branch, renders a preview and waits for approval. Each customer has an isolated repo, plan-based safety rules and full revision history. A separate Claude-Code-driven pipeline scrapes a prospect's existing site and bootstraps a modern React clone for onboarding.

From chat to deploy

One session, seven steps. Everything waits for approval before the live push — preview-first by default.

  1. 1

    Owner writes in the editor: 'swap the hero photo and change opening hours to 8-18'.

  2. 2

    Edit request lands in the Postgres queue with status PENDING → RUNNING.

  3. 3

    Orchestrator initialises a session with site context, plan rules and tool set.

  4. 4

    Tool loop: AI explores the repo, reads content files, edits surgically. Live events stream to the UI over WebSocket.

  5. 5

    AI calls finalize_edit_with_commit; complexity rules are validated against the plan.

  6. 6

    If OK: commit to a draft branch, Netlify preview, revision record created.

  7. 7

    Owner sees the preview, hits deploy → push to main, Netlify production build.

Architecture — Turborepo monorepo

Four internal packages plus the Next.js app. Tenant repos and onboarding pipeline live outside the SaaS runtime.

PathWhat for
apps/studio/Next.js admin and client UI (editor, preview, revisions, billing).
packages/core/Shared types, plan rules, defaults.
packages/ai-orchestrator/Provider interface (Claude / OpenAI), tool loop, event stream.
packages/git-adapter/Tenant-isolated git operations (checkout, diff, commit, branch).
packages/netlify-adapter/Site provisioning, preview deploys, production deploys via Netlify API.
prisma/Schema and migrations for auth, tenants, revisions, pipeline queue.
repos/{slug}/A real git repo per tenant (gitignored from the monorepo).
pipeline_updated/Separate Claude-Code pipeline that scrapes existing sites and bootstraps new React sites.
bot/Telegram bot that kicks off the onboarding pipeline from chat.

Tool loop — 8 tools

The loop is provider-agnostic: Claude (default) and OpenAI share exactly this tool schema and a common event stream.

ToolDescription
list_project_filesLists project files, optionally filtered by glob.
search_filesFull-text search through the tenant repo.
read_project_fileReads a file relative to project root.
edit_fileTargeted string replacement in an existing file.
write_project_fileWrites a file (new or overwrite).
delete_project_fileDeletes a file from the repo.
summarize_project_changesAggregated diff: changed files, +/- lines.
finalize_edit_with_commitCloses the session: validates complexity rules, commits, deploys preview.

Plan safety rules — basic vs pro

Rules run at finalize time against the aggregated diff — not per tool call. Violations reset the changes and set the edit to BLOCKED_COMPLEXITY.

RuleBasicPro
Max files per edit550
Max lines per edit801000
Max diff size10 KB100 KB
Allowed pathscontent/**, public/uploads/****
Layout changes

Onboarding pipeline — 6 phases

Separate Claude Code process that scrapes a prospect's existing site and bootstraps a modern React clone. Vite + React 18 + Tailwind, Netlify Forms and hosting.

1. Scrape & Analyze

low (scripted)

Extract the existing site with a custom scraper — text, images, colors, fonts, structure.

2. Research & Plan

medium

Industry research, sitemap, design direction.

3. Content & Design

medium

Per-page copy, design tokens, image selection.

4. Implement

high

Rich template ships header / footer / forms / SEO; only page content gets newly written.

5. QA & Verify Build

low

npm run build must be green; lint and visual checks.

6. Sales Pitch

low

Generates a sales-call script for cold outreach.

Key engineering decisions

Tenant-isolated git repos, not DB strings

Every customer site is a real git repo under repos/{slug}. Revisions, rollbacks and previews become plain git operations — no custom version mechanism, no custom diff.

Provider-agnostic tool loop

Claude and OpenAI share a single tool schema and a common event stream. Provider is swappable per edit request — environment default, request override.

Hard-enforced token budget

File reads, search results and conversation history get trimmed to hard limits before they go to the provider. Cost stays predictable on basic plans — the orchestrator doesn't become a cost trap.

Plan-gated safety rules

maxFilesChanged, maxLinesChanged, maxTotalDiffBytes, allowedPaths, allowLayoutChanges — configurable per plan. Basic plans only see content/** and public/uploads/**, pro plans get layout access. Validation runs at the finalize step, not per tool call.

Live activity stream over WebSocket

Tool calls and model deltas push to the editor UI in real time. The owner sees 'AI reads content/hero.md', 'edits ...', 'commit' — no black-box waiting spinner.

Onboarding pipeline as a separate process

The 6-phase pipeline does NOT run as a studio subprocess — it is its own Claude Code setup with its own skills (skills/), runnable independently of the studio. Telegram bot triggers it. Clean cut between onboarding tooling and runtime SaaS.

Tradeoffs — called out honestly

The awkward decisions most demos hide. Made visible here.

Tenant git repos instead of DB version strings

A real git repo per customer turns revisions, rollbacks and previews into plain git operations. Cost: more disk I/O, per-customer backup complexity, non-trivial storage footprint. Pays off the moment the first customer says 'this looked different yesterday'.

Validate at finalize, not per tool call

Complexity rules run against the aggregated diff at the end. Cost: the AI sometimes burns tokens on work that gets rejected at the finalize step. Pays off because editor UX stays smooth — no flaky tool that throws 'BLOCKED' mid-action.

Provider-agnostic tool loop (Claude + OpenAI)

Both providers share one tool schema and a common event stream exactly. Cost: tool definitions have to hit the highest common denominator — no extended thinking, no provider-specific prompt caching, no vision input. Pays off because the data model doesn't tear on the first model switch.

Hard token budget per edit request

File contents, search results and conversation history are trimmed to hard limits before every provider call. Cost: the AI gets cut off mid-thought occasionally and has to restart. Pays off because basic plans stay cost-predictable — the orchestrator doesn't become a cost trap.

Onboarding pipeline as its own process

The 6-phase pipeline for new customers does not run inside the studio runtime — it's a separate Claude Code setup with its own skills. Cost: no shared progress UI, no shared auth context. Pays off because onboarding tooling and runtime SaaS don't deploy or load each other.

What's deliberately not built

  • Real-time multi-user editing on the same site state — one owner per site, conflicts go through git branches, not CRDTs.
  • Mobile editor UI — capture via Telegram bot works on mobile, actual editing is desktop-only.
  • Theme marketplace — every site sits on a shared shadcn-based template; customization is per-tenant-repo, not swappable themes.
  • Auto SEO — the AI does not write meta tags or sitemaps on its own; that stays an explicit customer request.
  • Public preview URLs — every preview is auth-gated, no 'share the link with your boss' flow.
  • Per-site i18n — every customer site is monolingual; multilingual setups are a separate project.

Deployment

Docker Compose for local Postgres; studio runs as a Next.js app. Netlify handles actual hosting for customer sites — both previews and production builds. An nginx preview config is bundled as a fallback for self-hosted previews.