Last Updated: 2026-05-06 Status: Active
The complete internal reference for the Vlozi blog system. Everything a developer needs — architecture, schema, deployment, editor internals, SDK — lives here or is one link away.
1. What Is This System?
The Vlozi blog system is a multi-tenant headless blog engine built across three codebases:
| Codebase | Location | Role |
|---|---|---|
| blog-service | apps/blog-service |
Cloudflare Worker — owns all blog data, enforces permissions, serves the API |
| seller-dashboard | apps/seller-dashboard/src/modules/blog |
Next.js dashboard — where tenants write and manage posts |
| blog-sdk | packages/blog-sdk |
Published as @vlozi/blog — what customers embed on their websites |
Two doors in, one data store:
Seller Dashboard ──JWT──► Gateway ──service binding──► blog-service ──► Neon PostgreSQL
Customer Website ──API Key──► Gateway ──────────────────────────────────────────────────►- Admin door (
/blog/admin/*): JWT-authenticated. Full CRUD for posts, categories, and tags. - Public door (
/blog/public/*): API key-authenticated. Read-only, published posts only.
2. Start Here By Role
| Role | Reading Path |
|---|---|
| New to the project | This doc → glossary.md → architecture.md → user-journey.md |
| Backend / blog-service work | architecture.md → database.md → blog-service.md → permissions.md → deployment.md |
| Frontend / dashboard work | architecture.md → frontend-spec.md → editor.md → markdown-import.md |
| SDK integrator | sdk-reference.md → sdk-security-model.md → ai-integration-prompt.md |
| Need a curl example fast | cookbook.md |
| Setting up locally or deploying | deployment.md |
| Debugging a failing request | blog-workflow.md |
3. Doc Index
Core Reference
| Doc | What It Covers |
|---|---|
glossary.md |
Every term used across these docs — tenant, JWT, slug, content_json, hydration, etc. |
architecture.md |
System diagram, all services, request flows, header protocol, permission model, multi-tenant isolation |
database.md |
All 4 tables — column reference, constraints, indexes with rationale, migrations |
permissions.md |
Every permission string, what route it gates, role bundles, how to add a new scope |
deployment.md |
Local dev setup, env vars for all 3 services, production deploy, health checks |
blog-service.md |
Full API reference — every endpoint, request/response schemas, middleware pipeline |
cookbook.md |
Runnable curl + fetch recipes for common admin and public operations |
blog-workflow.md |
Step-by-step request traces, common failure modes and fixes, debug checklist |
editor.md |
TipTap extension inventory, custom node views, slash commands, how to add extensions |
markdown-import.md |
The 5-stage .md → draft pipeline: parse → resolve → convert → mirror images → create |
frontend-spec.md |
Dashboard UI — pages, components, API hooks, Redux state, permission-gating |
sdk-reference.md |
Complete @vlozi/blog API — all exports, hooks, components, types, defaults |
sdk-security-model.md |
HTML sanitization, iframe allowlist, XSS prevention, CSP guidance |
testing.md |
Test inventory, how to run, test patterns, coverage gaps |
Context & Process
| Doc | What It Covers |
|---|---|
user-journey.md |
9 end-to-end user journeys for admin authoring and SDK consumption |
sdk-backlog.md |
Active bug/improvement queue for @vlozi/blog |
ai-integration-prompt.md |
Paste-ready AI prompt for SDK integration tasks |
Vision (Forward-Looking)
These describe where the product is going — not the current implementation.
| Doc | What It Covers |
|---|---|
vision/blog-engine-vision.md |
Product north star — full editor, management, and integration vision |
vision/layouts-vision.md |
Pre-built blog layout presets |
vision/hosted-blog-vision.md |
Hosted blog pages (no SDK needed) |
vision/integration-friction-vision.md |
Reducing SDK integration friction |
vision/books-vision.md |
Blog → series → book publishing ladder |
4. Codebase Quick Map
apps/
├── blog-service/ Cloudflare Worker · port 8791 (local)
│ ├── src/index.ts Entry point — middleware pipeline + route registration
│ ├── src/db/schema.ts 4 tables: blog_posts, blog_categories, blog_tags, blog_post_tags
│ ├── src/routes/admin/ posts.ts · categories.ts · tags.ts
│ ├── src/routes/public/ posts.ts · categories.ts · tags.ts
│ ├── src/middleware/ auth.middleware.ts · db.middleware.ts
│ └── src/utils/tiptap-renderer.ts TipTap JSON → sanitized HTML
│
├── gateway/ Cloudflare Worker · port 8788 (local)
│ └── src/routes/blog.proxy.ts Admin + Public proxy handlers
│
└── seller-dashboard/ Next.js · port 3000 (local)
└── src/modules/blog/ ~54 files across pages, editor, components, store, import
packages/
└── blog-sdk/ Published as @vlozi/blog@2.1.6
└── src/ client · react/ · server/ · next/5. Three Things Every Dev Must Know
1. The gateway is the only trust boundary.
blog-service validates x-gateway-key on every request. Requests missing or bearing an invalid key are rejected 403. There is no direct public access to blog-service. When something is 403 but shouldn't be, check that GATEWAY_SECRET matches in both services.
2. Content is TipTap JSON in the database, HTML on the public API.
All content is stored as JSONB (content_json). The admin API returns raw TipTap JSON for the editor. The public API (/public/posts/:slug) runs it through tiptap-renderer.ts before responding — HTML is generated server-side per request, never persisted.
3. All database queries are scoped by tenant_id.
There is one blog-service serving every tenant. Isolation is enforced at the query level, not by routing or separate databases. Every SELECT, INSERT, UPDATE, and DELETE includes a WHERE tenant_id = ? clause. The requireTenant middleware rejects any request where x-tenant-id is absent.