Skip to main content

Spec Generation

pb-ext supports both runtime and build-time OpenAPI spec generation. For production deployments, specs should be generated during the build process and read from disk at runtime for optimal performance.

Dev vs Production

Development Mode

  • No disk specs — specs are generated at runtime via AST parsing
  • Specs regenerate on server restart (picks up code changes)
  • Slightly slower startup due to AST analysis
  • No build toolchain required
Command:

Production Mode

  • Specs generated at build time and copied to dist/specs/
  • Binary reads specs from disk at runtime
  • Fast startup (no AST parsing)
  • Specs are validated during build
  • Generated specs are version-controlled
Command:
This generates specs to dist/specs/ and bundles them with the final binary.

Build Pipeline Integration

The pb-cli toolchain automatically runs OpenAPI generation for production builds:

What Happens During Build

  1. Frontend build (if applicable)
  2. Spec generation: --generate-specs-dir=dist/specs
  3. Spec validation: Ensures all required fields present
  4. Go build with specs copied to final artifact

Programmatic Generation

Generate specs from your own code:

Using SpecGenerator

From main.go

The typical pattern in cmd/server/main.go:
Usage:

Validation

ValidateSpecs

Validate generated specs to ensure they’re valid OpenAPI 3.0:
Checks:
  • File exists and is readable JSON
  • Required fields present: openapi, info, info.title, info.version, paths
  • Filename matches version (e.g., v1.json for version v1)

ValidateSpecFile

Validate a single spec file:

From main.go

Usage:

Generated Spec Location

Specs are written to the output directory with version-based filenames:
Each file contains the full OpenAPI 3.0.3 spec for that version, including:
  • All paths and operations
  • Component schemas (structs)
  • Parameters, request bodies, responses
  • Security requirements
  • API metadata (title, description, contact, license)

Runtime Spec Loading

At runtime, pb-ext follows this source selection policy:
  1. If PB_EXT_OPENAPI_SPECS_DIR env var is set, read from that directory
  2. Otherwise, read from dist/specs/ relative to the binary
  3. If no specs found on disk, fall back to runtime AST generation (dev mode)

Environment Variables

PB_EXT_OPENAPI_SPECS_DIR: Override spec directory
PB_EXT_DISABLE_OPENAPI_SPECS: Force runtime generation (ignore disk)

Caching and Deep Copy

Caching: Parsed specs are cached per version in memory after first load. Deep Copy: Returned specs are deep-copied to avoid mutation leaks across requests. This ensures concurrent Swagger UI requests don’t interfere with each other.

Integration with APIVersionManager

The APIVersionManager coordinates spec loading:
Lookup order:
  1. Check if disk spec exists via HasEmbeddedSpec(version)
  2. If yes, load via GetEmbeddedSpec(version) (cached)
  3. If no, fall back to runtime GenerateComponentSchemas() via AST

Testing Spec Generation

Create a test that generates and validates specs:

CI/CD Integration

GitHub Actions

Makefile

Spec Format

Generated specs follow OpenAPI 3.0.3 format:

Common Issues

Missing Specs in Production

Problem: Server falls back to runtime AST parsing in production. Solution: Ensure specs are copied to the correct location:

Validation Failures

Problem: ValidateSpecs fails with missing required field. Solution: Check your APIDocsConfig has all required fields:

Stale Specs

Problem: OpenAPI docs don’t reflect recent code changes. Solution: Regenerate specs:

Best Practices

Version-Control Specs

Commit generated specs to Git so reviewers can see API changes in PRs.

Validate in CI

Run --validate-specs-dir in CI to catch invalid specs before deployment.

Use Build Flag

Always use pb-cli --production for prod builds to ensure specs are bundled.

Cache Busting

If specs don’t update, clear cache: rm -rf dist/specs && pb-cli --build-only

Further Reading