> ## Documentation Index
> Fetch the complete documentation index at: https://kweri.uchenna.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# Quickstart

> Get typed data fetching running in under five minutes.

Kweri supports two usage patterns. Choose the one that fits your project:

|           | Path A — With an OpenAPI spec                          | Path B — Without an OpenAPI spec       |
| --------- | ------------------------------------------------------ | -------------------------------------- |
| Endpoints | Generated by `kweri-gen`                               | Defined manually with `defineEndpoint` |
| Hooks     | `useGet`, `usePost`, `usePut`, `usePatch`, `useDelete` | `useQuery`, `useMutation`              |
| Best for  | Teams with a Swagger / OpenAPI spec                    | Teams hand-crafting their API layer    |

***

## Path A — With an OpenAPI spec (recommended)

### 1. Install

```bash theme={null}
npm install kweri
# or
bun add kweri
```

### 2. Create a Kweri instance

```ts theme={null}
// src/lib/kweri.ts
import { Kweri } from 'kweri'

export const kweri = new Kweri({
  baseURL: 'https://api.example.com',
  staleTime: 30_000,
  cacheTime: 300_000,
  enableDevTools: true
})
```

### 3. Generate from your spec

```bash theme={null}
npx kweri-gen https://api.example.com/openapi.json --out src/api/kweri
```

This writes `src/api/kweri/client.ts` with TypeBox schemas, an `EndpointByMethod` map for every route in your spec, and a `createClient` that routes through kweri. Commit it and re-run whenever your API changes.

### 4. Set up path hooks

<Tabs>
  <Tab title="React">
    ```ts theme={null}
    // src/hooks/useKweri.ts
    import { useSyncExternalStore } from 'react'
    import { createReactPathHooks } from 'kweri'
    import { EndpointByMethod } from '@/api/kweri/client'
    import { kweri } from '@/lib/kweri'

    export const { useGet, usePost, usePut, usePatch, useDelete } =
      createReactPathHooks(useSyncExternalStore, kweri, EndpointByMethod)

    export { kweri }
    ```
  </Tab>

  <Tab title="Vue">
    ```ts theme={null}
    // src/composables/useKweri.ts
    import { ref, watch, onUnmounted } from 'vue'
    import { createVuePathHooks } from 'kweri'
    import { EndpointByMethod } from '@/api/kweri/client'
    import { kweri } from '@/lib/kweri'

    export const { useGet, usePost, usePut, usePatch, useDelete } =
      createVuePathHooks({ ref, watch, onUnmounted }, kweri, EndpointByMethod)

    export { kweri }
    ```
  </Tab>
</Tabs>

<Note>
  Create the hook factory once and export it. Don't call `createReactPathHooks` or `createVuePathHooks` inside a component.
</Note>

### 5. Fetch data in your components

<Tabs>
  <Tab title="React">
    ```tsx theme={null}
    // src/components/UserList.tsx
    import { useGet, usePost, kweri } from '@/hooks/useKweri'

    export function UserList() {
      const { data, isLoading, isError, error } = useGet('/users', {})

      if (isLoading) return <p>Loading...</p>
      if (isError)   return <p>Error: {error?.message}</p>

      return (
        <ul>
          {data?.map(user => <li key={user.id}>{user.name}</li>)}
        </ul>
      )
    }

    export function CreateUserButton() {
      const { mutateAsync, isLoading } = usePost('/users')

      async function handleClick() {
        await mutateAsync({ body: { name: 'Alice' } })
        kweri.invalidateByPath('/users')
      }

      return (
        <button onClick={handleClick} disabled={isLoading}>
          {isLoading ? 'Creating...' : 'Create user'}
        </button>
      )
    }
    ```
  </Tab>

  <Tab title="Vue">
    ```vue theme={null}
    <!-- src/components/UserList.vue -->
    <script setup lang="ts">
    import { useGet, usePost, kweri } from '@/composables/useKweri'

    const { data, isLoading, isError, error } = useGet('/users')

    const createMutation = usePost('/users')

    async function handleCreate() {
      await createMutation.mutateAsync({ body: { name: 'Alice' } })
      kweri.invalidateByPath('/users')
    }
    </script>

    <template>
      <p v-if="isLoading.value">Loading...</p>
      <p v-else-if="isError.value">Error: {{ error.value?.message }}</p>
      <ul v-else>
        <li v-for="user in data.value" :key="user.id">{{ user.name }}</li>
      </ul>
      <button @click="handleCreate" :disabled="createMutation.isLoading.value">
        Create user
      </button>
    </template>
    ```
  </Tab>
</Tabs>

***

## Path B — Without an OpenAPI spec

Use this path when you don't have a spec and want to define endpoints by hand.

### 1. Install

```bash theme={null}
npm install kweri
# or
bun add kweri
```

### 2. Create a Kweri instance

```ts theme={null}
// src/lib/kweri.ts
import { Kweri } from 'kweri'

export const kweri = new Kweri({
  baseURL: 'https://api.example.com',
  staleTime: 30_000,
  cacheTime: 300_000,
})
```

### 3. Define your endpoints

```ts theme={null}
// src/api/users.ts
import { Type, defineEndpoint } from 'kweri'

export const getUsers = defineEndpoint({
  method: 'GET',
  path: '/users',
  params: Type.Object({}),
  response: Type.Array(
    Type.Object({
      id:    Type.Number(),
      name:  Type.String(),
      email: Type.String()
    })
  )
})

export const createUser = defineEndpoint({
  method: 'POST',
  path: '/users',
  params: Type.Object({
    body: Type.Object({ name: Type.String(), email: Type.String() })
  }),
  response: Type.Object({ id: Type.Number(), name: Type.String(), email: Type.String() })
})
```

### 4. Set up hooks

<Tabs>
  <Tab title="React">
    ```ts theme={null}
    // src/hooks/useKweri.ts
    import { useSyncExternalStore } from 'react'
    import { createReactQueryHooks } from 'kweri'
    import { kweri } from '@/lib/kweri'

    export const { useQuery, useMutation } =
      createReactQueryHooks(useSyncExternalStore, kweri)
    ```
  </Tab>

  <Tab title="Vue">
    ```ts theme={null}
    // src/composables/useKweri.ts
    import { ref, watch, onUnmounted } from 'vue'
    import { createVueQueryHooks } from 'kweri'
    import { kweri } from '@/lib/kweri'

    export const { useQuery, useMutation } =
      createVueQueryHooks({ ref, watch, onUnmounted }, kweri)

    export { kweri }
    ```
  </Tab>
</Tabs>

### 5. Fetch data in your components

<Tabs>
  <Tab title="React">
    ```tsx theme={null}
    // src/components/UserList.tsx
    import { useQuery, useMutation, kweri } from '@/hooks/useKweri'
    import { getUsers, createUser } from '@/api/users'

    export function UserList() {
      const { data, isLoading, isError, error } = useQuery(getUsers, {})

      if (isLoading) return <p>Loading...</p>
      if (isError)   return <p>Error: {error?.message}</p>

      return (
        <ul>
          {data?.map(user => <li key={user.id}>{user.name}</li>)}
        </ul>
      )
    }

    export function CreateUserButton() {
      const { mutateAsync, isLoading } = useMutation(createUser)

      async function handleClick() {
        await mutateAsync({ body: { name: 'Alice', email: 'alice@example.com' } })
        kweri.invalidateByPath('/users')
      }

      return (
        <button onClick={handleClick} disabled={isLoading}>
          {isLoading ? 'Creating...' : 'Create user'}
        </button>
      )
    }
    ```
  </Tab>

  <Tab title="Vue">
    ```vue theme={null}
    <!-- src/components/UserList.vue -->
    <script setup lang="ts">
    import { useQuery, useMutation, kweri } from '@/composables/useKweri'
    import { getUsers, createUser } from '@/api/users'

    const { data, isLoading, isError, error } = useQuery(getUsers, {})
    const createMutation = useMutation(createUser)

    async function handleCreate() {
      await createMutation.mutateAsync({ body: { name: 'Alice', email: 'alice@example.com' } })
      kweri.invalidateByPath('/users')
    }
    </script>

    <template>
      <p v-if="isLoading.value">Loading...</p>
      <p v-else-if="isError.value">Error: {{ error.value?.message }}</p>
      <ul v-else>
        <li v-for="user in data.value" :key="user.id">{{ user.name }}</li>
      </ul>
      <button @click="handleCreate" :disabled="createMutation.isLoading.value">
        Create user
      </button>
    </template>
    ```
  </Tab>

  <Tab title="Vanilla JS">
    ```ts theme={null}
    import { kweri } from './lib/kweri'
    import { getUsers } from './api/users'

    const unsubscribe = kweri.subscribe(getUsers, {}, (entry) => {
      console.log('Cache updated:', entry.data)
    })

    await kweri.query(getUsers, {})

    unsubscribe()
    ```
  </Tab>
</Tabs>
