Developer Guide

Getting Started with Pouta

Pouta is a serverless, edge-native, framework-agnostic Git-backed CMS running entirely on Cloudflare Pages/Workers and D1 SQLite. Follow this comprehensive setup guide to boot your own instance.

Step 01

Register a GitHub App

Pouta CMS integrates as a GitHub App to secure individual repository scopes, list repository installations, and commit files using dynamic, short-lived installation access tokens.

1

Go to your GitHub profile settings: Settings > Developer Settings > GitHub Apps > New GitHub App.

2

Configure the primary Application settings:

  • Homepage URL: https://your-pouta-domain.com (Marketing site)
  • Callback URL: https://app.your-pouta-domain.com/api/auth/callback (Active app auth API endpoint)
  • Setup URL: https://app.your-pouta-domain.com (Redirects after installation)
3

Grant dynamic Repository Permissions:

  • Contents: Read & Write (To load configurations and commit Markdown files)
  • Metadata: Read-Only (Required by GitHub to list active repositories)
4

Generate secure credentials and encode keys:

Create an OAuth Client Secret and record the Client ID. Then, generate a Private Key (.pem). Since Cloudflare secrets do not handle raw multiline PEM formatting cleanly, encode the key in Base64:

Shell
base64 -i your-app-private-key.pem | pbcopy
Step 02

Configure Cloudflare Variables

Sensitive credentials, client secrets, and base64-encoded private keys must never be committed to repository files. Pouta loads these keys dynamically at the Edge.

A. Local Development (.dev.vars)

Create a Git-ignored file named .dev.vars in the project root:

GITHUB_APP_ID="1002345"
GITHUB_CLIENT_ID="Iv1.xxxxxxxxx"
GITHUB_CLIENT_SECRET="xxxxxxxxxxxxxxx"
GITHUB_APP_PRIVATE_KEY_B64="base64_pem..."
SESSION_SECRET="32_char_minimum_secret"

B. Production Dashboard Bindings

Go to Cloudflare Dashboard > Pages/Workers Project > Settings > Environment Variables and define:

  • GITHUB_APP_ID, GITHUB_CLIENT_ID
  • GITHUB_CLIENT_SECRET (Mark as Secret)
  • GITHUB_APP_PRIVATE_KEY_B64 (Mark as Secret)
  • SESSION_SECRET (Stateless Session Encryption Key)
  • D1 Database Binding: Bind variables under Settings > Functions. Bind the name DB directly to your production SQLite D1 database.
Step 03

Create Website Configuration

Pouta is completely schema-agnostic. Drop a pouta.config.json at the root of your target website repository. Pouta reads this schema dynamically to draw sidebars, fields, and paths.

pouta.config.json
{
  "contentTypes": [
    {
      "type": "blog",
      "label": "Blog Posts",
      "writePath": "src/content/blog/{slug}.md",
      "fields": [
        { "name": "featured_image", "label": "Cover Image", "type": "image" },
        { "name": "description", "label": "Meta Description", "type": "textarea" },
        { "name": "pinned", "label": "Pinned Post", "type": "boolean" }
      ]
    }
  ]
}
Field Schema Note: Declaring fields is fully optional but highly recommended. The schema currently supports three distinct custom metadata types: image (draws visual asset selector), textarea (ideal for SEO meta blocks), and boolean (draws visual toggle switches). If no fields are needed, declare "fields": [].
Step 04

Boot Server & Run Migrations

Pouta uses a lightweight local SQLite engine using Cloudflare's Wrangler. Boot migrations on your local sandbox and start drafting.

A. MIGRATING D1 DATABASE SCHEMA
npx wrangler d1 execute pouta-d1-db --local --file=db/schema.sql
B. START DEVELOPMENT SERVER
npm run dev

Visit http://localhost:4321 to sign in with GitHub, grant installations to your repository workspace, and begin drafting content. Every autosave updates D1 SQLite at the edge, and clicking "Publish" commits structured Markdown directly to your Git branch!

Production SaaS Domain Architecture

For production SaaS implementations, we strongly recommend separating your public-facing marketing assets and documentation resources from the high-security admin workspace:

Root Domain your-pouta-domain.com

Hosts your public-facing marketing landing page, product pricing details, terms, and search-optimized developer documentation.

Secure Subdomain app.your-pouta-domain.com

Dedicated workspace hosting the interactive Pouta admin dashboard panel, edge API routes, auth callback links, and session cookie validation gates.

This design pattern scopes your HTTP-only, cryptographically sealed session cookie strictly to your secure app. subdomain, isolating it from generic marketing scripts and assets.