schemaf

module
v0.5.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 16, 2026 License: MIT

README

Schema F

schemaf is an opinionated framework that eliminates infrastructure churn by making all the boring decisions for you. Build production-ready applications with Go backend, Postgres, and static frontend immediately - no setup, no bikeshedding.

The name "Schema F" comes from the German expression meaning "the standard operating procedure" or "the tried-and-true method" - which is exactly what this framework provides: a reliable, proven approach to project infrastructure.

Documentation:

  • INSTALL.md — Setting up a new project
  • EXTEND.md — Adding endpoints, CLI subcommands, database queries, testing

Golden Rule

If it can be generalized, put it in schemaf. If arbitrary decisions need to be made: decide them normatively in the framework. Leave only creative decisions to the application layer.

schemaf deliberately reduces degrees of freedom. We cement:

  • Run scripts and CLI tooling
  • Code generation workflows (one command → everything)
  • Docker compose layout and dependency resolution
  • Port assignments
  • Database choice and migration patterns
  • Server architecture (the Go server is the gateway)
  • Glue code generation (migrations provider, endpoint provider, etc.)

You focus on:

  • Your database schema
  • Your business logic
  • Your API endpoints
  • Your frontend UI

This repository is the framework itself. The example project lives in example/ and demonstrates how a project consumes the framework.

What schemaf Provides

schemaf is batteries-included. These are built-in, not optional:

  • Server with default endpoints: /health, /status, auth layer
    • Go server is the gateway
    • Binds /api/* for your handlers + framework endpoints
    • Binds / for frontend (proxy in dev, embed in production)
    • Single exposed port (7000)
  • Authentication: JWT-based auth, fully managed by the framework
    • Bearer token in Authorization header
    • Signing key is auto-generated on first boot and stored in Postgres (_schemaf_config table)
    • No configuration, no secrets to manage — the framework owns the key entirely
    • Auth is declared per-endpoint (see Endpoint Interface) — /health and /status are always open
  • Database: Postgres is the built-in, always-present SQL database
    • schemaf provisions and manages Postgres — no setup, no configuration
    • It is the one and only SQL database in a schemaf project
    • You add tables, migrations, and queries; the infrastructure is handled for you
    • See Database for details
    • Need a graph DB, NoSQL store, or other data layer? Add it as a Docker container in your project's compose/
  • API endpoints: Structs implementing a typed interface — not plain functions
    • Request and response types are Go generics on the struct — the framework handles JSON decode, validate, encode
    • No boilerplate: your Handle method receives a typed request and returns a typed response
    • Codegen scans endpoint structs → generates api.Provider + full OpenAPI spec → generates TypeScript client
    • See Endpoint Interface for details
  • Docker compose: Built-in compose for backend and Postgres — merged with compose/ in your project
  • Code generation: One command generates all glue code — see Code Generation
  • Ports: Fixed allocation (see below)
  • Project entrypoint: schemaf.sh codegen, schemaf.sh test, schemaf.sh run, schemaf.sh dev

What You Add

Projects built with schemaf add only creative logic:

  • Database schema: Write SQL migrations in go/db/migrations/
  • Database queries: Write SQL queries in go/db/queries/
  • API handlers: Write Go handlers in go/api/
  • Frontend: Any static site framework in frontend/ (React, Vue, Svelte, etc.)
  • Optional services: Additional Docker containers if needed (Redis, workers, etc.)
  • Optional CLI commands: Custom subcommands via app.AddSubcommand()
  • Tests: Go tests and TypeScript integration tests

That's it. No configuration files (except minimal schemaf.toml). No binding framework commands. No decisions about project structure - it's normative.

Project Structure (Normative)

schemaf expects a specific directory layout. No configuration, no flexibility - this is the structure:

myapp/
├── schemaf.toml                    # Minimal config (title, name)
├── schemaf.sh                      # Copy from schemaf repo — project entrypoint
├── gen/                            # All generated files (gitignored)
│   ├── compose.gen.yml             # Generated: merged compose definition
│   └── openapi.json                # Generated: OpenAPI spec
├── go/                            # All Go code (CLI + server unified)
│   ├── main.go                    # Wire up providers, start app
│   ├── db/                        # All database concerns
│   │   ├── migrations/            # Your SQL migrations
│   │   │   ├── 001_users.sql
│   │   │   └── 002_posts.sql
│   │   ├── queries/               # Your SQL queries (sqlc input)
│   │   │   └── users.sql
│   │   ├── queries.gen.go         # Generated: sqlc query functions
│   │   └── migrations.gen.go      # Generated: db.Provider
│   └── api/                       # Your API handlers (normative!)
│       ├── users.go              # Your handler implementations
│       └── endpoints.gen.go      # Generated: api.Provider
├── frontend/                      # Your static site (any language/framework)
│   ├── api/
│   │   └── openapi.gen.ts        # Generated: TypeScript client
│   ├── src/
│   └── package.json
└── compose/                       # Optional: docker-compose overrides

Why normative paths?

  • Zero decisions about "where do I put this?"
  • Codegen knows exactly where to write generated providers
  • No configuration needed
  • Clone any schemaf project and the structure is identical

Generated file naming: All generated files use .gen. infix (e.g., *.gen.go, *.gen.ts) making them instantly recognizable and easy to .gitignore.

Recommended .gitignore:

gen/

Server Architecture

The Go server built from schemaf is the gateway.

Your Application (port 7000)
├── /api/*        → Go handlers (your business logic)
└── /*            → Frontend
    ├── Dev:      Proxy to frontend dev server (port 7002)
    └── Prod:     Serve embedded static files

In production, frontend assets are embedded at build time via //go:embed and served directly by the Go server. In dev mode, the Go server proxies frontend requests to the dev server on port 7002.

Default endpoints:

  • /health - Health check (built-in)
  • /status - Service status (built-in)
  • /api/* - Your handlers + auth layer (framework provides auth, you add business logic)

Port Convention

schemaf uses a fixed port allocation scheme to eliminate configuration:

7000           - Application server (main entry point)
                 Serves /api (Go handlers) and / (frontend)
7001           - Reserved (future use)
7002           - Frontend dev server (Vite, Next.js dev, etc.)
7003           - Postgres
7004 - 7009    - schemaf framework reserved
7010+          - Project-specific services (Redis, workers, etc.)

Why fixed ports?

  • No port conflicts across projects (each gets its own range)
  • No environment variables needed for service discovery
  • Docker compose networking "just works"
  • Clear convention: 700X for core, 701X+ for project services

The One Binary Principle

Most application stacks are a collection of tools: a server process, a migration runner, a codegen CLI, a dev runner script, a separate frontend build, scattered admin utilities. Each has its own install, its own config, its own mental model.

schemaf collapses all of this into a single compiled binary:

What How
HTTP server ./myapp server — runs inside the container
Compose orchestration ./schemaf.sh run/dev — execs docker compose, then exits
Code generation ./schemaf.sh codegengo runs the framework CLI, reads your files
Database migrations embedded SQL, applied automatically on server startup
Frontend embedded via //go:embed in production; proxied from port 7002 in dev (no rebuild needed)
TypeScript API client generated from compiled-in endpoint structs at codegen time
Admin / custom tools ./myapp <subcommand> — anything you add via app.AddSubcommand()

The binary has full knowledge of itself. Its endpoint structs are compiled in — so it can reflect over its own API to generate the OpenAPI spec and TypeScript client without a running server. Its migrations are embedded — so it can apply them on startup without external files. Its frontend is embedded — so production deployment is a single binary copy.

Deployment is therefore trivial:

go build -o myapp go/main.go   # one artifact
./schemaf.sh codegen            # generates gen/compose.gen.yml
./schemaf.sh run                # everything runs

No package manager. No deployment pipeline that installs twelve tools. No config files spread across the filesystem. One binary, one compose file, done.

Repository Map

compose/        - Reusable compose blocks (postgres, future: redis, etc.)
example/        - Example project demonstrating schemaf usage
api/            - API registry + OpenAPI generation
schemaf/        - App lifecycle (schemaf.New, app.Run)
cli/            - schemaf CLI framework (subcommands, config/state)
compose/        - Compose dependency resolver (x-schemaf metadata)
db/             - Database helpers + migrations

Design Philosophy

schemaf is documentation-first. We design by writing the README and docs for features that don't exist yet. The documentation is the source of truth for how the framework should work.

Core principles:

  1. Maximize decisions made - Every choice you don't have to make is time saved
  2. Minimize configuration - Zero config is the goal; convention over configuration
  3. Maximize generation - If we can generate it, you don't write it
  4. Cement boilerplate - Run scripts, codegen, compose layout, ports, database choice, glue code
  5. Single responsibility - Framework handles infra, you handle business logic
  6. Fast to production - Clone, add schema + handlers, run codegen, deploy

Directories

Path Synopsis
ai
Package ai provides a unified interface for working with multiple LLM providers.
Package ai provides a unified interface for working with multiple LLM providers.
tool
Package tool provides high-level utilities for common AI workflows.
Package tool provides high-level utilities for common AI workflows.
cli
cmd/ctl
Package ctl re-exports the compose resolver types from github.com/flocko-motion/schemaf/compose for use by the CLI subcommands.
Package ctl re-exports the compose resolver types from github.com/flocko-motion/schemaf/compose for use by the CLI subcommands.
cmd
schemaf command
This is a CLI built from the extensible, modular CLI kit provided by the framwork.
This is a CLI built from the extensible, modular CLI kit provided by the framwork.
Package log provides the framework's centralized logger.
Package log provides the framework's centralized logger.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL