glokki

BlogEngineering

We rebuilt glokki.com with an AI agent and our own CMS

Two weeks, 31 commits, one agent. What worked when Claude Code built our site through the glokki MCP server, what broke, and the 18 documentation gaps we found on the way.

glokki team4 min read

In October we rebuilt glokki.com: the home page, a contact page, a request-access flow and a /docs section with 15 guides. We did not write most of it by hand. An AI agent (Claude Code) wrote the code in the repo and built the pages inside glokki itself, through the glokki MCP server: adding blocks, filling in props, publishing pages and editing the navigation.

Every one of the 31 commits between 8 and 21 October is co-authored by the agent. This post is what that looked like, including the parts that did not work.

The setup

glokki.com is an ordinary glokki tenant: a Next.js app that renders pages from the delivery API. There are two kinds of work on a site like this, and the agent did both:

  • Code, in the repo. Blocks are React components with a Zod schema, declared with defineBlock(). The agent wrote the hero, the bento grid, the FAQ, the docs shell, sidebar and article blocks, and the plumbing around them: ISR, the revalidation webhook, the asset and OG-image proxies, sitemap.xml, robots.txt.
  • Content, in the CMS. Once a block is deployed, it shows up in the editor, and the MCP server lets an agent use it the same way an editor would: create_page, add_block, update_block_props, publish_page, add_nav_item, set_layout_field.
agent ──► repo:  defineBlock({ type: "hero", propsSchema, component })
      ──► deploy
      ──► MCP:   add_block(page, "hero") → update_block_props → publish_page

That split matters. The agent never edits content by writing JSON into a file, and nobody has to click through the editor to try out a block the agent just wrote. A marketer can open the same page later and change a headline in the visual editor without knowing an agent built it.

What worked

Docs from Markdown, in one script. Our guides live as Markdown. The agent wrote scripts/import-docs.ts, which talks to the MCP server directly: it matches entries by slug, creates missing ones as drafts, fills in category and order, seeds the block tree and publishes. It is idempotent and retries on rate limits, so we re-run it whenever the guides change.

Agent-readable output. Since an agent was building the site, it made sense to make the site readable by agents too. Every page is also served as Markdown (/docs/mcp-server.md, or Accept: text/markdown), and /llms.txt and /llms-full.txt list the whole site. Each block declares how it renders to Markdown, next to its React component, so the two never drift apart.

Performance work with numbers. Public pages moved to ISR and the docs sidebar is now rendered on the server, trimmed to the fields it shows: about 3 KB for the whole list of guides, against about 420 KB with every guide's full text (measured on 25 October).

Accessibility as a pass/fail check. The agent ran axe on every page and fixed what it found until the whole site came back clean for WCAG 2.2 AA. With an agent, "make it pass" is a better instruction than "make it accessible".

What broke

Building your own site on your own product is the fastest way to find out what your docs leave out. We kept a list as we went and ended up with 18 gaps in the glokki documentation and SDK. A few that mattered:

  • Production silently set to noindex. cmsMetadata() adds noindex, nofollow unless APP_ENV=production, and the docs did not mention APP_ENV anywhere. Following the guide to the letter would keep a site out of Google without any warning.
  • Images never cached on Vercel. The CMS sends Cache-Control: public, max-age=31536000, immutable, but Vercel's CDN does not cache function responses without s-maxage or CDN-Cache-Control, so every image request ran a function. Fixed in @glokki-cms/sdk 0.17: the proxies add CDN-Cache-Control themselves.
  • A nested field the editor could not set. A z.object() field in a block schema is serialized as plain text, so the MCP server rejected the object the agent sent and the header's mobile menu could never be configured. Phones had no menu until we flattened the schema.
  • The agent cannot see a new block until a human opens the editor. The MCP server works from a schema snapshot that refreshes when the editor is opened. After every deploy that adds a block, add_block rejects it until someone opens the editor once. This was the only step in the loop that needed a person.

Smaller ones: update_block_props cannot delete a prop, only blank it; header and footer share one draft token, so editing one makes the other stale; opening a page in the editor flips its status to draft. Each one cost the agent a failed call and a retry, and cost us a line in the list.

What we would do differently

  • Flat block schemas from the start. Arrays of objects work, nested objects do not (yet). Designing blocks around that would have saved a redesign of the header.
  • Write the gap list in the open. We kept it in the repo, but most of it belongs in the docs, so the next team does not have to find the same problems.
  • Let the agent verify, not just build. The best results came from tasks with a check at the end: typecheck, axe, a request against the live page, a diff of the Markdown output. "Done" with no check meant nothing.

Try it

The MCP server is part of every glokki workspace. Point Claude Code, Cursor or any MCP client at it and an agent can build pages from your own blocks. The setup is in the MCP server guide, and the site you are reading is the reference integration.

Create a free account and try it on your site.

More from the blog

Let an agent build your next page

Free during beta · No credit card required