# Prism

[![CI](https://github.com/Lasse-numerous/prisme/actions/workflows/ci.yml/badge.svg)](https://github.com/Lasse-numerous/prisme/actions/workflows/ci.yml)
[![codecov](https://codecov.io/gh/Lasse-numerous/prisme/graph/badge.svg?flag=prism-core)](https://codecov.io/gh/Lasse-numerous/prisme)
[![PyPI](https://img.shields.io/pypi/v/prisme)](https://pypi.org/project/prisme/)
[![Documentation](https://img.shields.io/badge/docs-readthedocs-blue)](https://prisme.readthedocs.io/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)

> **"One spec, full spectrum."**

Prism is a code generation framework that turns Pydantic model definitions into production-ready full-stack applications. Define your data models once in Python and generate a complete backend (REST + GraphQL + MCP APIs), a React frontend, authentication, admin panel, tests, Docker config, CI/CD pipelines, and cloud deployment — all from a single spec file.

```bash
pip install prisme  # or: uv add prisme
prisme create my-app && cd my-app && prisme install && prisme generate && prisme test && prisme dev
```

## Why Prism?

Most code generators produce a one-time scaffold you immediately start editing by hand. Prism is different: it generates code you can **regenerate** without losing your customizations. Protected regions, base/extension file splitting, and smart merge strategies let you keep evolving your spec while preserving every line of custom business logic.

| Problem | How Prism solves it |
|---|---|
| Writing the same CRUD across REST, GraphQL, and frontend | Define once in a spec, generate everywhere |
| Generated code becomes unmaintainable after edits | Four file strategies preserve your customizations across regenerations |
| Setting up auth, admin, Docker, CI for every project | All included — toggle features in the spec |
| No type safety between backend and frontend | End-to-end types from database column to React prop |
| Repetitive filtering, sorting, pagination boilerplate | Declared per-field in the spec, generated into every API layer |

## What You Get

From a single `specs/models.py` file, `prisme generate` produces:

**Backend** — Python 3.13+ / FastAPI / SQLAlchemy (async)
- SQLAlchemy models with relationships, soft delete, timestamps, and temporal queries
- Pydantic schemas (create, update, read, list, filter)
- Service layer with CRUD, bulk operations, nested creates, and extension points
- REST API with filtering, sorting, pagination, and OpenAPI docs
- GraphQL API (Strawberry) with queries, mutations, connections, and subscriptions stubs
- MCP server (FastMCP) so AI assistants can interact with your data
- Alembic migrations
- JWT authentication with RBAC, OAuth (GitHub/Google), email verification, password reset
- API key authentication
- Admin panel with role-based access

**Frontend** — React 19 / TypeScript / Vite / Tailwind CSS
- TypeScript types mirroring your backend schemas
- React components (list, detail, create, edit) with the Nordic design system
- Data-fetching hooks (REST and GraphQL)
- Client-side routing with protected routes
- Auth pages (login, signup, password reset, profile)
- Admin dashboard
- Landing page, error pages, search
- Headless component architecture with pluggable widgets

**Infrastructure & DevOps**
- Docker Compose for dev and production (with Traefik reverse proxy)
- GitHub Actions CI/CD with Codecov, semantic-release, Dependabot, commitlint
- Hetzner Cloud deployment via Terraform
- Dev container with Claude Code integration

**Testing**
- Backend tests (pytest) and frontend tests (Vitest + React Testing Library)
- Generated automatically from your spec

## Spec as Code

Everything starts with a Python file. No YAML, no GUI — just Pydantic models with full IDE support.

```python
# specs/models.py
from prisme import (
    StackSpec, ModelSpec, FieldSpec, FieldType, FilterOperator,
    RESTExposure, GraphQLExposure, MCPExposure, FrontendExposure,
)

spec = StackSpec(
    name="my-crm",
    version="1.0.0",
    description="Customer Relationship Management",
    models=[
        ModelSpec(
            name="Customer",
            soft_delete=True,
            timestamps=True,
            fields=[
                FieldSpec(
                    name="name",
                    type=FieldType.STRING,
                    max_length=255,
                    required=True,
                    searchable=True,
                    filter_operators=[FilterOperator.EQ, FilterOperator.ILIKE],
                ),
                FieldSpec(
                    name="email",
                    type=FieldType.STRING,
                    max_length=255,
                    required=True,
                    unique=True,
                    ui_widget="email",
                ),
                FieldSpec(
                    name="status",
                    type=FieldType.ENUM,
                    enum_values=["active", "inactive", "prospect"],
                    default="prospect",
                ),
            ],
            rest=RESTExposure(enabled=True, tags=["customers"]),
            graphql=GraphQLExposure(enabled=True, use_connection=True),
            mcp=MCPExposure(enabled=True, tool_prefix="customer"),
            frontend=FrontendExposure(enabled=True, nav_label="Customers"),
        ),
    ],
)
```

**13 field types** (STRING, TEXT, INTEGER, FLOAT, DECIMAL, BOOLEAN, DATETIME, DATE, TIME, UUID, JSON, ENUM, FOREIGN_KEY) and **17 filter operators** give you fine-grained control over every field.

## Selective Exposure

Each model independently controls which APIs and UI it exposes:

```python
ModelSpec(
    name="InternalMetric",
    rest=RESTExposure(enabled=True),        # REST API only
    graphql=GraphQLExposure(enabled=False),  # No GraphQL
    mcp=MCPExposure(enabled=False),          # No MCP tools
    frontend=FrontendExposure(enabled=False), # No UI pages
)
```

## Extend, Don't Overwrite

Prism uses four file strategies to keep your customizations safe:

| Strategy | Behavior | Use case |
|---|---|---|
| `ALWAYS_OVERWRITE` | Regenerated every time | Types, schemas, generated code |
| `GENERATE_ONCE` | Created once, never touched again | Custom pages, user-written services |
| `GENERATE_BASE` | Base class regenerated, your extension preserved | Service layer, components |
| `MERGE` | Smart merge with protected regions | Router assembly, app providers |

Protected regions (`// PRISM:PROTECTED:START` / `// PRISM:PROTECTED:END`) let you embed custom code inside regenerated files — Prism preserves those blocks on every regeneration.

## Project Templates

Start with the template that fits your use case:

```bash
prisme create my-app                          # Full-stack (default)
prisme create my-app --template minimal       # Backend only
prisme create my-app --template api-only      # API without frontend
prisme create my-app --template mcp-only      # MCP server only
prisme create my-app --template website       # Content website
prisme create my-app --template saas          # SaaS with auth + billing
prisme create my-app --template enterprise-platform  # Enterprise with admin
```

Options: `--database sqlite|postgresql`, `--package-manager npm|pnpm|yarn`, `--docker`, `--no-ci`, and more.

## Authentication & Authorization

Toggle in your spec — generated end-to-end:

- **JWT authentication** with access/refresh tokens
- **Role-based access control** (RBAC) with custom roles and permissions
- **OAuth** (GitHub, Google) with configurable providers
- **API key authentication** for service-to-service communication
- **Email verification** and **password reset** via Resend
- **Signup whitelisting** and access control
- **Admin panel** with role-gated views

## Design System

The generated frontend ships with the **Nordic** design system (Tailwind-based), with additional presets:

- **3 theme presets**: Nordic, Minimal, Corporate
- **Dark mode** with light/dark/system toggle
- **2 icon sets**: Lucide React, Heroicons
- **Customizable** colors, fonts, border radius, and animations

## Docker & Deployment

```bash
# Local development with Docker
prisme create my-app --docker
prisme dev --docker
# → app available at http://my-app.localhost

# Production deployment to Hetzner Cloud
prisme deploy init --domain example.com
prisme deploy apply -e production
```

- Shared **Traefik** reverse proxy — run multiple projects simultaneously
- Automatic **subdomain routing** (`project-name.localhost`)
- Production Docker Compose with replicas and SSL
- **Terraform** templates for Hetzner Cloud with staging/production environments

## CLI Reference

Prism ships with **88 CLI commands** across project lifecycle, code generation, testing, Docker, deployment, and more:

```bash
# Core workflow
prisme create my-project       # Scaffold a new project
prisme install                 # Install backend + frontend dependencies
prisme generate                # Generate code from spec
prisme generate --dry-run      # Preview changes without writing
prisme generate --diff         # Show diff of what would change
prisme test                    # Run all tests (backend + frontend)
prisme dev                     # Start dev servers (backend + frontend)
prisme dev --watch             # Watch spec for changes and regenerate
prisme validate specs/models.py  # Validate your spec

# Database
prisme db migrate              # Create and apply Alembic migrations
prisme db seed                 # Seed with test data
prisme db reset                # Reset database

# Docker
prisme docker init             # Generate Docker dev config
prisme docker init-prod --domain example.com  # Production config
prisme dev --docker            # Run everything in Docker

# CI/CD
prisme ci init                 # Generate GitHub Actions workflows

# Deployment
prisme deploy init             # Initialize Terraform config
prisme deploy apply -e staging # Deploy to staging
prisme deploy ssh production   # SSH into production server

# Override management
prisme review list             # See what you've customized
prisme review diff <file>      # Diff a customized file
```

See `prisme --help` for the full command tree.

## Technology Stack

| Layer | Technology |
|-------|------------|
| Specification | Pydantic (Python 3.13+) |
| Database | PostgreSQL / SQLite |
| ORM | SQLAlchemy (async) |
| Migrations | Alembic |
| REST API | FastAPI |
| GraphQL | Strawberry GraphQL |
| MCP | FastMCP |
| Auth | JWT + OAuth + API Keys |
| Frontend | React 19 + TypeScript + Vite + Tailwind CSS |
| Testing | pytest / Vitest + React Testing Library |
| Containers | Docker + Traefik |
| CI/CD | GitHub Actions + semantic-release |
| Deployment | Terraform (Hetzner Cloud) |

## Under the Hood

Prism's generator pipeline:

```
StackSpec → validate → GeneratorContext → 30 generators → 278 Jinja2 templates → your project
```

- **30 generators** (11 backend, 15 frontend, 2 testing, 2 infrastructure)
- **278 Jinja2 templates** producing static, inspectable output
- **Manifest tracking** detects which files you've customized
- **Protected region** parsing preserves inline customizations

## Installation

```bash
# Using uv (recommended)
uv add prisme

# Using pip
pip install prisme
```

Requires Python 3.13+. Published on [PyPI](https://pypi.org/project/prisme/).

## Documentation

Full documentation at **[prisme.readthedocs.io](https://prisme.readthedocs.io/)**:

- [Getting Started](https://prisme.readthedocs.io/getting-started/) — Installation and quickstart
- [User Guide](https://prisme.readthedocs.io/user-guide/) — CLI reference, spec guide, extensibility
- [Tutorials](https://prisme.readthedocs.io/tutorials/) — Step-by-step project tutorials
- [API Reference](https://prisme.readthedocs.io/reference/) — Specification class reference
- [Architecture](https://prisme.readthedocs.io/architecture/) — Design principles and internals

## Contributing

Contributions welcome. See [CONTRIBUTING.md](CONTRIBUTING.md) for setup, commit conventions, and development workflow.

```bash
git clone https://github.com/Lasse-numerous/prisme.git && cd prisme
uv sync --all-extras
uv run pre-commit install --hook-type pre-commit --hook-type commit-msg --hook-type pre-push
uv run pytest
```

## License

MIT License — see [LICENSE](LICENSE) for details.

Copyright (c) 2026 Numerous ApS
