# Headless starter

Source: https://docs.qiick.io/externa/headless-starter

Official **Next.js App Router** and **Nuxt 3** starters that read collection items from Externa’s headless `/api/v1` API. List + detail pages, env-based config, server-side fetches only.

> **Related**
> [Public CMS API](https://docs.qiick.io/externa/public-cms-api) · [Public CMS API types](https://docs.qiick.io/externa/public-cms-api-types) · [GraphQL](https://docs.qiick.io/externa/graphql) · [Quick Start](https://docs.qiick.io/externa/quick-start) · [Installation](https://docs.qiick.io/externa/installation) · Conventions: [core `docs/starters.md`](https://github.com/qiick-io/externa-core/blob/develop/docs/starters.md) · Marketing: [externa.qiick.io](https://externa.qiick.io/en)

## Repos

| Framework           | Repo                                                                              |
| ------------------- | --------------------------------------------------------------------------------- |
| Next.js (reference) | [qiick-io/externa-next-starter](https://github.com/qiick-io/externa-next-starter) |
| Nuxt                | [qiick-io/externa-nuxt-starter](https://github.com/qiick-io/externa-nuxt-starter) |

Shared bar (TypeScript, env vars, CI, Dependabot): core [#156](https://github.com/qiick-io/externa-core/issues/156) / [`docs/starters.md`](https://github.com/qiick-io/externa-core/blob/develop/docs/starters.md).

## What you get

| Piece          | Notes                                                                                      |
| -------------- | ------------------------------------------------------------------------------------------ |
| `/`            | Lists items for one collection slug                                                        |
| `/items/[id]`  | Shows field values for one item                                                            |
| Typed helpers  | `lib/externa/*` (Next) / `server/utils/externa/*` (Nuxt) — fetch client, OpenAPI probe     |
| `.env.example` | `EXTERNA_API_URL`, `EXTERNA_API_KEY`, `EXTERNA_COLLECTION` (optional; auto-picks if empty) |

**Not included:** marketing theme, Kitchen Sink seed, OpenAPI codegen client (see [Public CMS API types](https://docs.qiick.io/externa/public-cms-api-types) and core [#25](https://github.com/qiick-io/externa-core/issues/25)).

## 1. Run Externa

Follow [Quick Start](https://docs.qiick.io/externa/quick-start) or [Installation](https://docs.qiick.io/externa/installation) until the admin is up (e.g. `http://externa-core.test`).

Create a collection (slug `posts` is a common default) and at least one item.

Grant **Read** on that collection for the `public` role (or create an API key whose role has Read) — [Public CMS API quick start](https://docs.qiick.io/externa/public-cms-api#quick-start-typical-website-read).

## 2a. Next.js starter

```bash
git clone https://github.com/qiick-io/externa-next-starter.git
cd externa-next-starter
cp .env.example .env.local
```

Edit `.env.local`:

```env
EXTERNA_API_URL=http://externa-core.test
# optional — omit to use the public role
EXTERNA_API_KEY=
EXTERNA_COLLECTION=posts
```

```bash
npm install
npm run dev
```

Open `http://localhost:3002`.

> `EXTERNA_API_KEY` is read only in Server Components / server `fetch`. Do not prefix it with `NEXT_PUBLIC_`.

## 2b. Nuxt starter

```bash
git clone https://github.com/qiick-io/externa-nuxt-starter.git
cd externa-nuxt-starter
cp .env.example .env
```

Same env vars as Next. Fetches run in Nitro `/api/*` handlers with private `runtimeConfig` — never put the key under `runtimeConfig.public` or a `NUXT_PUBLIC_` prefix.

```bash
npm install
npm run dev
```

Open `http://localhost:3003`.

## 3. Verify the API without a frontend

```bash
curl -sS 'http://externa-core.test/api/v1/collections/posts/items?page=1&per_page=5' \
  -H 'Accept: application/json'
# optional: -H "Authorization: Bearer ek_YOUR_SECRET"
```

Ready-made requests: [externa-bruno](https://github.com/qiick-io/externa-bruno).

## GraphQL

Both starters use REST. The same Collection access rules apply at `/api/graphql` — [GraphQL](https://docs.qiick.io/externa/graphql).

## Rebuild when content changes

Point Externa [outbound webhooks](https://docs.qiick.io/externa/webhooks) at your host’s deploy hook (or a Make/n8n scenario) so publishes trigger a rebuild.

## Optional: full-text search

For on-site search beyond API `filter[...]`, enable Externa’s [Meilisearch sync](https://docs.qiick.io/externa/meilisearch) and query the index from a **server** route with a search-only key (filter by `collection_slug`).
