# Tutorials overview

Map of the runnable example apps under examples/, from focused ORM ports to full showcase apps.

`examples/` holds runnable, zero-infrastructure apps. Most run with `go test ./examples/...`. The larger apps (`showcase`, `todo`, `bookings`, `demoapp`, `external-sms`) are separate Go modules; build and test them by path.

New to Zever? Do [Build a booking API](https://zenta-dev.github.io/zever/tutorials/build-a-booking-api/) first, then [Explore the showcase app](https://zenta-dev.github.io/zever/tutorials/explore-the-showcase-app/) for DSL breadth.

## Full apps

| App | What it proves |
|---|---|
| `examples/bookings` | Marketplace domain (hosts list spaces, guests book them); walked through in [Build a booking API](https://zenta-dev.github.io/zever/tutorials/build-a-booking-api/). `payment` stub charges, `billing`, `ratelimit`, `idempotency`, `lock`, and `queue` compose in one booking request. |
| `examples/showcase` | DSL depth: every schema feature in one shop schema, HTTP and gRPC parity; walked through in [Explore the showcase app](https://zenta-dev.github.io/zever/tutorials/explore-the-showcase-app/). |
| `examples/demoapp` | Battery breadth: every service battery behind one HTTP API; adapter swaps stay config-only. |
| `examples/todo` | Auth-gated notes app with HTTP and gRPC parity tests. JWT auth is enforced identically on both transports. |

## Focused ORM ports

Each app proves one ORM feature end to end against sqlite.

| App | What it proves |
|---|---|
| `examples/transactions` | `orm.WithNestedTx` savepoint-nested transfers: a failed inner transfer rolls back to its savepoint, not the outer transaction. |
| `examples/bulk_upsert` | Multi-row `Insert`, `OnConflict(...).DoUpdate/DoNothing`, `Returning().ExecReturning`: one round trip, per-row conflict resolution. |
| `examples/pagination` | Offset paging (`Limit`/`Offset`/`Count`) and keyset paging (`AfterTuple`, cursors): stable traversal with concurrent inserts. |
| `examples/recursive_cte` | `orm.WithRecursive`: an org chart in one query, with no N+1. |
| `examples/json_query` | `orm/json/sqlite` nested-key, key-exists, and array-membership filters. |
| `examples/fts` | `orm/fts/sqlite` full-text `MATCH` with rank-ordered search. |
| `examples/ormdrill` | Cursors, preload, joins, subqueries, and expressions without codegen (the raw builder). |

Every service battery (`cache`, `queue`, `db`, `payment`, `ai`, `vectorstore`, and the rest in the [Config reference](https://zenta-dev.github.io/zever/reference/config/)) also has `ExampleXxx` tests against its zero-infra adapter, with one happy path and one error path in `// Output:` comments. Browse them in `core/<battery>/example_test.go`.

## Run the examples

```sh
# examples that live in the `examples` module
go test ./examples/...        # zero infra, no setup needed
go test -race ./examples/...  # with the race detector

# the separate full-app modules, from the repo root (workspace-aware)
go test ./examples/showcase/...
go test ./examples/todo/...
go test ./examples/bookings/...

# one focused port
go test ./examples/pagination/... -v
```

Expected output:

```text
ok  	github.com/zenta-dev/zever/examples/pagination/cmd/app	0.008s
ok  	github.com/zenta-dev/zever/examples/fts/cmd/app	0.010s
ok  	github.com/zenta-dev/zever/examples/transactions/cmd/app	0.004s
...
```

The signal is `ok` on every line and no `FAIL`.

The focused ports open sqlite directly, so they ignore `DB_ADAPTER`. To run the ORM against postgres, use the ORM suite: `POSTGRES_DSN='postgres://user:pass@localhost:5432/test?sslmode=disable' go test ./orm/...`. Features a dialect lacks fail closed with `dialect.ErrUnsupportedByDialect`.

## Set up the full apps

```sh
cd examples/bookings
zever db migrate --adapter=sqlite --dsn=data/bookings.db schema/bookings.zen
go run ./db/seed
```

```text
OK applied 8 statement(s) via sqlite
{"time":"...","level":"INFO","msg":"seed complete"}
```

```sh
cd ../showcase
zever db migrate --adapter=sqlite --dsn=data/showcase.db schema/shop/shop.zen
go run ./db/seed
```

```text
OK applied 16 statement(s) via sqlite
{"time":"...","level":"INFO","msg":"seed complete"}
```

Both servers require `AUTH_JWT_SECRET` of at least 32 bytes and fail closed without it. Seed and worker output is JSON log lines (the `slog` adapter).

## How an example is laid out

1. `schema/*.zen` (full apps only) holds the domain. Never hand-edit `generated/` next to it.
2. `wiring.go` lists explicit typed providers.
3. `db/seed` holds idempotent demo data; `cmd/server` and `cmd/worker` mirror `zever generate server` / `zever generate worker`.
4. Tests sit next to the code they cover. The `// Output:` comments are runnable claims, not prose.

## Troubleshooting

<details>
<summary>`go test ./examples/...` fails on a clean clone</summary>

Cause: a half-downloaded module cache, which all modules share. Fix: run `go mod download`, then re-run.
</details>

<details>
<summary>A postgres-backed run fails to connect</summary>

Cause: the server is down, the database is missing, or the DSN is wrong. Fix: confirm the server and database, or unset the vars to fall back to sqlite.
</details>

<details>
<summary>Tests drifted after a schema edit</summary>

Cause: generated code is stale. Fix: regenerate with `zever compile` (see the showcase tutorial) and re-run `zever db migrate --dry-run` for fresh DDL. Never hand-edit `generated/`.
</details>

## Related

- [Build a booking API](https://zenta-dev.github.io/zever/tutorials/build-a-booking-api/): Guided walkthrough of the bookings flow.
- [Explore the showcase app](https://zenta-dev.github.io/zever/tutorials/explore-the-showcase-app/): A tour of DSL breadth over HTTP and gRPC.
- [Configuration](https://zenta-dev.github.io/zever/guides/operate/configuration/): Layered config.
- [Container](https://zenta-dev.github.io/zever/concepts/container/): How examples resolve services.
