CraftWeb
Loader image Loader image Loader image Loader image Loader image Loader image Loader image
0 %
Loading

BlueBee

Full agency website on Payload CMS plus a Gemini sales-offer generator

Agency site + AI Payload CMS v3 Next.js 15 PL + EN i18n
Gemini Flash Puppeteer Twenty CRM

/ Overview

The whole agency website — design, build, content model, PL+EN i18n — plus a custom Gemini sales-offer generator and a self-hosted Twenty CRM on the same Mikrus VPS. One stack. One bill. Editable by the agency, not by engineering.

See it live

/ Project Details

Category: Agency website + own AI platform

Client: BlueBee Marketing — built by CraftWeb

Role: Full-stack · AI · CMS architecture

Timeline: 2026

/ Problem

BlueBee needed a website first. Then they needed to sell faster than they could write. Every offer is bespoke. Writing one from scratch takes 45–90 minutes. The naive "just ask Gemini" answer rewrites sacred prices, switches Polish to English, drops half the bullets and 504s after 80+ s.

/ TL;DR

10 / 6

Services across 6 industries — the full marketing surface of the agency.

PL + EN

Field-level i18n with translated paths and hreflang.

15–25 s

Internal AI offer generator — down from 80+ s synchronous baseline. 5× speedup.

4 layers

Prompt guards (sacred numbers / language lock / completeness / user-edit).

/ Vision

Site is the brand, before it's a funnel. Editable by the agency, not engineering. The offer-generator never lies about prices. One VPS, no SaaS bills.

/ Principles

Site is the brand

Bold typography on neon yellow, no stock photos, a magenta hero character memorable enough to come up in onboarding calls.

Editable by the agency

Every service, industry, case study, testimonial, blog post lives in Payload CMS as a first-class collection.

Never lies about prices

SACRED NUMBERS extracted from brief, regex-validated against generated HTML, drift fails the response and triggers stricter retry.

One VPS, no SaaS bills

Site, Payload admin, Gemini generator, Puppeteer PDF and self-hosted Twenty CRM share one Mikrus VPS.

/ Engineering challenges

Async Gemini that doesn't 504. Hallucinated prices caught by regex. Puppeteer PDF that matches the iframe pixel-for-pixel. WYSIWYG edits locked against AI refine. Six challenges, six named commits.

/ 01 — 06

01 — Async Gemini → 504 timeout

80 s synchronous Gemini calls → nginx 504. Fix: in-memory job queue (f7ad1df, 78476c4). POST returns jobId, client polls every 1.5 s with Cancel + shimmer + bytes.

02 — Hallucinated prices + silent PL→EN drift

4 prompt-guardrail layers in src/lib/gemini.ts (f7ad1df, 5deaaab) — SACRED NUMBERS regex, language hard lock, completeness check, data-user-edited hard lock.

03 — Puppeteer PDF matching the iframe exactly

Hardcoded 1280 px viewport ≠ iframe's real width → pagebreaks mid-table. Fix (cc19b83, 6edb917): measure actual .page width, set viewport dynamically, @page { margin: 0 } + pageRanges: '1'.

04 — WYSIWYG inline edit + lock against refine

inline-edit.ts (~250 lines, 5deaaab) — toggle contenteditable on leaves; diff stamps data-user-edited="1"; refine prompt prepends rule #0 "HARD LOCK".

05 — i18n middleware with translated EN paths

PL bez prefiksu (/uslugi), EN with prefix + translated segments (/en/services). Custom middleware in src/middleware.ts — Accept-Language detection, static-map path rewriting, hreflang.

06 — AOS scroll vs SSR opacity trap

AOS CSS sets opacity: 0 until scroll fires — never fires on SSR. Fix: override [data-aos] { opacity: 1 !important; transform: none !important; }. Instant content beats clever entrance.

/ Stack

Next.js 15 + Payload CMS v3 + Postgres + Gemini Flash + Puppeteer + self-hosted Twenty CRM. One PM2 fork, one nginx, one Mikrus VPS.

/ Tech

Next.js 15 + React 19

App Router. Server Actions cut API ceremony. Route groups split (frontend) and (payload).

Payload CMS v3 (headless)

Code-as-config, TS-native, Postgres adapter. Local API → custom routes share admin auth.

PostgreSQL via Payload adapter

One Postgres for collections + Offers + form submissions + audit log.

Google Gemini Flash

Streaming via generateContentStream. Speed for offer generation.

Puppeteer v24 (dynamic viewport)

Renders actual iframe HTML at iframe's real width — pixel-for-pixel.

Self-hosted Twenty CRM

Docker Compose. Own data, custom fields aligned with agency pipeline, zero per-seat cost.

PM2 + nginx + Certbot

Single PM2 fork enough. In-memory job queue lives in that one process.

/ Results

5× speedup on offer generation. Zero hallucinations across 50+ shipped offers. 100% PL+EN coverage for 10 services + 6 industries + case studies + blog.

/ Numbers

15–25 s per offer

Vs 80+ s baseline — 5× speedup.

0 hallucinations

Across 50+ shipped offers — SACRED NUMBERS regex catches every drift.

100% PL+EN

Locale coverage for 10 services + 6 industries + case studies + blog.

0 timeouts

Async job queue + GC after 15 min — salesperson never sees a 504.

Payload CMS
Next.js 15
PL + EN i18n
Gemini Flash
Puppeteer
Twenty CRM
Postgres
PM2 + nginx
Resend
Bootstrap 5