Prompt Engineering for Rabbithole

Rabbithole Documentation — github.com/ajbt200128/rabbithole — live at isarabbithole.com

Rabbithole generates each page in complete isolation: a single prompt is the only input the LLM receives. There is no shared memory, no session state, no inherited context between pages. This makes prompt quality the single most important factor in whether your site feels coherent and intentional or like a random collection of unrelated pages. This guide covers everything you need to write prompts that produce consistent, high-quality results across deep link chains.

Contents

1. Writing a Good Seed Prompt

The seed prompt is the description of your homepage — the founding document of the entire site. Every other page eventually traces its lineage back to context you establish here. Treat it as a complete creative brief: if you would need to tell a designer about it, put it in the seed prompt.

Required elements of a seed prompt

Subject matter & purpose
What is this site about? Who is the audience? What does a visitor come here to do? Be specific. "A documentation site for a Rust CLI tool that generates websites with LLMs" is better than "a tech website."
Visual design language
State background color, text color, link colors (normal and visited), font choices for headings vs. body, border styles, whether gradients/shadows/rounded corners are used or explicitly forbidden. Example: "White background (#ffffff), Arial/Helvetica body, Times New Roman headings, blue links (#0000cc), visited purple (#551a8b), no gradients, no rounded corners."
Navigation structure
List every nav item by label and absolute path. Specify the separator character (pipe, bullet, dash). Specify placement (top, sidebar). The model cannot invent the right URLs — you must supply them explicitly.
Tone and voice
"Formal technical documentation," "friendly tutorial blog," "corporate marketing," "dry academic," "playful and irreverent." Tone affects word choice, sentence length, use of humor, heading styles, and more.
Recurring terminology / lore
Any project-specific terms, brand names, character names, or fictional concepts that will recur across pages. Define them here so linked prompts can carry them forward.
Layout density
"Dense, information-heavy like craigslist" vs. "spacious with lots of whitespace like Apple.com." This governs padding, line-height, use of horizontal rules, table borders, etc.
Content requirements for this specific page
After the global context, describe what goes on this page: sections, headings, examples, call-outs.

Example seed prompt (annotated)

Documentation homepage for Rabbithole — an open-source Rust tool
(github.com/ajbt200128/rabbithole, live at isarabbithole.com) that
dynamically generates entire websites on the fly using LLMs (Anthropic
Claude).                                                         <-- subject matter

DESIGN: Plain minimal HTML like gcc.gnu.org or Craigslist. White
background (#ffffff), system fonts (Arial/Helvetica body, Times New
Roman headings), no gradients, no shadows, no rounded corners.  <-- visual design
Blue links (#0000cc), visited purple (#551a8b).                  <-- link colors
Pre/code with #f4f4f4 bg and 1px solid #ccc. Dense layout. No JS.

NAV (pipe-separated, top of page):                               <-- nav structure
  Home | Getting Started | Architecture | Configuration |
  Web Tools | Deployment | Examples | About
  (paths: /index.html, /docs/getting-started.html, ...)

TONE: Technical, terse, direct documentation prose.             <-- tone

CONTENT: Hero intro explaining what Rabbithole does; feature list;
quick-start snippet; links to all doc sections.                  <-- page content

Note how design, nav, tone, and content are all separable concerns, each addressed explicitly. The more precisely you specify each dimension, the less the model has to guess — and guessing is where inconsistency enters.

2. Why Linked-Page Prompts Must Be Self-Contained

When Rabbithole generates a linked page, it invokes the LLM in a fresh context. The only input is the prompt string you wrote when generating the parent page. There is no:

This is not a bug — it is a deliberate architectural choice that enables caching, parallelism, and stateless deployment. But it means every prompt must carry the full blueprint.

❌ BAD: "About page for the Rabbithole project."
The model knows nothing about Rabbithole's design, nav structure, color scheme, or tone. It will produce a generic blue-gradient card layout that looks nothing like the rest of the site.
✓ GOOD: "About page for Rabbithole — open-source Rust LLM site generator (github.com/ajbt200128/rabbithole). DESIGN: white bg #ffffff, Arial/Helvetica body, Times New Roman headings, blue links #0000cc, visited #551a8b, no gradients, no rounded corners, pre/code #f4f4f4 bg 1px solid #ccc, dense layout, no JS. NAV (pipe-separated): Home|Getting Started|Architecture|Configuration|Web Tools| Deployment|Examples|About (/index.html, /docs/getting-started.html, ...). TONE: terse technical docs. CONTENT: project history, motivation, contributors, license (MIT), links to GitHub."

The good version could stand alone as input to any LLM and produce a page visually and tonally consistent with the rest of the site, even if the model has never seen any other page.

Think of each prompt as a complete creative brief

Imagine you are handing off a one-page design brief to a contractor who will never see any other page of your site. They will produce exactly what you describe and nothing more. Everything they need must be on that sheet of paper. The same principle applies here.

3. Common Failure Modes

3.1 Inconsistent styling

The most common failure. Symptoms: linked pages use different color schemes, different font stacks, different heading hierarchy, gradients appear where none were wanted, link colors differ.

Root cause: The linked-page prompt omitted the design specification, so the model fell back to its default aesthetic (often modern Bootstrap-style with rounded corners and drop shadows).

Fix: Always copy the full design block — background, fonts, link colors, border styles, code block styles — verbatim into every linked-page prompt. Consider defining a reusable "design spec" string in your seed prompt comments and manually pasting it everywhere.

3.2 Topic drift

The page starts on-topic but drifts into tangential or invented content. A configuration page for a Rust CLI tool starts discussing Python config parsers. A character bio in a fantasy site contradicts lore established on the homepage.

Root cause: The prompt described the subject too vaguely ("configuration options") without grounding it in the specific project context and constraints.

Fix: Always include the project name, its actual domain (Rust, LLMs, documentation, etc.), and concrete facts (GitHub URL, actual config keys, real character names). Specificity anchors the model.

3.3 Vague prompts producing generic pages

The page is technically on-topic and well-designed, but it contains nothing specific to your project. It reads like boilerplate that could describe any tool of the same type.

Root cause: Prompt said "explain how to deploy the tool" without specifying the actual deployment method (systemd, Docker, fly.io, etc.), command-line flags, config file format, or platform constraints.

Fix: Front-load concrete facts. If you want the page to mention specific flags, name them. If there's a real config file format, describe its keys. If there's a specific deployment platform, say so. The more specific facts you provide, the less the model must hallucinate.

3.4 Navigation link rot

Linked pages generate nav bars with different items, different ordering, or different paths than the rest of the site, causing broken or inconsistent navigation.

Root cause: Nav structure was not specified in the linked-page prompt, or was specified incompletely (labels but no paths, or paths but no labels).

Fix: Always include the full nav specification: every label, its separator character, and its exact absolute path. Example:

NAV (pipe-separated, top of every page):
Home | Getting Started | Architecture | Configuration | Web Tools | Deployment | Examples | About
/index.html | /docs/getting-started.html | /docs/architecture.html | /docs/configuration.html |
/docs/web-tools.html | /docs/deployment.html | /examples.html | /about.html

3.5 Missing or broken local links on generated pages

A generated page fails to link to subpages, or generates links with incorrect or non-canonical paths (e.g., getting-started instead of /docs/getting-started.html).

Fix: In your prompt, explicitly list the links the page should generate and the exact URL paths they should point to. Rabbithole will only cache and serve pages whose URLs were registered in the mappings output. A link with the wrong path will 404.

3.6 Heading hierarchy collapse

All headings render at the same size, or the page uses only <h1> for everything. Alternatively, the page has no semantic structure at all — just a wall of text.

Fix: Specify heading hierarchy in the design spec: "h2 with bottom border, h3 bold sans-serif, h1 serif for page title only." Include an example in the prompt if needed.

3.7 Context dilution in deep chains

Pages 1–2 look consistent. By page 4–5 (page → subpage → sub-subpage → deep link), the design has subtly shifted: slightly different padding, a color that's close but not quite right, a nav item that went missing.

Root cause: Each page author (the model) rewrote the design spec slightly when writing child prompts, introducing small mutations that compound across generations.

Fix: See Section 4 on maintaining consistency in deep chains.

4. Maintaining Consistency Over Deep Link Chains

Every time a page is generated, it also writes prompts for its child pages. If the model slightly paraphrases the design spec when writing those child prompts, the error compounds: grandchild pages get a paraphrase of a paraphrase, and so on. After 3–4 hops, the design can drift noticeably.

Strategy 1: Use a literal, verbatim design block

Structure your design spec so it reads like a structured data block rather than prose. Prose invites paraphrasing; structured data with explicit key-value pairs is more likely to be preserved verbatim:

DESIGN SPEC (copy verbatim into all child page prompts):
  bg: #ffffff | text: #000000 | link: #0000cc | visited: #551a8b
  body-font: Arial, Helvetica, sans-serif, 14px
  heading-font: Times New Roman, serif
  h1: 24px bold | h2: 18px bold, border-bottom: 1px solid #000
  code/pre: bg #f4f4f4, border 1px solid #ccc, Courier New 13px
  no gradients | no shadows | no rounded corners | no JS
  layout: dense, max-width 860px, centered

The key-value format is harder to accidentally rewrite in a different way than flowing prose like "use a white background with Arial fonts and blue links."

Strategy 2: Explicitly instruct child prompts to copy the design spec

In your seed prompt (and in every page prompt), include an instruction like:

IMPORTANT: When writing prompts for linked pages in the mappings JSON,
always include the full DESIGN SPEC and NAV SPEC blocks above, verbatim,
at the top of each child prompt. Do not paraphrase or abbreviate them.

This "meta-instruction" tells the model generating each page to preserve fidelity when it writes its children's prompts. It cannot guarantee perfect preservation, but it significantly reduces drift.

Strategy 3: Use structural anchors

Reference canonical external anchors that uniquely identify the project and its aesthetic in the real world:

"Plain minimal HTML like gcc.gnu.org or Craigslist — not Bootstrap,
not Tailwind, not Material Design."

These reference points activate strong, specific model priors. "Like gcc.gnu.org" is harder to drift away from than "simple and minimal" because the model has seen gcc.gnu.org and knows what it looks like.

Strategy 4: Limit link depth where possible

Every extra hop in a chain is another opportunity for drift. If your site has a deep hierarchy, consider whether some pages can be combined, or whether very deep pages (3+ hops from root) really need to be generated dynamically rather than linked to as static anchors or external URLs.

Strategy 5: Use concrete negative constraints

Don't just say what you want — say what you explicitly forbid. This is especially valuable for design:

NO gradients. NO box-shadow. NO border-radius. NO external CSS frameworks.
NO JavaScript. NO dark mode toggle. NO sticky headers. NO hero images.

Negative constraints are highly stable across paraphrasing: even if the model rewrites your design spec, "NO gradients" is hard to accidentally invert.

5. Prompt Length vs. Context Fidelity

Longer prompts carry more context and produce more consistent, accurate results. But each prompt is passed to the LLM at generation time, and the LLM must also write child prompts of similar length. This creates a direct cost tradeoff.

Prompt length Cost per page Consistency Accuracy Risk
Very short (<50 words) Minimal Poor Poor Generic, drifted pages
Short (50–150 words) Low Moderate Moderate Design drift after 2–3 hops
Medium (150–400 words) Moderate Good Good Some drift in deep chains
Long (400–800 words) Higher Very good Very good Context window pressure on deep chains
Very long (>800 words) High Excellent Excellent Model may truncate child prompts

Practical recommendation

For most sites, 150–400 words per prompt is the practical sweet spot. This is enough to carry a full design spec, nav structure, tone descriptor, and page-specific content brief without creating runaway token cost or triggering child-prompt truncation.

The design spec and nav spec tend to be the most important content to preserve and are also among the most compressible: a key-value design block covering all critical styling can be written in under 60 words and will dominate consistency outcomes more than any other factor.

Separate fixed context from variable content

Structure prompts with a fixed "header" (design + nav — same for every page) and a variable "body" (page-specific content). This lets you optimize each section independently:

[FIXED HEADER — copy verbatim to all child prompts, ~80 words]
Site: Rabbithole docs (github.com/ajbt200128/rabbithole, isarabbithole.com)
bg #ffffff | text #000 | link #0000cc | visited #551a8b
fonts: Arial/Helvetica body 14px, Times New Roman headings
h2: 18px serif, border-bottom 1px solid #000
pre/code: bg #f4f4f4 1px solid #ccc Courier New 13px
no gradients, no shadows, no rounded corners, no JS, max-width 860px
NAV (pipe | ): Home /index.html | Getting Started /docs/getting-started.html |
Architecture /docs/architecture.html | Configuration /docs/configuration.html |
Web Tools /docs/web-tools.html | Deployment /docs/deployment.html |
Examples /examples.html | About /about.html

[VARIABLE BODY — specific to this page]
PAGE: Configuration reference. Cover: environment variables (ANTHROPIC_API_KEY,
RABBITHOLE_PORT, RABBITHOLE_CACHE_DIR), the rabbithole.toml format,
cache backend options, timeout settings, log level. Use a table for each
config key with columns: key, type, default, description.

When to invest in longer prompts

When shorter prompts are acceptable

6. Prompt Templates

The following templates can be copied and adapted for common page types.

Standard documentation page

[PAGE NAME] page for Rabbithole — open-source Rust LLM site generator
(github.com/ajbt200128/rabbithole, live at isarabbithole.com).
Each page generated in isolation by Anthropic Claude; only prompt carries context.

DESIGN: white bg #ffffff, Arial/Helvetica body 14px, Times New Roman headings,
blue links #0000cc, visited #551a8b, pre/code bg #f4f4f4 1px solid #ccc
Courier New 13px, h2 with border-bottom 1px solid #000, dense layout,
no gradients, no shadows, no rounded corners, no JS, max-width 860px centered.

NAV (pipe-separated top of page):
Home | Getting Started | Architecture | Configuration | Web Tools | Deployment | Examples | About
/index.html | /docs/getting-started.html | /docs/architecture.html | /docs/configuration.html |
/docs/web-tools.html | /docs/deployment.html | /examples.html | /about.html

TONE: Terse technical documentation prose. Direct. No marketing language.

CONTENT:
[Describe specific sections, headings, tables, code examples here]

Example/showcase page

Examples page for Rabbithole (github.com/ajbt200128/rabbithole, isarabbithole.com).
[Paste full DESIGN and NAV blocks from above]
TONE: Practical, demo-focused. Show real seed prompts and screenshots.
CONTENT: 3–5 example sites built with Rabbithole. For each: site name, seed prompt
used, link to live URL, brief description of what makes it interesting.
Include a section on example failure cases. Link to /docs/prompt-engineering.html.

7. Prompt Quality Checklist

Before finalizing a seed prompt or a linked-page prompt, verify:

ItemIncluded?
Background color (hex)
Text color (hex)
Link color — normal (hex)
Link color — visited (hex)
Body font family + size
Heading font family
h1, h2, h3 styles described
pre/code background + border
Explicit no-gradient / no-shadow / no-border-radius (if desired)
Max-width and centering
Full nav: all labels + all paths
Nav separator character
Tone description
Project name + GitHub URL + live URL
Page-specific content description
Instruction to copy design spec to child prompts
Any specific links this page should generate (with paths)
Note: This checklist is most useful for your first several pages. Once you have a standard prompt header that passes all checks, copy it mechanically into each new prompt. The goal is to make correct prompts the path of least resistance.

See also