← Plugin catalog
Developer Tools

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

Plugin package12 files · 40.9 KBBrowse files →
Skill instructions
garchi-build-site10.6 KB

View saved version →

---
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

View saved version →

---
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

View saved version →

---
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)