---
import DocsLayout from '../../layouts/DocsLayout.astro';
import CodeBlock from '../../components/CodeBlock.astro';
const schemaExample = `// =============================================================================
// Datasource: Database provider and extensions
// Connection URL is configured in prax.toml
// =============================================================================
datasource db {
provider = "postgresql"
// extensions = [vector, pg_trgm] // Optional: PostgreSQL extensions
}
// =============================================================================
// Generator: Code generation settings
// =============================================================================
generator client {
provider = "prax-client-rust"
output = "./src/generated"
plugins = ["serde", "graphql"]
}
// =============================================================================
// Enums: Type-safe enumerated values
// =============================================================================
enum Role {
USER
ADMIN
MODERATOR
}
enum Status {
DRAFT
PUBLISHED
ARCHIVED
}
// =============================================================================
// Models: Database tables
// =============================================================================
/// User accounts in the system
model User {
id Int @id @auto
email String @unique @validate.email
name String?
role Role @default(USER)
posts Post[]
profile Profile?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([email])
@@map("users")
}
/// Blog posts
model Post {
id Int @id @auto
title String
content String? @db.Text
status Status @default(DRAFT)
author User @relation(fields: [authorId], references: [id])
authorId Int @map("author_id")
tags Tag[]
createdAt DateTime @default(now())
@@index([authorId, status])
@@map("posts")
}
/// User profiles (one-to-one with User)
model Profile {
id Int @id @auto
bio String? @db.Text
avatar String?
userId Int @unique
user User @relation(fields: [userId], references: [id])
}
/// Tags for posts (many-to-many)
model Tag {
id Int @id @auto
name String @unique
posts Post[]
}
// =============================================================================
// Views: Read-only aggregated data
// =============================================================================
view UserStats {
id Int
email String
postCount Int @map("post_count")
@@sql("""
SELECT u.id, u.email, COUNT(p.id) as post_count
FROM users u
LEFT JOIN posts p ON p.author_id = u.id
GROUP BY u.id, u.email
""")
}`;
const fileStructure = `my-project/
├── prax.toml # Configuration (project root)
├── prax/ # Prax directory
│ ├── schema.prax # Your schema definition
│ └── migrations/ # Database migrations
│ ├── 001_init/
│ └── 002_add_roles/
├── src/
│ ├── generated/ # Generated client code
│ │ ├── mod.rs
│ │ ├── user.rs
│ │ └── post.rs
│ └── main.rs
└── .env # Environment variables`;
const simpleSchema = `// Minimal schema example
// Database URL is in prax.toml: [database] url = "..."
datasource db {
provider = "postgresql"
}
generator client {
provider = "prax-client-rust"
output = "./src/generated"
}
model User {
id Int @id @auto
email String @unique
name String?
}`;
const workflowSteps = `# 1. Define your schema
edit prax/schema.prax
# 2. Generate the Rust client
prax generate
# 3. Create a migration (SQL only — the CLI does not apply it in v0.11)
prax migrate dev --name init --create-only
# 4. Apply the generated SQL with your database tool
psql "$DATABASE_URL" -f prax/migrations/<timestamp>_init/migration.sql
# (or mysql / sqlite3 for other backends)
# 5. Use in your Rust code
use generated::*;`;
---
<DocsLayout title="Schema Overview - Prax ORM">
<article class="max-w-4xl mx-auto px-6 py-12">
<header class="mb-12">
<h1 class="text-4xl font-bold mb-4">Schema Overview</h1>
<p class="text-xl text-muted">
The Prax schema is a declarative language for defining your data models, relationships,
and database configuration in a single, type-safe file.
</p>
</header>
<div class="space-y-12">
<!-- Introduction -->
<section>
<h2 class="text-2xl font-semibold mb-4">What is a Schema?</h2>
<p class="text-muted mb-4">
A Prax schema is a text file (located at <code class="px-2 py-1 bg-surface-elevated rounded">prax/schema.prax</code>)
that serves as the single source of truth for your database structure. It defines:
</p>
<ul class="list-disc list-inside text-muted space-y-2 mb-6">
<li><strong>Datasources</strong> - Database connection configuration</li>
<li><strong>Generators</strong> - Code generation settings and plugins</li>
<li><strong>Models</strong> - Database tables and their columns</li>
<li><strong>Enums</strong> - Type-safe enumerated values</li>
<li><strong>Relations</strong> - Connections between models</li>
<li><strong>Views</strong> - Read-only aggregated data</li>
</ul>
<p class="text-muted mb-4">
Prax uses your schema to generate type-safe Rust code, create database migrations,
and validate your queries at compile time.
</p>
</section>
<!-- Quick Start -->
<section>
<h2 class="text-2xl font-semibold mb-4">Minimal Schema</h2>
<p class="text-muted mb-4">
Here's the simplest possible schema to get started:
</p>
<CodeBlock code={simpleSchema} lang="prax" filename="prax/schema.prax" />
</section>
<!-- Full Example -->
<section>
<h2 class="text-2xl font-semibold mb-4">Complete Example</h2>
<p class="text-muted mb-4">
A production-ready schema demonstrating all major features:
</p>
<CodeBlock code={schemaExample} lang="prax" filename="prax/schema.prax" />
</section>
<!-- Schema Components -->
<section>
<h2 class="text-2xl font-semibold mb-4">Schema Components</h2>
<p class="text-muted mb-4">
Click on any component to learn more:
</p>
<div class="grid md:grid-cols-2 gap-4">
<a href="/schema/generators"
class="p-6 rounded-xl bg-surface border border-border hover:border-primary-500/50 transition-colors group">
<div class="flex items-center gap-3 mb-2">
<svg class="w-6 h-6 text-primary-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"/>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/>
</svg>
<h3 class="text-lg font-semibold group-hover:text-primary-400 transition-colors">Datasources & Generators</h3>
</div>
<p class="text-muted text-sm">
Configure database connections, code generation output, and plugins.
</p>
</a>
<a href="/schema/models"
class="p-6 rounded-xl bg-surface border border-border hover:border-primary-500/50 transition-colors group">
<div class="flex items-center gap-3 mb-2">
<svg class="w-6 h-6 text-primary-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10"/>
</svg>
<h3 class="text-lg font-semibold group-hover:text-primary-400 transition-colors">Models</h3>
</div>
<p class="text-muted text-sm">
Define database tables, primary keys, indexes, and constraints.
</p>
</a>
<a href="/schema/fields"
class="p-6 rounded-xl bg-surface border border-border hover:border-primary-500/50 transition-colors group">
<div class="flex items-center gap-3 mb-2">
<svg class="w-6 h-6 text-primary-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 10h16M4 14h16M4 18h16"/>
</svg>
<h3 class="text-lg font-semibold group-hover:text-primary-400 transition-colors">Fields & Types</h3>
</div>
<p class="text-muted text-sm">
Scalar types, type modifiers, default values, and database-specific types.
</p>
</a>
<a href="/schema/relations"
class="p-6 rounded-xl bg-surface border border-border hover:border-primary-500/50 transition-colors group">
<div class="flex items-center gap-3 mb-2">
<svg class="w-6 h-6 text-primary-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13.828 10.172a4 4 0 00-5.656 0l-4 4a4 4 0 105.656 5.656l1.102-1.101m-.758-4.899a4 4 0 005.656 0l4-4a4 4 0 00-5.656-5.656l-1.1 1.1"/>
</svg>
<h3 class="text-lg font-semibold group-hover:text-primary-400 transition-colors">Relations</h3>
</div>
<p class="text-muted text-sm">
One-to-one, one-to-many, many-to-many relationships and referential actions.
</p>
</a>
<a href="/schema/attributes"
class="p-6 rounded-xl bg-surface border border-border hover:border-primary-500/50 transition-colors group">
<div class="flex items-center gap-3 mb-2">
<svg class="w-6 h-6 text-primary-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 7h.01M7 3h5c.512 0 1.024.195 1.414.586l7 7a2 2 0 010 2.828l-7 7a2 2 0 01-2.828 0l-7-7A1.994 1.994 0 013 12V7a4 4 0 014-4z"/>
</svg>
<h3 class="text-lg font-semibold group-hover:text-primary-400 transition-colors">Attributes</h3>
</div>
<p class="text-muted text-sm">
Field and model attributes for validation, mapping, defaults, and more.
</p>
</a>
<a href="/schema/enums"
class="p-6 rounded-xl bg-surface border border-border hover:border-primary-500/50 transition-colors group">
<div class="flex items-center gap-3 mb-2">
<svg class="w-6 h-6 text-primary-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"/>
</svg>
<h3 class="text-lg font-semibold group-hover:text-primary-400 transition-colors">Enums</h3>
</div>
<p class="text-muted text-sm">
Type-safe enumerated values with database-level enforcement.
</p>
</a>
<a href="/schema/views"
class="p-6 rounded-xl bg-surface border border-border hover:border-primary-500/50 transition-colors group">
<div class="flex items-center gap-3 mb-2">
<svg class="w-6 h-6 text-primary-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"/>
</svg>
<h3 class="text-lg font-semibold group-hover:text-primary-400 transition-colors">Views</h3>
</div>
<p class="text-muted text-sm">
Read-only database views with custom SQL for aggregations and joins.
</p>
</a>
</div>
</section>
<!-- File Structure -->
<section>
<h2 class="text-2xl font-semibold mb-4">Project Structure</h2>
<p class="text-muted mb-4">
Prax uses a dedicated <code class="px-2 py-1 bg-surface-elevated rounded">prax/</code> directory
for the schema and migrations:
</p>
<CodeBlock code={fileStructure} lang="text" />
</section>
<!-- Workflow -->
<section>
<h2 class="text-2xl font-semibold mb-4">Schema Workflow</h2>
<p class="text-muted mb-4">
The typical workflow when working with Prax schemas:
</p>
<CodeBlock code={workflowSteps} lang="bash" />
<div class="mt-6 grid gap-4">
<div class="flex items-start gap-4 p-4 rounded-xl bg-surface border border-border">
<div class="w-8 h-8 rounded-full bg-primary-500 text-white flex items-center justify-center flex-shrink-0 font-bold">1</div>
<div>
<h4 class="font-semibold mb-1">Define Schema</h4>
<p class="text-muted text-sm">Write your models, enums, and relations in <code class="px-1 bg-surface-elevated rounded">prax/schema.prax</code></p>
</div>
</div>
<div class="flex items-start gap-4 p-4 rounded-xl bg-surface border border-border">
<div class="w-8 h-8 rounded-full bg-primary-500 text-white flex items-center justify-center flex-shrink-0 font-bold">2</div>
<div>
<h4 class="font-semibold mb-1">Generate Client</h4>
<p class="text-muted text-sm">Run <code class="px-1 bg-surface-elevated rounded">prax generate</code> to create type-safe Rust code</p>
</div>
</div>
<div class="flex items-start gap-4 p-4 rounded-xl bg-surface border border-border">
<div class="w-8 h-8 rounded-full bg-primary-500 text-white flex items-center justify-center flex-shrink-0 font-bold">3</div>
<div>
<h4 class="font-semibold mb-1">Create Migration</h4>
<p class="text-muted text-sm">Run <code class="px-1 bg-surface-elevated rounded">prax migrate dev --create-only</code> to generate SQL migration files</p>
</div>
</div>
<div class="flex items-start gap-4 p-4 rounded-xl bg-surface border border-border">
<div class="w-8 h-8 rounded-full bg-primary-500 text-white flex items-center justify-center flex-shrink-0 font-bold">4</div>
<div>
<h4 class="font-semibold mb-1">Apply</h4>
<p class="text-muted text-sm">Apply the generated SQL with your database tool (psql, mysql, sqlite3) — <code class="px-1 bg-surface-elevated rounded">prax migrate deploy</code> is not yet implemented</p>
</div>
</div>
</div>
</section>
<!-- Next Steps -->
<section>
<h2 class="text-2xl font-semibold mb-4">Next Steps</h2>
<div class="p-6 rounded-xl bg-gradient-to-r from-primary-500/10 to-primary-700/10 border border-primary-500/30">
<p class="text-muted mb-4">
Ready to dive deeper? Start with <a href="/schema/models" class="text-primary-400 hover:text-primary-300 underline">Models</a>
to learn how to define your database tables, then explore
<a href="/schema/fields" class="text-primary-400 hover:text-primary-300 underline">Fields & Types</a>
for the full type system.
</p>
<div class="flex flex-wrap gap-3">
<a href="/schema/models"
class="px-4 py-2 bg-primary-500 hover:bg-primary-600 text-white rounded-lg text-sm font-medium transition-colors">
Learn about Models →
</a>
<a href="/quickstart"
class="px-4 py-2 bg-surface hover:bg-surface-elevated border border-border rounded-lg text-sm font-medium transition-colors">
Quick Start Guide
</a>
</div>
</div>
</section>
</div>
</article>
</DocsLayout>