# Quick Start Guide

Get started with FraiseQL in 5 minutes! This guide will walk you through creating a simple note-taking GraphQL API.

## Prerequisites

- **Python 3.13+** (required for FraiseQL's Rust pipeline and advanced features)
- **PostgreSQL 13+**

## Step 1: Install FraiseQL

```bash
pip install fraiseql[all]
```

## Step 2: Create Database

Create a PostgreSQL database for your notes:

```bash
createdb quickstart_notes
```

## Step 3: Set Up Database Schema

Create a file called `schema.sql` with this content:

```sql
-- Simple notes table with trinity pattern
CREATE TABLE tb_note (
    pk_note INT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,  -- Internal fast joins
    id UUID UNIQUE NOT NULL DEFAULT gen_random_uuid(),         -- Public API
    identifier TEXT UNIQUE,                                     -- Optional human-readable identifier
    title VARCHAR(200) NOT NULL,
    content TEXT,
    created_at TIMESTAMP DEFAULT NOW()
);

-- Notes view for GraphQL queries
CREATE VIEW v_note AS
SELECT
    id,
    jsonb_build_object(
        'id', id,                            -- UUID for GraphQL API
        'title', title,
        'content', content,
        'created_at', created_at
    ) AS data
FROM tb_note;

-- SQL function for creating notes (CQRS pattern)
CREATE OR REPLACE FUNCTION fn_create_note(input jsonb)
RETURNS jsonb AS $$
DECLARE
    new_id uuid;
BEGIN
    INSERT INTO tb_note (title, content)
    VALUES (input->>'title', input->>'content')
    RETURNING id INTO new_id;

    RETURN jsonb_build_object('success', true, 'id', new_id);
END;
$$ LANGUAGE plpgsql;

-- Sample data
INSERT INTO tb_note (title, content) VALUES
    ('Welcome to FraiseQL', 'This is your first note!'),
    ('GraphQL is awesome', 'Queries and mutations made simple'),
    ('Database-first design', 'Views compose data for optimal performance');
```

Run the schema:

```bash
psql quickstart_notes < schema.sql
```

## Step 4: Create Your GraphQL API

Create a file called `app.py` with this complete code:

```python
import uuid
from datetime import datetime
import uvicorn
import fraiseql
from fraiseql.fastapi import create_fraiseql_app

# Define GraphQL types
@fraiseql.type(sql_source="v_note", jsonb_column="data")
class Note:
    """A simple note with title and content."""
    id: uuid.UUID
    title: str
    content: str | None
    created_at: datetime

# Define input types
@fraiseql.input
class CreateNoteInput:
    """Input for creating a new note."""
    title: str
    content: str | None = None

# Define success/failure types
@fraiseql.success
class CreateNoteSuccess:
    """Success response for note creation."""
    note: Note
    message: str = "Note created successfully"

@fraiseql.failure
class ValidationError:
    """Validation error."""
    message: str
    code: str = "VALIDATION_ERROR"

# Queries
@fraiseql.query
async def notes(info) -> list[Note]:
    """Get all notes."""
    db = info.context["db"]
    return await db.find("v_note", "notes", info, order_by=[("created_at", "DESC")])

@fraiseql.query
async def note(info, id: uuid.UUID) -> Note | None:
    """Get a single note by ID."""
    db = info.context["db"]
    return await db.find_one("v_note", "note", info, id=id)

# Mutations
@fraiseql.mutation
class CreateNote:
    """Create a new note."""
    input: CreateNoteInput
    success: CreateNoteSuccess
    failure: ValidationError

    async def resolve(self, info) -> CreateNoteSuccess | ValidationError:
        db = info.context["db"]

        try:
            # Call SQL function (CQRS pattern)
            result = await db.execute_function("fn_create_note", {
                "title": self.input.title,
                "content": self.input.content,
            })

            if not result.get("success"):
                return ValidationError(message="Failed to create note")

            # Fetch the created note via Rust pipeline
            note = await db.find_one("v_note", "note", info, id=result["id"])
            return CreateNoteSuccess(note=note)

        except Exception as e:
            return ValidationError(message=f"Failed to create note: {e!s}")

# Create the app
QUICKSTART_TYPES = [Note]
QUICKSTART_QUERIES = [notes, note]
QUICKSTART_MUTATIONS = [CreateNote]

if __name__ == "__main__":
    import os

    # Database URL (override with DATABASE_URL environment variable)
    database_url = os.getenv("DATABASE_URL", "postgresql://localhost/quickstart_notes")

    app = create_fraiseql_app(
        database_url=database_url,
        types=QUICKSTART_TYPES,
        queries=QUICKSTART_QUERIES,
        mutations=QUICKSTART_MUTATIONS,
        title="Notes API",
        description="Simple note-taking GraphQL API",
        production=False,  # Enable GraphQL playground
    )

    print("🚀 Notes API running at http://localhost:8000/graphql")
    print("📖 GraphQL Playground: http://localhost:8000/graphql")

    uvicorn.run(app, host="0.0.0.0", port=8000)
```

## Step 5: Run Your API

```bash
python app.py
```

Visit `http://localhost:8000/graphql` to open the GraphQL Playground!

## Step 6: Try Your First Queries

### Get all notes:
```graphql
query {
  notes {
    id
    title
    content
    createdAt
  }
}
```

### Get a specific note:
```graphql
query {
  note(id: "550e8400-e29b-41d4-a716-446655440000") {
    id
    title
    content
    createdAt
  }
}
```

**Note**: Replace the UUID with an actual ID from your database. You can get IDs from the `notes` query above.

### Create a new note:
```graphql
mutation {
  createNote(input: { title: "My New Note", content: "This is awesome!" }) {
    ... on CreateNoteSuccess {
      note {
        id
        title
        content
        createdAt
      }
      message
    }
    ... on ValidationError {
      message
      code
    }
  }
}
```

## What Just Happened?

🎉 **Congratulations!** You just built a complete GraphQL API with:

- **Database Schema**: PostgreSQL table and JSONB view
- **GraphQL Types**: Note type with proper typing
- **Queries**: Get all notes and get note by ID
- **Mutations**: Create new notes with success/failure handling
- **FastAPI Integration**: Ready-to-deploy web server

## Next Steps

- [Understanding FraiseQL](../guides/understanding-fraiseql.md) - Learn the architecture
- [First Hour Guide](first-hour.md) - Progressive tutorial
- [Troubleshooting](../guides/troubleshooting.md) - Common issues and solutions
- Examples (../../examples/) - More complete examples
- [Style Guide](../development/style-guide.md) - Best practices

## Need Help?

- [GitHub Discussions](../discussions)
- [Documentation](https://docs.fraiseql.com)
- [Troubleshooting Guide](../guides/troubleshooting.md)

---

Ready to build something amazing? Let's go! 🚀
