# Quick Start

> Define a resource, generate a typed client, and read and write data end to end.

This walks through the full loop: define a model, compile it, generate the client, and use it in React. It takes about five minutes.

## 1. Define a resource

Resources are the single source of truth. A field whose type references another resource is a foreign key — the compiler infers the relation, so you never declare it twice.

```ts title="resources/airports.ts"
import { resource, s } from "rastack/define";

export const Airport = resource("airports", "airport", {
  code: s.string({ maxLength: 3, unique: true }),
  name: s.string({ maxLength: 120 }),
}, { search: ["code", "name"], admin: { listDisplay: ["code", "name"] } });

export const Terminal = resource("airports", "terminal", {
  airport: s.ref(() => Airport),   // FK — inferred from the field's type
  label: s.string({ maxLength: 20 }),
});
```

## 2. Compile

The compiler builds a `ts.Program` + `TypeChecker`, walks every `resource(...)` call, and reads each field's type to emit the canonical manifest and an OpenAPI document.

```bash title="terminal"
npx rastack compile
# → schema.rastack.json   (the canonical manifest)
# → openapi.json          (the /api/{app}/v1/{model}/ contract)
```

## 3. Generate the typed client

```bash title="terminal"
npx rastack generate
```

This reads `openapi.json` and emits one typed hook set per model — `useList*`, `useCreate*`, `useUpdate*`, `useDelete*` — into your repo.

## 4. Use it in React

Wrap your app in a provider (it picks where the engine runs), then import the hooks anywhere:

```tsx title="app/terminals.tsx"
import { RAStackProvider } from "rastack/provider";
import { useListTerminals, useCreateTerminal } from "@/entities";

export function Terminals() {
  const { data } = useListTerminals();          // typed rows
  const create = useCreateTerminal();
  return (
    <RAStackProvider mode="local">
      {data?.results.map((t) => <Text key={t.id}>{t.label}</Text>)}
    </RAStackProvider>
  );
}
```

> **Tip:** That is the entire loop. The same generated hooks work unchanged whether the engine runs in the browser, on S3, or on a remote server — see [Provider & Runtime Modes](https://reactapistack.com/docs/provider.md).

---

_Source: [https://reactapistack.com/docs/quickstart](https://reactapistack.com/docs/quickstart) · Full docs as one file: [llms-full.txt](https://reactapistack.com/llms-full.txt)_
