# Quickstart

Build and run an in-memory SQLite CRUD service in less than 5 minutes.

Source: /docs/quickstart

This guide gets a runnable Brick-TS service running locally with Bun and SQLite in less than five minutes.

## 1. Install Dependencies

Initialize a new Bun project and install `@brickkit/core`, `@brickkit/crud`, and `@brickkit/cli`:

**bun**

```bash
mkdir my-brick-app && cd my-brick-app
bun init -y
bun add @brickkit/core @brickkit/crud @brickkit/cli
```

**pnpm**

```bash
pnpm add @brickkit/core @brickkit/crud @brickkit/cli
```

**npm**

```bash
npm install @brickkit/core @brickkit/crud @brickkit/cli
```

## 2. Create the Application

Create `src/app.ts` with a SQLite table, a database handle, and a CRUD resource:

```ts title="src/app.ts"
import {
  brick,
  defineDatabase,
  defineService,
  sqliteTable,
  syncSchema,
  text,
} from "@brickkit/core";
import { crud } from "@brickkit/crud";

// Define the database table with Drizzle
export const pages = sqliteTable("pages", {
  id: text("id")
    .primaryKey()
    .$defaultFn(() => crypto.randomUUID()),
  title: text("title").notNull(),
  content: text("content"),
});

// Configure an in-memory database for immediate development
const database = defineDatabase({ tables: { pages } });
export const pagesService = defineService("pages", { database });

// Register the CRUD resource. CRUD requires an explicit access policy.
pagesService.resource({ name: "page", table: pages, id: pages.id }).use(
  crud({
    access: "public",
    fields: {
      id: { read: true, filter: ["eq"] },
      title: {
        read: true,
        create: true,
        update: true,
        filter: ["eq", "contains"],
        sort: true,
      },
      content: { read: true, create: true, update: true },
    },
  }),
);

// Prepare the in-memory SQLite table schema
syncSchema(pagesService);

// Export the default application for the brick CLI or embedded runtime
export const app = brick({
  services: [pagesService],
  title: "Pages API",
  version: "1.0.0",
});

export default app;
```

### Schema

These columns match the Drizzle tables in the example. Defaults marked as application defaults run in Drizzle, rather than in SQL.



#### Table Name: `pages`

| Field     | Type   | Description                                                   |
| --------- | ------ | ------------------------------------------------------------- |
| `id`      | `text` | Row identifier. PK Default: crypto.randomUUID() (application) |
| `title`   | `text` | Display title.                                                |
| `content` | `text` | Page content. Optional                                        |


## 3. Start the Server

Run the development server with live reload using the `brick` CLI:

```bash
bunx brick dev src/app.ts --port 4000
```

The CLI loads your entry, then prints the registered services and the route each action is mounted on:

```text
[Brick-TS] Loading application entry: /path/to/my-brick-app/src/app.ts

🧱 Brick-TS Development Server
   Registered Services: 1
   • pages (8 actions)
     -> POST   /api/page/query
     -> GET    /api/page/:id
     -> POST   /api/page
     -> PATCH  /api/page/:id
     -> DELETE /api/page/:id
     -> POST   /api/page/find-one
     -> POST   /api/page/count
     -> POST   /api/page/exists

⚡ API Gateway running on: http://localhost:4000
🩺 Health check:        http://localhost:4000/_health
🗺️ Architecture graph:  http://localhost:4000/_brick/services
```

CRUD routes are mounted under the resource name (`page`), not the service name. The action names are still `page.list`, `page.get`, `page.create`, and so on.

> `brick dev` imports your entry to register its services, then builds its own
> server with the default `/api` prefix. Options you pass to `brick()` in the
> entry (such as `title`) don't apply under `brick dev`. Without `--port`, the
> port comes from the `PORT` environment variable, then defaults to `4000`.

## 4. Test the API Endpoints

Execute HTTP requests against the generated CRUD endpoints. Successful calls return `200` with the JSON result.

### Create a Record

```bash
curl -X POST http://localhost:4000/api/page \
  -H "Content-Type: application/json" \
  -d '{"title": "First Page", "content": "Welcome to Brick-TS!"}'
```

Response:

```json
{
  "id": "e379b38c-8f19-485a-a71c-3b91ef5246a4",
  "title": "First Page",
  "content": "Welcome to Brick-TS!"
}
```

### List Records with Filtering

`page.list` is a `POST` to `/api/page/query`. The body is validated against the filter operators and sortable fields you enabled in `fields`:

```bash
curl -X POST http://localhost:4000/api/page/query \
  -H "Content-Type: application/json" \
  -d '{
    "where": {
      "field": "title",
      "op": "contains",
      "value": "First"
    },
    "orderBy": [{ "field": "title", "direction": "asc" }],
    "limit": 10
  }'
```

Response:

```json
{
  "items": [
    {
      "id": "e379b38c-8f19-485a-a71c-3b91ef5246a4",
      "title": "First Page",
      "content": "Welcome to Brick-TS!"
    }
  ],
  "limit": 10,
  "offset": 0
}
```

### View Interactive API Documentation

Visit the interactive API documentation and spec endpoints provided out of the box. They're mounted at the root, not under the `/api` prefix:

- Scalar API Docs: `http://localhost:4000/docs`
- Swagger UI: `http://localhost:4000/swagger`
- OpenAPI 3.1 Spec: `http://localhost:4000/openapi.json`
- Service Architecture Graph: `http://localhost:4000/_brick/services`
- Health Check: `http://localhost:4000/_health`
