Garchi CMS
LumenHarbor Digital Solutions Limited v4.0.0
Publisher description
From the marketplace listing
Garchi CMS is a headless SaaS CMS used to manage content across platforms such as websites and apps. With this app, you could connect to Garchi CMS using the MCP server and manage your platform's content levaraging the power of Chat GPT. Example prompts - Create a blog article on best principles of Gen AI using Garchi CMS - Create a landing page using the provided brief in Garchi CMS.
Language: English · Automatically detected from descriptions.
Files & skills
File archives
Skill instructions
garchi-build-site10.6 KB
--- name: garchi-build-site description: Plan and wire up a website or application that uses Garchi CMS as its content backend — deciding between an official Garchi starter kit and integrating into an existing project, connecting the Garchi MCP server, mapping the space's pages/sections/templates/data items to components, and verifying content stays editable in the CMS. Use when the user says things like "build me a site with Garchi", "use Garchi as the CMS for this project", "connect this project to my Garchi space", or "start a project with the official Garchi starter kit". Routes rendering work to garchi-render-content and CMS write operations to garchi-manage-content. --- # Garchi CMS: build or connect a project Garchi CMS is a hosted headless CMS. Content lives in Garchi; the application renders it. The point of a correct integration is that business content can change in Garchi afterwards **without another code change**. This skill orchestrates. It decides the shape of the work and hands off: | Work | Go to | | --- | --- | | Writing fetch/render code, section renderers, components | `garchi-render-content` | | Creating or editing content in the CMS (pages, sections, items, assets) | `garchi-manage-content` | | Choosing/bootstrapping an official starter kit | [starter-kits.md](./references/starter-kits.md) | ## When Garchi is the right home for something Garchi holds **structured content and lightweight configuration that fits its existing content model** — pages built from section templates and props, and data items with categories and metadata. It is not the application's database. **A good fit.** Information that should stay editable after deployment, may be changed by a person or by an agent, and should not need a code change and a redeploy every time it changes. Where it maps onto the content model, that includes: - website and landing-page content - pricing and plan presentation - FAQs - navigation - onboarding copy and steps - product or catalogue content, and similar collection-style records - reusable marketing or UI copy - prompts or agent instructions the user is meant to be able to edit - lightweight application configuration that fits sections and props, or data items and metadata These are the cases that benefit from what Garchi already provides: agents write drafts and the user publishes, changes are attributable, the dashboard keeps restore points the user can roll back to, templates give the content a structure the frontend can rely on, and the same content is reachable over REST, the SDKs and MCP. **Not a fit.** Operational and transactional state stays in the application's own database and infrastructure: - authentication, sessions and user accounts - credentials, API keys and secrets - payments and financial transactions - high-frequency or machine-written operational data - queues, jobs, logs, telemetry and analytics events - complex relational state, and records that need transactional guarantees The useful question is "who edits this, and does it need to change without a deploy?" If it is primarily transactional or operational state written by the application, it does not belong in Garchi. ## Workflow Work through these in order. Skip a step only when it is already satisfied, and say so rather than silently skipping. ### 1. Understand what is being built Establish: the kind of site/app, which pages or content types it needs, and whether content will be authored by a human in the Garchi dashboard, by the agent over MCP, or both. Ask only what you cannot infer from the repo. ### 2. Inspect the project Look before choosing an approach: - Is there an existing project in the working directory at all? - Framework and version (`package.json`, `composer.json`, `nuxt.config.*`, `next.config.*`, `artisan`). - Does it already depend on `@garchicms/garchi-node-sdk` or `garchicms/garchi-sdk-php`? Are `GARCHI_*` variables already set? - Is there an existing CMS or content layer being replaced? - Is structured content hardcoded in source — pricing or plan arrays, FAQ lists, navigation structures, homepage or onboarding copy, reusable marketing strings — that would reasonably need to change after deployment? Note the candidates and put them to the user before creating or migrating anything. Use judgement: a constant that only ever changes alongside a code change is not a candidate, and transactional or backend state never is. ### 3. Decide: starter kit or integrate - **Empty directory / new project** in Next, Nuxt or Laravel → propose the official starter kit. See [starter-kits.md](./references/starter-kits.md). Those three are the only kits; do not scaffold any other name the CLI offers. - **Existing project of any maturity** → integrate the SDK/API into it. Do not replace a working application with a starter kit, and do not copy starter-kit files over existing conventions. Read the starter kit as a *reference* if useful. - **Any other stack** (Django, Rails, Astro, React Native, mobile) → integrate via the REST API from the server side. Say which branch you took and why before you start writing files. ### 4. Check the Garchi MCP connection The plugin ships the hosted server as `garchi` (`https://garchi.co.uk/mcp-oauth`, OAuth). Confirm the tools are actually available before planning content work — try `list-space-tool`. - Tools available → you can inspect and author content directly. - Not available → the user must authorize the `garchi` MCP server in their agent (see the repository README for per-client steps). Do not attempt to work around this with an API key you invent, and do not ask the user to paste a token into a file. Continue with the code-only parts of the work and tell the user what is blocked. ### 5. Inspect the space With MCP available: 1. `get-garchi-cms-guide` → the current content model and field rules, straight from the server. Free, read-only, no arguments. 2. `list-space-tool` → pick the target space, note its `space_uid`. The result also carries content counts and the space's front-end URL, which tells you how much already exists before you plan anything. 3. `list-section-template-tool` → existing templates with their prop ids, keys and types. 4. `list-pages-tool` → existing pages and paths. 5. `list-categories-tool` / `list-data-items-tool` → existing structured data. The space's existing shape drives the component design. Never invent a template or prop that you have not either read or created. `garchi-manage-content` covers how the ids from these calls feed every subsequent write. ### 6. Configure credentials The application reads content with a server-side API key, separate from MCP. Confirm with the user which space, then have them supply: | Variable | Purpose | | --- | --- | | `GARCHI_API_KEY` | Account API key (dashboard → Settings → API Keys). It belongs to the account, not a space, and covers every space that account owns | | `GARCHI_SPACE_UID` | Target space UID | | `GARCHI_API_URL` | `https://garchi.co.uk/api/v2` | | `GARCHI_PREVIEW_TOKEN` | Per space (Space Settings). Only if draft/preview rendering is needed | Exact names vary slightly per starter kit — check [starter-kits.md](./references/starter-kits.md). The key is **server-side only**: never expose it to the browser, never commit it, never prefix it with `NEXT_PUBLIC_`/`VITE_`/`PUBLIC_`. ### 7. Model the content First confirm the information belongs in Garchi at all — see *When Garchi is the right home for something* above. Then decide what belongs where before writing components: - **Pages + sections** for page-shaped content (marketing pages, landing pages). One section template per reusable component. - **Data items + categories** for collections (blog posts, products, events), with `item_meta` for extra fields. - **Assets** for images used in page sections. Where templates are missing, create them with `garchi-manage-content` so that template prop ids/keys match the component props you are about to write. ### 8. Build the rendering layer Hand off to `garchi-render-content`. It holds the authoritative patterns for the server-side client, the section renderer, nested sections, data items, metadata, assets and preview mode. ### 9. Author content Hand off to `garchi-manage-content` for creating pages, adding sections, filling prop values, and creating data items over MCP. ### 10. Test rendering Run the project's own dev server / test command and check that real content renders: at least one page with sections, and one data-item listing if the project has one. Fix missing-component fallbacks and unsanitized HTML. Anything authored in step 9 is a **draft**: page writes put the page back into draft and new data items are unpublished, and `live` serves published content only. So test against `draft` (with the preview token), and expect an empty or stale `live` result until the user publishes. That is correct behaviour, not a bug in the integration. ### 11. Verify the content/code separation This is the acceptance test for the whole job. Confirm that: - Copy, headings, images and lists come from Garchi props or item fields — not from string literals in components. - Changing a prop value in Garchi changes the rendered page with no code edit. Where MCP is available, prove it: change one value, re-fetch, revert it. - Adding another instance of an existing section to a page needs no new code. - Layout, styling and behaviour live in code; content does not. Report anything you had to hard-code and why. ## Rules - Prefer the official starter kit for greenfield projects on a supported framework; never force one onto an existing project. - Read before you write: inspect the space rather than assuming its shape. - Fetch content on the server. The Garchi API key must not reach the browser. - Do not add dependencies beyond the Garchi SDK unless the user asks. - Do not modify application source code to change business content — change it in Garchi instead. - Agents write drafts; the user publishes. When you finish, list the pages and items you created or changed and tell them to publish those in the dashboard. - If something cannot be determined from the repository, the space, or the official Garchi docs, say so rather than inventing it. ## Reference - Content model and entities: [../garchi-render-content/references/garchi-cms-doc.md](../garchi-render-content/references/garchi-cms-doc.md), or the `get-garchi-cms-guide` MCP tool, or <https://garchi.co.uk/documentation> - Starter kits: [starter-kits.md](./references/starter-kits.md) - REST API: <https://garchi.co.uk/docs/v2> · OpenAPI: <https://garchi.co.uk/docs/v2.openapi> - MCP client setup: <https://garchi.co.uk/mcp-docs>
Referenced files: 1
garchi-manage-content17.1 KB
---
name: garchi-manage-content
description: Operate content in Garchi CMS through the Garchi MCP server — pages and their section trees, section templates and props, data items, categories, item metadata, assets, languages and social posts. Use when the user asks to add or edit pages, change copy or images, build a page from templates, create blog posts or products, reorder or remove sections, add translations, update SEO metadata, or turn Garchi content into a LinkedIn or Instagram post for a person to approve. This is content operations, not code — for fetching and rendering content in an application use garchi-render-content.
---
# Garchi CMS: operating content over MCP
Content lives in the CMS. If the user wants different copy, a new page, a new
blog post or a different image, that is an MCP operation and the application
code should not change at all.
Requires the `garchi` MCP server. If its tools are unavailable, stop and ask the
user to authorize it. Do not substitute source edits for CMS edits.
**Start every session by calling `get-garchi-cms-guide`.** It is free,
read-only, takes no arguments, and returns the current content model and field
rules straight from the server. It is more current than this file. Read it
before planning any write.
## The one thing to understand: ids flow between calls
Almost every Garchi tool takes an id that a previous call returned. Nothing is
derivable, nothing is guessable. Most failed Garchi sessions are an agent
inventing an id instead of listing for it.
```
list-space-tool ─────────► space_uid ──► needed by nearly every other tool
│
┌────────────────────────┼────────────────────────┐
▼ ▼ ▼
list-section-template list-pages-tool list-categories-tool
│ │ │
│ section_template_id │ page_id │ category ids
│ + prop template ids │ │
▼ ▼ ▼
create-section-tool ──► get-page-tool ──► section ids create-data-item-tool
│ (mode=draft) │ │
└──────────┬──────────────────────────────┘ ▼
▼ create-meta-for-item
upsert-section-content-tool
(needs page_id + section_id + prop template ids)
```
Two id traps worth knowing:
- `get-page-tool` takes a **`slug`** (`/`, `/about`), not a page id. But
`upsert-section-content-tool`, `delete-section-tool` and the rank tools take a
**`page_id`**. Get the id from `list-pages-tool` and the section ids from
`get-page-tool`.
- `get-data-item-tool`, `update-data-item-tool` and `create-meta-for-item-tool`
take a numeric **`item_id`**, not the slug.
## Working rules
1. **Orient before writing.** `list-space-tool` first. It returns each space's
`space_uid`, its `agent_description`, per-type content counts and, when set,
the front-end URL — enough to tell which space the user means and what
already exists, without further calls.
2. **Read before you edit.** `get-page-tool` with `mode=draft` (or
`get-data-item-tool`) to see current values and ids before changing them.
3. **Verify after you write.** A success message confirms the call ran, not that
the result is what the user wanted. Re-read and check the values landed.
4. **One upsert, all the props.** `upsert-section-content-tool` accepts an array
of props. Fill a whole section in one call rather than one call per field.
5. **Don't re-list what you already have.** Template lists, asset lists and
category lists are stable within a task. Fetch once, reuse. In particular,
`list-assets-tool` returns the entire asset list in one response — never loop
over it.
6. **Match the code to the content.** A section template's props become a
component's props. When creating a template for an existing component, read
the component first and mirror its props. When the component does not exist
yet, say so — `garchi-render-content` builds it.
## Filling a section: the prop value contract
`upsert-section-content-tool` merges by prop template id. Props you send are
written; props you omit are left untouched. Send only what changes.
That is the contract for every Garchi write, not just this one: **only what you
provide changes.** A field or prop sent as `null` or `""` means "empty this"; one
you leave out keeps its current value. So blanking a heading or removing an
image is an explicit empty value, never an omission.
Because of that, never pad a request with nulls for arguments you are not
setting — send the fields that change and nothing else. The fields a record
cannot live without (a data item's `name`, `slug`, `detail_description` and
`categories`; a page's `title`, `description` and `path`) reject an empty value
outright, so a null-padded request fails rather than wiping content.
Each entry in `props` needs the prop template `id` plus **either** `value`
**or** `asset_id`, decided by the prop's type:
| Prop type | What to send |
| --- | --- |
| `media` | `asset_id` from `list-assets-tool`, in the same space. `value` is ignored. Send `asset_id: null` to remove the current image. |
| `select` | `value`, and it must be one of that prop's `allowed_values`. |
| `text`, `longtext`, `richtext`, `date` | `value` as a string. Send `""` to blank it. |
| `icon_lucid`, `icon_hero` | `value` = an icon name from that icon library. |
Sending `asset_id` for a non-media prop is rejected, and so is omitting it for a
media prop. Prop keys are lowercase snake_case.
Pass `language_id` to write a translated value for a space language other than
the default.
## Sequences that work
**Build a page**
1. `list-space-tool` → `space_uid`
2. `list-section-template-tool` → template ids, prop ids, prop types,
`allowed_values`. If the space has no templates, `create-section-template-tool`
first.
3. `create-page-tool` → the shell only: `title`, `path`, `description`
(the meta description), optional `json_ld` for structured data.
4. `create-section-tool` per section — or `create-nested-section-tool` with a
`parent_id` to place one inside another.
5. `upsert-section-content-tool` per section, all props at once.
6. `get-page-tool` with `mode=draft` → verify.
**Edit page content**
`list-pages-tool` → `get-page-tool` (`mode=draft`) → `upsert-section-content-tool`
with just the changed props → `get-page-tool` again.
**Reorder** — `change-section-rank-tool` with `new_index` for top-level
sections, `change-nested-section-rank-tool` (plus `parent_id`) for children.
This is what "move that section up" means; it is not a delete-and-recreate.
**Create a data item**
1. `list-categories-tool` → category ids (`manage-category-tool` with
`action: create` if needed). An item needs at least one.
2. `list-item-meta-tool` → what keys and types similar items already use.
3. `create-data-item-tool` → `name`, unique `slug`, `categories`,
`detail_description` (the HTML body), optional `one_liner` (a one line
summary, max 1000 chars), optional `scheduled_for_datetime`, and `price`
(decimals allowed) / `stock` / `sku` only for sellable items. `sku` is unique
within the space.
4. `create-meta-for-item-tool` per extra field, reusing the keys and types from
step 2.
5. `get-data-item-tool` → verify. The result carries `published`, which will be
false.
6. Tell the user the item is a draft and needs publishing in the dashboard.
**Images** — two different systems, do not mix them:
- *Page sections* use space assets. `list-assets-tool` to find one,
`upload-asset-tool` to add one, then set the `media` prop by `asset_id`. The
asset must belong to the same space; an id from another space is rejected.
- *Data items* take images **inline as base64 data URIs** on the item itself,
first image being the featured one — `png`, `jpg`, `jpeg`, `webp` or
`svg+xml`, max 10 MB each. Data items never use space assets.
- `generate-image-tool` covers both: `image_for: page` returns an `asset_id` to
use in a section prop; `image_for: data_item` needs a `data_item_id` and sets
that item's main image directly.
For `upload-asset-tool`, `file_type` must be an allowed MIME type and the
`file_name` extension has to match it. Omitting the file content opens a browser
upload window for the user and returns a signed upload link — that is the right
path for anything but small files, rather than pushing large base64 through the
conversation. Uploads are rate-limited; if you hit that, wait rather than retry
in a loop.
## Social posts: you draft, a person publishes
A space can connect social channels (LinkedIn, and Instagram where it is
available to that account) in the Garchi dashboard. Over MCP you can read those
channels, draft posts from Garchi content, revise them and hand them to a person
for approval. **That is where your part ends.**
The six tools: `list-social-channels-tool`, `create-social-post-tool`,
`update-social-post-tool`, `get-social-post-tool`, `list-social-posts-tool` and
`request-social-post-approval-tool`.
**Only a person, in the dashboard, can** approve a post, publish it, schedule or
reschedule it, cancel it or withdraw its approval, retry a failed publish, edit a
post that is already live on the network, delete a live post, or connect and
reconnect a channel. No tool does any of these, and asking for one will not
produce one. Do not suggest workarounds.
**Turn a page or item into a post**
1. `get-page-tool` (`mode=draft`) or `get-data-item-tool` — read the source.
2. `list-social-channels-tool` → `channel_id`s. Skip a channel with
`usable: false` and tell the user it needs reconnecting.
3. Write copy suited to each network yourself.
4. `create-social-post-tool` with `body`, `channel_ids`, optional `media`, and
`source_type`/`source_id` pointing at what it was written from.
5. `request-social-post-approval-tool`. This checks the post against every
selected network's rules; an error names the channel and the problem. Fix it
with `update-social-post-tool` and ask again.
6. Tell the user the post is waiting for their approval in the dashboard. Stop.
Rules that matter:
- **Media is referenced, never uploaded.** `media` entries are
`{"source": "space_asset", "id": "<asset id>"}` from `list-assets-tool`, or
`{"source": "data_item_image", "id": "<item id>"}` for an item's feature
image. No URLs.
- **A post has text only, images, or exactly one video** — never both. Attaching
a video removes the other media; attaching an image removes a video.
- **Video must already be a space asset** (`type: uploaded-video`).
`upload-asset-tool` does not accept video, so ask the user to upload it in the
dashboard. LinkedIn takes MP4; Instagram takes MP4 or MOV as a Reel; 500 MB
maximum. Garchi checks the file type and size, not codecs or duration, and
never converts video — the network can still reject a file after approval.
- **Editing an approved or scheduled post withdraws its approval.** It returns to
`pending_approval`. Say so whenever you edit one.
- **Publishing spends the space's credits**: one per successful publish to one
channel, so a post to LinkedIn and Instagram uses two. Failed and cancelled
publishes use none; deleting a published post gives none back. Every social
tool returns `publishing_allowance`. When `can_publish_more` is false you may
still draft, but tell the user it cannot publish until they upgrade.
Tool details, network rules and worked examples:
[social-publishing.md](./references/social-publishing.md).
## Leave notes for the next agent
Spaces, pages, section templates, data items and assets each accept an
`agent_description` — a field meant for agents, not visitors. Use it to record
what a template is for, when a page should be used, or what an asset shows. It
costs one field on a write you are already making and it is what a later session
reads instead of guessing. Fill it in whenever you create something.
## Draft, live, and what MCP cannot do
**You write drafts. A human publishes.** Nothing here reaches the live site on
its own, and that review step is the point: the user sees the change before
their visitors do.
**Pages.** Every content write puts the page back into draft. Verify with
`mode=draft`. `mode=live` keeps serving the last published version, so the site
never shows a half-finished edit — and your change is not visible until the
owner publishes again. A page that has never been published returns "no
published version" on `live`. Rendering drafts in an application needs a preview
token — see `garchi-render-content`.
**Data items.** New and updated items are drafts (`published: false`), and the
content API serves published items only, so a fresh item is not on the site yet.
The exception is `scheduled_for_datetime` (`Y-m-d H:i`, in the future): the item
stays a draft until that time, then Garchi publishes it automatically.
**End every content task by saying what you changed and that the user needs to
publish it in the dashboard.** Reading your work back over MCP shows drafts, so
a clean verification is not evidence that anything is live.
Several things are deliberately outside this server. Tell the user to do them in
the Garchi dashboard rather than looking for a tool:
- **Creating a space.** No tool creates one.
- **Publishing a page or a data item.** Both go live only when the owner
publishes them in the dashboard.
- **Deleting pages, data items, categories or section templates.**
`delete-section-tool` is the only delete here, and `manage-category-tool` only
creates and updates.
- **Anything past requesting approval for a social post**: approving,
scheduling, publishing, cancelling, retrying, editing or deleting a live post,
and connecting a channel.
## Before a change that is hard to undo
Two tools change or remove content that other content depends on:
- **`delete-section-tool`** removes a section, every nested section under it, and
all their prop values. If the page is published, the section stops appearing on
the live site.
- **`update-prop-template-tool`** changes a prop's `key` or `type` on a template
that may be used by many sections across many pages. Existing values can become
invalid for the new type, and published pages reflect the change. Renaming a
key also breaks the matching component prop in the codebase until that is
updated too.
For either one:
1. Read first — `get-page-tool` (`mode=draft`) or `list-section-template-tool` —
so you are acting on the right target.
2. Name the exact page and section, or the exact template and prop, and get an
explicit yes. "Tidy up this page" is not approval to delete anything.
3. Confirm one item at a time. For a batch, show the full list first.
4. For a prop change, check what the change breaks on the rendering side and say
so before making it.
Garchi keeps automatic restore points for recent page, section-template and data
item changes, restorable from the content history in the dashboard. Treat that
as a safety net for the user, not a licence to act without asking: the window is
limited, and **no MCP tool restores anything** — from here every one of these
changes is final.
## Costs and plan limits
`generate-image-tool` spends part of the account's monthly AI image allowance,
shared across all of the user's spaces. Ask before generating, keep the prompt
under 200 words, describe subject, style, colour and composition, leave a clear
zone where text will overlay, and do not ask for text inside the image.
Creating pages, data items, categories and generated images is capped by the
user's subscription plan. When a tool reports a limit reached or no active
subscription, **stop** — that is a billing state, not a transient failure.
Retrying it burns calls and changes nothing. Report which limit was hit and what
was created before it.
Social publishing credits are counted per space: 2 on Sandbox, 300 on Basic,
unlimited on Pro, unlimited or custom on Business. Drafting and requesting
approval never spend them — only a successful publish does, and a person starts
that. Read `publishing_allowance` rather than assuming a plan.
## Stop conditions
- Never retry a failing call more than twice. Re-read the state, then report.
- A validation error names the exact field and rule. Fix that field; do not
resend the same payload hoping for a different outcome.
- If an id is missing, list for it. Never guess one.
- Tool calls are recorded against the user's account, so loops are not free.
## Reference
- [mcp-tools.md](./references/mcp-tools.md) — full tool inventory, arguments,
and safety annotations
- [social-publishing.md](./references/social-publishing.md) — social post tools,
network rules, the approval boundary and worked examples
- `get-garchi-cms-guide` — the live content model from the server
- Content model background:
[../garchi-render-content/references/garchi-cms-doc.md](../garchi-render-content/references/garchi-cms-doc.md)
or <https://garchi.co.uk/documentation>
Referenced files: 2
garchi-render-content7.4 KB
---
name: garchi-render-content
description: Write the application code that fetches and renders Garchi CMS content — the server-side Garchi client, page and section renderers, nested sections, data items (blogs/products), item metadata, assets, SEO metadata and draft/preview mode — in Next, Nuxt, Laravel, SvelteKit or any other stack, via the Node SDK, PHP SDK or REST API. Use when implementing or fixing the frontend/server integration for Garchi content. Code only — to create or edit the content itself use garchi-manage-content; to plan a whole project or pick a starter kit use garchi-build-site.
---
# Skill: garchi-render-content
## Scope
- ✅ Build or improve the code needed to **fetch and render** Garchi CMS content (pages, sections, data items).
- ✅ Integrate Garchi CMS into an existing codebase without breaking conventions.
- ❌ Do not manage CMS content (create pages/sections/assets/templates) here — that is `garchi-manage-content`, over MCP.
- ❌ Do not choose or bootstrap a starter kit here — that is `garchi-build-site`.
## Quick start: choose your path
1. **Fresh project → a starter kit is probably right.** Hand back to
`garchi-build-site`, or read
[starter-kits.md](../garchi-build-site/references/starter-kits.md). Kits ship
the SDK, env config, a section renderer and example components.
2. **Existing project, Node or PHP backend → use the SDK** (`@garchicms/garchi-node-sdk` or `garchicms/garchi-sdk-php`).
3. **Existing project, any other backend → use the REST API** via the OpenAPI spec.
4. **Always render from the server** (SSR / server runtime). The API/SDK is **server-side only** and does not support client-side calls.
## Configuration contract
Confirm these exist before writing fetch code (starter kits create them for you):
| Env var | Purpose | Required |
| --- | --- | --- |
| `GARCHI_API_KEY` | Account API key used to authenticate all API/SDK calls. Account-level, not space-level: one key covers every space the account owns | Yes |
| `GARCHI_SPACE_UID` | Target space UID passed to most calls | Yes |
| `GARCHI_API_URL` | API base, `https://garchi.co.uk/api/v2` | Yes |
| `GARCHI_PREVIEW_TOKEN` | Enables draft/preview mode. Per space (Space Settings → Preview Token) | Only if preview is needed |
Nuxt keeps these values in `runtimeConfig` in `nuxt.config.ts` rather than in a
`.env` file. Match whatever the project already uses rather than introducing a
second convention.
**Rule:** the API key is **server-side only**. Never expose it to the client, never
prefix it with `NEXT_PUBLIC_`/`VITE_`/`PUBLIC_`, never commit it, and never call
the Garchi API from the browser.
## Always (non-negotiable rules)
1. **Preserve Visual Editor attributes**
- For every section component, forward unknown/extra props/attributes to the **root element** (outermost wrapper).
- Framework-agnostic rule: "Unknown attributes must not be dropped; attach them to the root/host element."
- Patterns:
- React/Preact/Solid: spread `...other` on root
- Vue: `v-bind="$attrs"` on root (if `inheritAttrs: false`, re-bind manually)
- Svelte: spread `...$$restProps` on root
- Angular: preserve/pass through host attributes; do not strip unknown attrs
- Web Components: keep attrs on host or forward to outer wrapper
- Laravel Blade: ensure attributes are passed to the root element of the section component `{{ $attributes->merge() }}`
2. **Content belongs in Garchi, not in components**
- Copy, headings, image URLs and list contents come from section props or data-item fields. Do not hard-code them, and do not "temporarily" inline content that the CMS should own.
- If a value has nowhere to live in the CMS yet, add the prop or template through `garchi-manage-content` rather than baking the value into code.
- Components own layout, styling and behaviour. They should not encode which page they appear on.
3. **Do not modify reference snippets/docs**
- Treat [code-snippets](./references/code-snippet.md) and provided examples as reference. Do not rewrite them unless asked.
- The reference code is React/Next. Adapt the same logic to the target stack using its native primitives (component resolution, attribute forwarding, HTML sanitization).
4. **Keep codebase conventions**
- Follow existing linting, formatting, naming, and folder conventions.
- Reuse existing components (Markdown/HTML sanitizer, typography atoms) instead of adding new ones or new dependencies.
- Avoid large refactors unless requested.
## Reference resources — load on demand
Read only what the current task needs. Do **not** fetch the full OpenAPI spec upfront.
| When you need to… | Load |
| --- | --- |
| Understand entities & hierarchy (space, page, section, data item, meta) | [garchi-cms-doc.md](./references/garchi-cms-doc.md) |
| Copy-adaptable rendering code (React reference) | [code-snippet.md](./references/code-snippet.md) |
| Node backend call signatures & types | [garchi-sdk-node.md](./references/garchi-sdk-node.md) |
| PHP backend call signatures & types | [garchi-sdk-php.md](./references/garchi-sdk-php.md) |
| Which starter kit ships what | [starter-kits.md](../garchi-build-site/references/starter-kits.md) |
| Exact request/response shapes, or an endpoint not in the SDK | [OpenAPI spec](https://garchi.co.uk/docs/v2.openapi) |
## Recommended implementation workflow
### A) Choose access method
- Prefer starter kits for fresh projects (see Quick start).
- Prefer SDKs where available (Node / PHP).
- If using the raw API, create a small server-side service layer (DRY/SOLID, typed, reusable). Raw API calls must be made from the server. Use the OpenAPI spec for reference.
### B) Build the rendering pipeline
1. Fetch page/data item from server-side (SSR/server runtime).
2. Render sections via a single section renderer (mapper) — `GarchiComponent`.
3. Each section maps to a reusable component (resolved from the section `description`, falling back to `name`).
4. Support nested sections (`subsections`) if present — the renderer is reused recursively.
### C) Quality + safety
- Sanitize HTML before rendering (XSS). Reuse the project's sanitizer/Markdown atom if present.
- Handle errors gracefully (notFound, fallback UI).
- Use stable keys (prefer section id/uid over array index).
- Add a consistent "missing component" fallback that fails gracefully and logs what's missing.
- Cache/revalidate page fetches appropriately; fetch lists (assets/templates) once and reuse.
- Prefer typed section props; validate critical CMS payload shape at boundaries where helpful.
## Definition of Done
- Pages/data items render correctly in the chosen stack.
- Visual Editor attributes are preserved on all section components.
- Preview/draft mode works (if required).
**If a page or item renders empty in `live`, check whether it is published before
debugging the code.** Garchi serves published content only: page content writes put the
page back into draft, and data items are created unpublished, so freshly authored content
is missing from `live` by design until the user publishes it in the dashboard. Fetch the
same content in `draft` mode to confirm it exists.
- Errors are handled without infinite retries/loops.
- HTML content is sanitized where applicable.
- No content that belongs in Garchi is hard-coded in components.
## Loop prevention (stop conditions)
- Do not retry the same failing operation more than 2 times.
- After an update/fetch, verify state once; if still incorrect, stop and report what's missing.
Referenced files: 4
Package details
Publisher declarations from the archived package. These are separate from our research and the live service's terms.
- Package author
- LumenHarbor Digital Solutions Limited
Package observed Sep 30, 2026.
Technical details
- First seen
- Sep 30, 2026 · 22:02 UTC
- Last seen
- Oct 1, 2026 · 18:00 UTC
- Collection status
- Collected
plugin_asdk_app_698da77dd2f48191ba19e15b0b188796
Download plugin data (JSON)