Zum Inhalt springen
Externa

Copy-paste-KI-Prompts

In Cursor, Claude oder ähnliche Assistenten einfügen. Jeder Prompt startet mit dem offiziellen Docs-llms.txt; keine erfundenen APIs.

Diese Prompts weisen Ihren Assistenten an, zuerst die offiziellen Docs zu lesen (llms.txt und Context7-IDs /qiick-io/externa-core und /llmstxt/externa_qiick_io_llms_txt). Generierten Code immer prüfen und niemals API-Keys, APP_KEY oder Webhook-Secrets in einen Chat einfügen.

Die Prompt-Bibliothek ist vorerst nur auf Englisch verfügbar.

Add Live Preview to a Next.js frontend

Implement the documented Live Preview contract (URL template tokens, signed token, GET /api/v1/preview) in a Next.js app.

You are helping me with Externa, an open-source headless CMS for Laravel (documented core version 1.2.2).

BEFORE WRITING ANY CODE OR ADVICE:
1. Read https://docs.qiick.io/externa/llms.txt first. It lists every docs page as Markdown.
2. Then read these pages (fetch the .md versions):
   - https://docs.qiick.io/externa/live-preview.md
   - https://docs.qiick.io/externa/content-versioning.md
   - https://docs.qiick.io/externa/headless-starter.md
   - https://docs.qiick.io/externa/public-cms-api.md
   - https://docs.qiick.io/externa/public-cms-api-types.md
   - https://docs.qiick.io/externa/ai-coding-tools.md
3. Optional: pull docs via Context7 MCP using library IDs /qiick-io/externa-core and/or /llmstxt/externa_qiick_io_llms_txt.
4. If you cannot fetch URLs, tell me and ask me to paste those pages. Do not guess.

RULES:
- Use ONLY endpoints, parameters, field types, permission names, env vars and UI paths that appear in those docs (or in the starter's code, if I paste it). If something is not documented, say "not documented — check the docs" instead of inventing it.
- Cite the docs page (URL) for each important step.
- Clearly separate Externa behavior from framework/host behavior (Next.js, Nuxt, Vercel, Docker, etc.).
- Never ask me to paste secrets (API keys ek_…, APP_KEY, webhook secrets) into this chat; use placeholders.
- Before finishing, list any assumptions you made and anything I should double-check against my installed version.

GOAL: Help me add Externa Live Preview to my Next.js App Router site (based on qiick-io/externa-next-starter).

STEPS TO HELP WITH:
1. Tell me how to enable content versioning on the collection, so drafts exist.
2. Propose a Live Preview URL template using only the documented tokens ({{id}}, {{collection}} / {{slug}} — both are the COLLECTION slug, {{locale}}, {{version}}, {{token}}) and tell me where to set it (collection drawer or Settings → Project default).
3. Implement a preview route that reads `token` from the query and calls GET {EXTERNA_API_URL}/api/v1/preview?token=… with no caching (reuse the starter's `externaFetch()`); render `data` with the same components as my production pages and show `meta.version` / `meta.expires_at` in a banner.
4. Handle the documented errors (422 missing token, 403 invalid/expired) with a friendly "click Live Preview again" message.
5. Account for the payload shape: a draft returns the raw `draft_data` bag (translatable fields as locale maps, files and relations as ids); a published preview is a flattened item without `include` expansion (files are ids too).
6. Explain draft vs published per the content-versioning docs, and confirm the Public CMS API keeps returning published values.
7. Never put API keys in preview URLs; if Allowed origins is set, send the API key as a server-side header. Mark preview pages noindex.

MY CONTEXT (fill in):
- Externa URL (local/staging): <e.g. http://externa-core.test>
- Frontend / stack: <e.g. Next.js 15 App Router on Vercel>
- What I already have: <paste relevant schema, files, or errors — no secrets>

Draft → review → publish workflow

Enable content versioning and editorial approvals: submit, in_review, approve/reject, then Publish.

You are helping me with Externa, an open-source headless CMS for Laravel (documented core version 1.2.2).

BEFORE WRITING ANY CODE OR ADVICE:
1. Read https://docs.qiick.io/externa/llms.txt first. It lists every docs page as Markdown.
2. Then read these pages (fetch the .md versions):
   - https://docs.qiick.io/externa/content-versioning.md
   - https://docs.qiick.io/externa/approvals.md
   - https://docs.qiick.io/externa/roles-and-permissions.md
   - https://docs.qiick.io/externa/ai-coding-tools.md
3. Optional: pull docs via Context7 MCP using library IDs /qiick-io/externa-core and/or /llmstxt/externa_qiick_io_llms_txt.
4. If you cannot fetch URLs, tell me and ask me to paste those pages. Do not guess.

RULES:
- Use ONLY states, UI labels, and permissions from those docs. Do not invent a multi-branch versions engine — Externa uses lean draft_data + publish.
- Cite the docs page (URL) for each important step.
- Never ask me to paste secrets into this chat.
- Before finishing, list assumptions and what I should verify on my collections.

GOAL: Help me set up a draft → review → publish editorial workflow on Externa collections.

STEPS TO HELP WITH:
1. On the collection edit drawer: turn on Versioning first, then Approvals required. Approvals without versioning are rejected.
2. Explain Draft vs Published workspaces: Draft edits `draft_data` only; Published is read-only while versioning is on. Publish (promote) copies draft_data into published values and clears the draft; Discard drops draft_data. Both need `can-edit-collections` (+ item write access).
3. Map the approval states exactly: draft → submit → in_review → approve → approved → Publish → published (approval resets). Reject (+ note) → rejected → edit/resubmit → in_review. Saving a draft while in_review/approved/rejected invalidates approval back to draft.
4. Permissions: `can-submit-collections` to submit; `can-approve-collections` to approve/reject (note required on reject); `can-edit-collections` to publish/discard/edit. Point reviewers at the In review filter on the items list.
5. Note scheduled publish also requires `approved` when approvals are on, and needs `collections:process-schedules` / a running scheduler.
6. Optional outbound webhook events: `item.submitted`, `item.approved`, `item.rejected` (plus `item.published` on promote). Remind me this is not a BPM / e-sign product.

MY CONTEXT (fill in):
- Externa URL (local/staging): <e.g. http://externa-core.test>
- Collections: <slugs that need review>
- Roles already created: <editor / reviewer / …>
- What I already have: <paste notes — no secrets>

Migrate from Directus into Externa

Import Directus items via profile=directus, with the first-locale-only translations caveat and dry-run upsert.

MigrationAI tools
You are helping me with Externa, an open-source headless CMS for Laravel (documented core version 1.2.2).

BEFORE WRITING ANY CODE OR ADVICE:
1. Read https://docs.qiick.io/externa/llms.txt first. It lists every docs page as Markdown.
2. Then read these pages (fetch the .md versions):
   - https://docs.qiick.io/externa/cms-import.md
   - https://docs.qiick.io/externa/ai-imports-and-sync.md
   - https://docs.qiick.io/externa/field-types.md
   - https://docs.qiick.io/externa/ai-coding-tools.md
3. Optional: pull docs via Context7 MCP using library IDs /qiick-io/externa-core and/or /llmstxt/externa_qiick_io_llms_txt.
4. If you cannot fetch URLs, tell me and ask me to paste those pages. Do not guess.

RULES:
- Use ONLY endpoints, parameters, field types, permission names, env vars and UI paths that appear in those docs. If something is not documented, say "not documented — check the docs" instead of inventing it.
- Cite the docs page (URL) for each important step.
- Never ask me to paste secrets into this chat; use placeholders.
- Before finishing, list assumptions and what I should verify on my installed version.

GOAL: Help me migrate content from Directus into Externa using ImportRemoteJson with profile=directus.

STEPS TO HELP WITH:
1. Confirm the path is CMS import connectors on top of AI remote JSON import (AI chat preset: "Import from Directus URL").
2. Tell me to allowlist the Directus host in `AI_REMOTE_IMPORT_HOSTS`.
3. Dry-run first: ImportRemoteJson with a Directus items URL (e.g. https://cms.example/items/pages), `profile=directus`, `dry_run=true`, `upsert_key=slug` (or another stable key), and `auth_bearer=…` when needed.
4. Explain what profile=directus does: drop Directus system fields (`user_created`, `date_*`, …) and promote first translation scalars (`title`, `body`, …) onto the row.
5. Emphasize the locale caveat: Directus `translations[]` → first locale scalars only; a full locale matrix is out of scope for v1. Advise modeling Externa translatable fields afterward if I need more locales (field-types docs).
6. After preview looks right, re-run with `dry_run=false`. Note ~200 async threshold / max 500 rows per call, media not auto-downloaded, relations as JSON strings unless reshaped upstream, one-way import only.

MY CONTEXT (fill in):
- Externa URL (local/staging): <e.g. http://externa-core.test>
- Directus items URL (no secrets): <e.g. https://cms.example/items/pages>
- Target collection: <existing slug or create new>
- What I already have: <paste schema/errors — no secrets>

Migrate WordPress posts into Externa

Import WordPress REST posts via ImportRemoteJson profile=wordpress, Application Passwords, dry-run, and upsert.

MigrationAI tools
You are helping me with Externa, an open-source headless CMS for Laravel (documented core version 1.2.2).

BEFORE WRITING ANY CODE OR ADVICE:
1. Read https://docs.qiick.io/externa/llms.txt first. It lists every docs page as Markdown.
2. Then read these pages (fetch the .md versions):
   - https://docs.qiick.io/externa/cms-import.md
   - https://docs.qiick.io/externa/ai-imports-and-sync.md
   - https://docs.qiick.io/externa/ai-configuration.md
   - https://docs.qiick.io/externa/ai-coding-tools.md
3. Optional: pull docs via Context7 MCP using library IDs /qiick-io/externa-core and/or /llmstxt/externa_qiick_io_llms_txt.
4. If you cannot fetch URLs, tell me and ask me to paste those pages. Do not guess.

RULES:
- Use ONLY endpoints, parameters, field types, permission names, env vars and UI paths that appear in those docs. If something is not documented, say "not documented — check the docs" instead of inventing it.
- Cite the docs page (URL) for each important step.
- Never ask me to paste secrets (API keys ek_…, APP_KEY, webhook secrets, Application Passwords) into this chat; use placeholders.
- Before finishing, list assumptions and what I should verify on my installed version.

GOAL: Help me migrate WordPress posts into Externa collections using the CMS import connectors (ImportRemoteJson with profile=wordpress).

STEPS TO HELP WITH:
1. Confirm the migration path is the existing AI remote JSON import — not a second sync engine — and that AI chat presets include "Import from WordPress REST".
2. Tell me to allowlist the WordPress host in `AI_REMOTE_IMPORT_HOSTS` before fetching.
3. Walk me through a dry-run first: ImportRemoteJson with url pointing at `/wp-json/wp/v2/posts` (or a custom post type route), `profile=wordpress`, `dry_run=true`, and a sensible `upsert_key` (e.g. slug). Explain that profile=wordpress unwraps `{ rendered: "…" }` envelopes on first-level keys (`title`, `content`, `excerpt`).
4. For Application Passwords: use `auth_header` as `Basic …` when Bearer is not used (docs also allow `auth_bearer`). Never ask me to paste the real password.
5. After I confirm the proposed fields / preview rows (zero writes), re-run with `dry_run=false`. Note row caps (~200 queue threshold, max 500 per call) and that large payloads queue via ImportCollectionJob.
6. Call out documented v1 gaps: featured images / file UUIDs are not auto-downloaded into Externa File rows; relations stay JSON strings unless reshaped upstream; import is one-way (no write-back).

MY CONTEXT (fill in):
- Externa URL (local/staging): <e.g. http://externa-core.test>
- WordPress REST URL (no secrets): <e.g. https://blog.example.com/wp-json/wp/v2/posts>
- Target collection: <existing slug or create new>
- What I already have: <paste schema/errors — no secrets>

Model collections with Cursor or Claude

Design collections and fields using Context7 IDs, llms.txt, collection packs, field packs, and field conditions.

CollectionsAI tools
You are helping me with Externa, an open-source headless CMS for Laravel (documented core version 1.2.2).

BEFORE WRITING ANY CODE OR ADVICE:
1. Read https://docs.qiick.io/externa/llms.txt first. It lists every docs page as Markdown.
2. Then read these pages (fetch the .md versions):
   - https://docs.qiick.io/externa/ai-coding-tools.md
   - https://docs.qiick.io/externa/collections.md
   - https://docs.qiick.io/externa/field-types.md
   - https://docs.qiick.io/externa/field-conditions.md
   - https://docs.qiick.io/externa/extending.md
3. Prefer Context7 when available:
   - /qiick-io/externa-core — package source / admin internals
   - /llmstxt/externa_qiick_io_llms_txt — published docs from llms.txt
4. If you cannot fetch URLs, tell me and ask me to paste those pages. Do not guess.

RULES:
- Use ONLY field types, pack names, UI labels, and settings keys that appear in the docs. Never invent FieldTypeEnum values or pack slugs.
- Cite the docs page (URL) for each important step.
- Never ask me to paste secrets into this chat.
- Before finishing, list assumptions and what I should verify in the admin UI.

GOAL: Help me model Externa collections (and fields) for my content with Cursor/Claude, starting from packs when they fit.

STEPS TO HELP WITH:
1. Ask what content I need (blog, pages, products, custom). Prefer official collection packs when they match: `seo`, `categories`, `pages`, `articles`, `products` (Collections → Create from pack…). Missing dependencies are auto-created; existing slugs are reused.
2. For SEO on Articles/Pages/Products, prefer the SEO collection pack + M2O relation — not `seo_inline` unless I need denormalized `seo_*` fields on an existing collection. Field packs apply via Fields → Add field pack… (existing names skipped).
3. When packs are not enough, design fields using only documented FieldTypeEnum values and settings from field-types. Call out that `is_singleton` cannot be changed after create.
4. Add field conditions only with the documented shape (`logic` and/or `or`, `rules` with operators like equals / not_equals / contains / empty / not_empty / gt / gte / lt / lte / in / not_in, plus `hidden` / `readonly` / `required`).
5. If I need a custom field type or permission later, point me at Extending Externa (enum + sync + tests) — do not invent a half-implemented type.
6. Give me a concise schema checklist I can click through in the admin, with docs citations.

MY CONTEXT (fill in):
- Externa URL (local/staging): <e.g. http://externa-core.test>
- Content I need: <e.g. docs site with guides + authors>
- What I already have: <paste existing collection JSON or screenshots — no secrets>

Multilingual landing with the Nuxt starter

Locale-aware landing page (en/it) with qiick-io/externa-nuxt-starter, translatable fields, and the Translation workspace.

You are helping me with Externa, an open-source headless CMS for Laravel (documented core version 1.2.2).

BEFORE WRITING ANY CODE OR ADVICE:
1. Read https://docs.qiick.io/externa/llms.txt first. It lists every docs page as Markdown.
2. Then read these pages (fetch the .md versions):
   - https://docs.qiick.io/externa/headless-starter.md
   - https://docs.qiick.io/externa/translation-workspace.md
   - https://docs.qiick.io/externa/collections-data-model.md
   - https://docs.qiick.io/externa/project-settings.md
   - https://docs.qiick.io/externa/collections.md
   - https://docs.qiick.io/externa/field-types.md
   - https://docs.qiick.io/externa/public-cms-api.md
   - https://docs.qiick.io/externa/ai-coding-tools.md
3. Optional: pull docs via Context7 MCP using library IDs /qiick-io/externa-core and/or /llmstxt/externa_qiick_io_llms_txt.
4. If you cannot fetch URLs, tell me and ask me to paste those pages. Do not guess.

RULES:
- Use ONLY endpoints, parameters, field types, permission names, env vars and UI paths that appear in those docs (or in the starter's code, if I paste it). If something is not documented, say "not documented — check the docs" instead of inventing it.
- Cite the docs page (URL) for each important step.
- Clearly separate Externa behavior from framework/host behavior (Next.js, Nuxt, Vercel, Docker, etc.).
- Never ask me to paste secrets (API keys ek_…, APP_KEY, webhook secrets) into this chat; use placeholders.
- Before finishing, list any assumptions you made and anything I should double-check against my installed version.

GOAL: Help me build a multilingual landing page (e.g. en + it) with the official Nuxt starter (qiick-io/externa-nuxt-starter, Nuxt 3) on top of Externa.

STEPS TO HELP WITH:
1. From the docs, explain how to enable content languages in Settings → Project → Content languages and how translatable fields are stored (one value row per locale).
2. Help me model a singleton `landing` collection (is_singleton cannot be changed after create) and choose which fields are translatable according to the field-types docs.
3. Explain how editors use the Translation workspace on the item form (locale dropdown with filled/total completeness; **Apply to all locales** / **Apply to empty locales**; per-field **Copy from {{locale}}** and optional **Translate with AI from {{locale}}** when the user has `can-use-ai` and local AI is configured).
4. Write a Nitro server route that reuses the starter's `externaFetch(event, path)` from server/utils/externa/client.ts (private runtimeConfig, never runtimeConfig.public / NUXT_PUBLIC_) and calls /api/v1 with the documented `locale` param (enabled locales only, else 422). Read the locale from a route param with getRouterParam, like the starter's server/api/items/[id].get.ts.
5. Explain what the API returns for a missing translation: with `locale`, Externa falls back along the project's fallback chain (default locale first, then the other enabled locales); with `include_all_translations=true` a missing locale is simply absent. The starter adds no fallback logic of its own.
6. Write a pages/[locale] page with a language switcher and absolute hreflang links.

MY CONTEXT (fill in):
- Externa URL (local/staging): <e.g. http://externa-core.test>
- Frontend / stack: <e.g. Nuxt 3 on Netlify>
- What I already have: <paste relevant schema, files, or errors — no secrets>

Rebuild Vercel on Externa content change

Wire outbound HMAC webhooks to a thin receiver that triggers a Vercel Deploy Hook on item.published.

Webhooks
You are helping me with Externa, an open-source headless CMS for Laravel (documented core version 1.2.2).

BEFORE WRITING ANY CODE OR ADVICE:
1. Read https://docs.qiick.io/externa/llms.txt first. It lists every docs page as Markdown.
2. Then read these pages (fetch the .md versions):
   - https://docs.qiick.io/externa/webhooks.md
   - https://docs.qiick.io/externa/webhook-rebuild-purge.md
   - https://docs.qiick.io/externa/automation-without-flows.md
   - https://docs.qiick.io/externa/ai-coding-tools.md
3. Optional: pull docs via Context7 MCP using library IDs /qiick-io/externa-core and/or /llmstxt/externa_qiick_io_llms_txt.
4. If you cannot fetch URLs, tell me and ask me to paste those pages. Do not guess.

RULES:
- Use ONLY documented event types, headers, and Project settings fields. Externa has no Flows canvas — prefer outbound webhooks + a thin receiver.
- Cite the docs page (URL) for each important step.
- Never ask me to paste webhook secrets or Deploy Hook URLs with secrets into this chat; use placeholders.
- Before finishing, list assumptions and a verification plan (Send test event / ping).

GOAL: When editors publish content in Externa, rebuild my Vercel frontend safely.

STEPS TO HELP WITH:
1. Configure Admin → Settings → Project: Webhook URL + signing secret (both required). Delivery is queued (`DeliverOutboundWebhookJob`) — a queue worker must run. Optional Send test event (`type: ping`).
2. Prefer Pattern A from webhook-rebuild-purge: Externa → my HTTPS receiver → verify `X-Externa-Signature` (HMAC-SHA256 over raw body, `sha256=` prefix) → on matching `type`, POST the Vercel Deploy Hook. Do NOT expose an unsigned Deploy Hook as the public Externa webhook URL in production (hooks ignore HMAC; anyone with the URL can rebuild).
3. Event picks: listen for `item.published` when only live content should rebuild; use `item.created` / `item.updated` only if draft saves should rebuild too. Filter on JSON `type`.
4. Show a minimal Node receiver sketch matching the docs (timing-safe compare, then `fetch(deployHook, { method: 'POST' })`). Create the Deploy Hook in Vercel → Project → Settings → Git → Deploy Hooks.
5. Remind me: outbound webhooks are Externa → my URL (not an inbound Externa route). Do not confuse with `POST /ai/webhooks/collection-import`. Bodies are minimal (ids/slug). Retries: 3 tries with backoff.
6. Optional: Cloudflare purge after publish is a separate Pattern B — only if I ask.

MY CONTEXT (fill in):
- Externa URL (local/staging): <e.g. http://externa-core.test>
- Frontend host: <Vercel project name>
- Receiver host: <e.g. small Node/Edge function URL>
- What I already have: <paste envelope samples/errors — no secrets>

Roles and permissions for an editorial team

Set up Spatie roles, groups, Collection access, and approval permissions for editors and reviewers.

PermissionsApprovals
You are helping me with Externa, an open-source headless CMS for Laravel (documented core version 1.2.2).

BEFORE WRITING ANY CODE OR ADVICE:
1. Read https://docs.qiick.io/externa/llms.txt first. It lists every docs page as Markdown.
2. Then read these pages (fetch the .md versions):
   - https://docs.qiick.io/externa/roles-and-permissions.md
   - https://docs.qiick.io/externa/permissions.md
   - https://docs.qiick.io/externa/users-and-groups.md
   - https://docs.qiick.io/externa/approvals.md
   - https://docs.qiick.io/externa/ai-coding-tools.md
3. Optional: pull docs via Context7 MCP using library IDs /qiick-io/externa-core and/or /llmstxt/externa_qiick_io_llms_txt.
4. If you cannot fetch URLs, tell me and ask me to paste those pages. Do not guess.

RULES:
- Use ONLY permission names from PermissionEnum / the roles-and-permissions catalog. Never invent ad-hoc permission strings.
- Cite the docs page (URL) for each important step.
- Never ask me to paste secrets into this chat.
- Before finishing, list assumptions and what I should verify after permissions:sync.

GOAL: Help me design roles and permissions for an editorial team (editors, reviewers, maybe readers) in Externa admin.

STEPS TO HELP WITH:
1. Explain seeded roles: `super-admin`, `admin`, `reader`, and system role `public` (anonymous Public CMS API). Note that `public` is not assignable to users — only Collection access + Files access are editable on it.
2. Clarify the two layers: Spatie / PermissionEnum gates the admin UI; Collection access / Files access matrices gate the Public CMS API independently.
3. Propose custom roles (e.g. editor, reviewer) using only documented permissions. For approvals workflow, include `can-submit-collections` (submit draft for review) and `can-approve-collections` (approve/reject). Editors who publish need `can-edit-collections`. Sync with `php artisan permissions:sync` (and UI Sync from enum) — do not invent names outside the enum.
4. For large teams: attach roles to a group so members inherit Spatie permissions and the role’s collection/file matrices (no separate group→collection ACL).
5. Remind me `super-admin` cannot be deleted/renamed/duplicated; `public` cannot be renamed/deleted/duplicated; Prefer groups over per-user role spam.
6. Optional: sketch Collection access for the `public` role (Read only on public collections; Files Read without Read private) vs an API-key role for backends.

MY CONTEXT (fill in):
- Externa URL (local/staging): <e.g. http://externa-core.test>
- Team shape: <e.g. 3 editors, 2 reviewers, public website>
- Collections involved: <slugs>
- What I already have: <paste role screenshots/notes — no secrets>

Self-host Externa with Docker in production

Deploy via GHCR Compose quick/prod path, PHP 8.4.27 / 8.5.12 minimum, healthchecks, and reverse proxy TLS.

Docker
You are helping me with Externa, an open-source headless CMS for Laravel (documented core version 1.2.2).

BEFORE WRITING ANY CODE OR ADVICE:
1. Read https://docs.qiick.io/externa/llms.txt first. It lists every docs page as Markdown.
2. Then read these pages (fetch the .md versions):
   - https://docs.qiick.io/externa/deploy-with-docker.md
   - https://docs.qiick.io/externa/deployment.md
   - https://docs.qiick.io/externa/reverse-proxy.md
   - https://docs.qiick.io/externa/ai-coding-tools.md
3. Optional: pull docs via Context7 MCP using library IDs /qiick-io/externa-core and/or /llmstxt/externa_qiick_io_llms_txt.
4. If you cannot fetch URLs, tell me and ask me to paste those pages. Do not guess.

RULES:
- Use ONLY Compose files, env vars, health endpoints, and proxy settings from those docs. Never invent image tags or entrypoint flags.
- Cite the docs page (URL) for each important step.
- Never ask me to paste APP_KEY, DB_PASSWORD, or other secrets into this chat; use placeholders.
- Before finishing, list assumptions and a post-deploy smoke checklist.

GOAL: Help me self-host Externa in production with Docker (official GHCR image) behind TLS.

STEPS TO HELP WITH:
1. PHP runtime floor: composer declares `^8.4.27` (**PHP 8.4.27+ or 8.5.12+**). Official `ghcr.io/qiick-io/externa-core:1.2.2` / `latest` is built on `php:8.4.27-fpm-bookworm` with a hardened `php.ini` (`session.upload_progress.enabled=0`, `session.use_strict_mode=1`, body/multipart limits matching nginx 100M). Pull and recreate (`docker compose pull && docker compose up -d`), then `docker compose exec <php-service> php -v`. Source builds: rebuild with `--pull --no-cache`.
2. Quick deploy path from an externa-core checkout: copy `.env.docker.quick.example` → `.env`, set APP_KEY / strong DB_PASSWORD / APP_URL, then `docker compose -f compose.quick.yaml up -d`. Pin with `EXTERNA_IMAGE=ghcr.io/qiick-io/externa-core:1.2.2` when needed.
3. Explain gated first boot: `RUN_MIGRATIONS` / `RUN_SEED` (samples enable migrate; seed is opt-in with INITIAL_SUPER_ADMIN_*). After login works, set `RUN_SEED=false`.
4. Health: `GET /health/ready` (Compose app probe), also `/health/live` and Laravel `/up`.
5. For public HTTPS + Reverb: follow reverse-proxy cookbook (Caddy / Traefik / nginx). Set `APP_URL` to the browser HTTPS URL, `TRUSTED_PROXIES`, and browser-facing `REVERB_*` / `VITE_REVERB_*` (rebuild image after Vite Reverb public URL changes).
6. Build-from-source prod alternative: `.env.docker.prod.example` + `compose.prod.yaml` (+ managed overlay when DB/Redis are external). Do not invent Sail as the production path.

MY CONTEXT (fill in):
- Host / cloud: <e.g. Hetzner VPS>
- Domain: <e.g. https://cms.example.com>
- Prefer quick GHCR vs build-from-source: <choose>
- What I already have: <paste compose/.env keys only (names) — no secret values>

Wire the Next.js starter into a blog

Turn qiick-io/externa-next-starter into a blog (list + slug pages) on the Articles collection pack, using the Public CMS API.

You are helping me with Externa, an open-source headless CMS for Laravel (documented core version 1.2.2).

BEFORE WRITING ANY CODE OR ADVICE:
1. Read https://docs.qiick.io/externa/llms.txt first. It lists every docs page as Markdown.
2. Then read these pages (fetch the .md versions):
   - https://docs.qiick.io/externa/headless-starter.md
   - https://docs.qiick.io/externa/public-cms-api.md
   - https://docs.qiick.io/externa/public-cms-api-types.md
   - https://docs.qiick.io/externa/field-types.md
   - https://docs.qiick.io/externa/roles-and-permissions.md
   - https://docs.qiick.io/externa/quick-start.md
   - https://docs.qiick.io/externa/ai-coding-tools.md
3. Optional: pull docs via Context7 MCP using library IDs /qiick-io/externa-core and/or /llmstxt/externa_qiick_io_llms_txt.
4. If you cannot fetch URLs, tell me and ask me to paste those pages. Do not guess.

RULES:
- Use ONLY endpoints, parameters, field types, permission names, env vars and UI paths that appear in those docs (or in the starter's code, if I paste it). If something is not documented, say "not documented — check the docs" instead of inventing it.
- Cite the docs page (URL) for each important step.
- Clearly separate Externa behavior from framework/host behavior (Next.js, Nuxt, Vercel, Docker, etc.).
- Never ask me to paste secrets (API keys ek_…, APP_KEY, webhook secrets) into this chat; use placeholders.
- Before finishing, list any assumptions you made and anything I should double-check against my installed version.

GOAL: Help me turn the official Next.js starter (qiick-io/externa-next-starter, Next.js 15 App Router) into a blog with a /blog index and /blog/[slug] pages, reading an `articles` collection from Externa's Public CMS API (/api/v1).

STEPS TO HELP WITH:
1. Confirm from the docs how to create the `articles` collection with the Articles collection pack (Collections → Create from pack…) and which fields and relations it creates. Note that `body` is a `blocks` field (block types `section` and `rich_text`), so its value is an array of { id, type, data } and nested translatable fields keep their locale map.
2. Tell me exactly which grants the `public` role (or an API-key role) needs: Collection access → Read on `articles` and `categories`, Files access → Read for covers.
3. Write a server-only blog helper that reuses the starter's `externaFetch()` from lib/externa/client.ts and ONLY documented query params (page, per_page, filter[field][_eq], include, locale, include_all_translations). Use `include=files,category` to expand the cover and category.
4. The items endpoint has no sort parameter (items come back newest-first by id), so sort by `published_at` in my code and explain the per-page limitation.
5. Generate the index and slug pages plus a renderer for the blocks body. Keep EXTERNA_API_KEY server-side (never NEXT_PUBLIC_).
6. Remind me that, once Allowed origins is set, server-side requests need an API key, and that browser image requests to /api/v1/files are behind the same origin gate.

MY CONTEXT (fill in):
- Externa URL (local/staging): <e.g. http://externa-core.test>
- Frontend / stack: <e.g. Next.js 15 App Router on Vercel>
- What I already have: <paste relevant schema, files, or errors — no secrets>