---
title: "Custom pages on ComStack"
description: "Vibe-coded Astro/HTML pages with total layout freedom — what custom pages are, what they can do, and where the hard boundaries sit."
url: "https://comstack.ai/docs/custom-pages/"
---
## What this is

A **custom page** is a ComStack page whose entire body is your own code — a complete Astro component or HTML document, uploaded as one opaque `body_source` with the `upload-custom-page` tool. The platform never rewrites it: what you author is what ships (Astro's standard build applies; plain-HTML bodies are round-tripped through a standards-compliant parser). Layout, styling, animation, and interactivity are entirely yours.

Custom pages exist for everything a structured markdown template can't express: landing pages, product launches, interactive demos, calculators, animated showpieces, brand-heavy marketing pages. The rest of the site — docs, blogs, FAQs — belongs to `knowledge` pages and their templates; see [Knowledge vs custom pages](/docs/mcp/page-types.md).

## What is possible

Treat a custom page as a blank canvas with a fast CDN behind it:

- **Total layout freedom** — your own grids, sections, hero treatments, typography. No template structure is imposed on the body.
- **Animation** — CSS keyframes, scroll-driven effects, transitions, SVG animation. Inline `<style>` and `<script>` tags ship as authored.
- **Interactivity** — vanilla JS calculators, tabs, accordions, canvas effects, form-like widgets. No framework runtime is added or required.
- **Automatic translation** — wrap your visitor-facing strings in markers and every configured locale gets a native version of the page at publish, same URL structure, correct `hreflang`. You write the page once.
- **Platform AEO for free** — title/description metadata, JSON-LD, Open Graph, sitemap and `llms.txt` inclusion are handled by the platform shell around your body.

A page generated in Lovable, v0, or Bolt — or written by hand, or by an AI agent in one shot — can be live in minutes: add markers, upload, publish.

## How it works

1. **Author** a complete Astro component or HTML document elsewhere (any tool, any agent).
2. **Mark translatable strings** with `<T key="…" default="…">` (Astro/JSX) or `data-t-key` (HTML) — the upload extracts them into `translatable_strings`; publish translates them into every configured locale. Never hand-translate. See [Translation](/docs/custom-pages/translation.md).
3. **Upload** with `upload-custom-page` (`project_id`, `project_name`, `slug`, `body_source`, `title` 10–60 chars, `description` 50–160 chars). The result is a draft — nothing is live yet.
4. **Publish** with the standard two-step flow: `publish` (dry-run manifest + confirmation token) → `publish-confirm` → poll `publish-status`. See [Publishing](/docs/mcp/publishing.md).

Re-uploading the same slug replaces the body in one call; the live URL stays up until you publish the new draft.

## Hard boundaries

Three constraints are non-negotiable, by design:

1. **The body is opaque, but the envelope is not.** Your code renders inside the platform shell that provides `<head>` metadata, AEO tags, locale routing, and security headers. You author the `<body>`-level content, not the document head.
2. **Dangerous href schemes are rejected at upload.** `javascript:`, `data:` and `vbscript:` URLs in `href`/`xlink:href` attributes fail the upload outright — the body ships to the browser as authored, so the gate is at the door. `data:` URLs in `src` (inline images) are fine. See [Troubleshooting](/docs/custom-pages/troubleshooting.md).
3. **Quality is gated, not hoped for.** Custom pages are audited against Lighthouse with a bar of **95** in performance, accessibility, best practices, and SEO at pre-publish. Build to that bar from the first line. See [Quality gates](/docs/custom-pages/quality.md).

## When to use it

- A landing or campaign page that must look nothing like the rest of the site
- A product launch page with bespoke animation and scroll effects
- An interactive page — calculator, configurator, quiz — in plain HTML/JS
- Importing a vibe-coded export from Lovable, v0, or Bolt
- Any page where a markdown template is the wrong tool

For structured editorial content (docs, articles, FAQs), use a knowledge page instead — you get templates, validation, and FAQ JSON-LD that custom pages deliberately do not have.

## Example

The smallest valid custom page body (HTML form):

```html
<section class="hero">
  <h1 data-t-key="hero.title">Fresh bread, every morning</h1>
  <p data-t-key="hero.sub">Family bakery in the old town since 1962.</p>
  <a class="cta" href="tel:+34600000000" data-t-key="hero.cta">Call the bakery</a>
</section>
<style>
  .hero { min-height: 60vh; display: grid; place-content: center; text-align: center; }
  .cta { display: inline-block; padding: .8rem 1.6rem; border-radius: 999px; background: #1a7f5a; color: #fff; }
</style>
```

Upload it, publish, and `/es/` (plus every other configured locale) renders the same layout with translated strings substituted into the marker positions. Two fully annotated walkthroughs — minimal and advanced — are in [Recipes](/docs/custom-pages/recipes.md).

## Common errors

- **Marker mistakes** — unmarked strings stay untranslated; malformed markers reject the upload with character offsets. See [Translation](/docs/custom-pages/translation.md).
- **`wrong_tool_knowledge_page`** — the slug already belongs to a markdown page. Pick another slug or edit that page with `update-page`.
- **Lighthouse failures** — heavy images, render-blocking scripts, missing alt text. The fixes are mechanical; see [Quality gates](/docs/custom-pages/quality.md).

The full catalogue with exact messages and fixes: [Troubleshooting](/docs/custom-pages/troubleshooting.md).

## Related

- [Author a custom page](/docs/custom-pages/authoring.md) — the contract and the loop, end to end
- [Translation](/docs/custom-pages/translation.md) — markers, `translatable_strings`, `canonical_slug`
- [Quality gates](/docs/custom-pages/quality.md) — Lighthouse, performance and AEO expectations
- [Troubleshooting](/docs/custom-pages/troubleshooting.md) — every rejection and its fix
- [Recipes](/docs/custom-pages/recipes.md) — annotated minimal and advanced examples
- [Example gallery](/docs/custom-pages/examples.md) — live pages built the way these docs teach
