# Project structure

See the files in the project and what each one is for.

You have followed [Installation](/docs/start/installation) and [First schema](/docs/start/first-schema), or you have a directory with `package.json` and a Bun lockfile.

Use the tutorial layout when the files stay flat, the driver is postgres.js, you apply with [`okm push`](/docs/reference/cli/migrate#push), and the database can be recreated. Use the `okm init` layout when the schema and the client live in `db/`, the SQL files live in `migrations/`, and the scripts are check, plan, apply, and status.

<Steps>

<Step>
### Tutorial files

The tutorial writes these files in the project directory. `schema.ts` default-exports the notes schema. `okmodel.config.ts` is the file `okm push` reads. `db.ts` is the client. `check.ts` waits until the startup check finishes. `insert.ts`, `find.ts`, `one.ts`, `count.ts`, `exists.ts`, `update.ts`, and `delete.ts` are the calls. `find-without-limit.ts` and `update-without-where.ts` are the calls that throw OKM1101 and OKM1102.

</Step>

<Step>
### `okm init`

`okm init` writes starter files. It does not connect. In a directory whose `package.json` name is `notes`, with a `bun.lock` and no driver package, and with no terminal, `bunx okm init` writes this tree. A Bun project with no driver package selects `bun-sql`. The tutorial installs postgres.js and imports `okmodel/pg/postgresjs`.

```sh
bunx okm init
```

```text title="init.tree"
.
├── .env.example
├── .gitattributes
├── .gitignore
├── .okm
│   └── init.json
├── db
│   ├── client.ts
│   └── schema.ts
├── migrations
│   └── .gitkeep
├── okmodel.config.ts
└── package.json
```

</Step>

<Step>
### Files `okm init` writes

| File | What it is for |
| --- | --- |
| `db/schema.ts` | Example `users` table. `t.id()`, `minPostgres: 15`, and a named `app` schema. |
| `db/client.ts` | The client. An empty `DATABASE_URL` is refused. This run imports `okmodel/pg/bun`. `connect` includes `limits`. The library does not set them unless that object is there. [Query limits](/docs/operate/query-limits). |
| `okmodel.config.ts` | `schema` is `./db/schema.ts`. `migrations` is `./migrations`. `database` is set only when `DATABASE_URL` is a non-empty string. |
| `migrations/.gitkeep` | The migrations directory. |
| `.env.example` | `DATABASE_URL=` with no value. Init does not write `.env`. |
| `.gitattributes` | Line endings for migration SQL, catalog JSON, and `.okm`. |
| `.gitignore` | `.env` and `.env.local`. |
| `package.json` | Adds the `okmodel` dependency and `db:check`, `db:plan`, `db:apply`, and `db:status`. |
| `.okm/init.json` | The choices and the hash of each file init wrote. |

`db/client.ts` passes this `limits` object. `find` 100 covers `find`, `descendants`, and `ancestors`. `include` 20 is a to-many include. `page` 50 is `page()`. `groupBy` 500 is a grouped aggregate. `max` 1000 is the ceiling. `.all(reason)` reads past them. A `limit` on the call wins.

```ts
import { connect } from "okmodel/pg/postgresjs";
import { schema, table, t } from "okmodel/pg";

const users = table("users", {
  id: t.id(),
  email: t.text(),
  createdAt: t.timestamptz(),
});
const app = schema({ minPostgres: 15, tables: [users] });

const url = process.env.DATABASE_URL;
if (url === undefined || url.length === 0) {
  throw new Error("DATABASE_URL is not set");
}

export const db = connect(url, {
  schema: app,
  limits: { find: 100, include: 20, page: 50, groupBy: 500, max: 1000 },
});
```

The command ends with the next three commands.

```text title="init.next"
bun run --bun okm check
bun run --bun okm migrate plan init
bun run --bun okm migrate apply
```

[`okm generate init`](/docs/reference/cli/migrate#generate) writes the first migration. That is a different command. The tutorial uses [`okm push`](/docs/reference/cli/migrate#push).

</Step>

</Steps>

| Next | You use it for |
| --- | --- |
| [First migration](/docs/start/first-migration) | Generate the first SQL file, then apply one change. |
| [Queries](/docs/queries) | The rest of the calls on a table. |
| [Config](/docs/reference/config) | Targets, paths, timeouts, and roles. |
| [Safe use](/docs/operate/using-okmodel-safely) | Pin the lockfile, wait before updating, and read provenance. |

Index: [/llms.txt](/llms.txt)
