What you'll learn

By the end of this you'll understand how the Baseline prompt library was designed and built — the schema decisions, the rendering strategy, the UX trade-offs, and the editorial work that turned a list of strings into something people actually bookmarked.

This is as much a product design case study as a technical one. The code was the easy part.

Who this is for

  • Developers building curated resource libraries (prompts, snippets, templates, tools)
  • Product builders who want to ship useful AI tooling without building a full product
  • Content strategists wondering how to turn loose internal docs into structured, SEO-friendly features

You can skip this if you're building a full prompt-management SaaS with user accounts and saved prompts. This is a read-only, curated, editorial library — not a user-generated platform.

What is the prompt library? Plain English

It's a curated collection of AI prompts organised by use case (writing, coding, analysis, creativity) with a one-click copy button, a short description of when to use each prompt, and a plain-English explanation of why it works.

It started as a Notion database of "prompts that worked well" maintained by the Baseline team. The problem was that it was only useful to people with access to the Notion. Making it public and searchable on the site turned out to be a multi-week project, not a weekend.

Prerequisites

  • Familiarity with Next.js App Router and React state
  • Basic understanding of MongoDB or any document store
  • Some exposure to content schema design (or read the [content hub case study](/case-studies/building-baseline-content-hub) first)

Setup from zero

Step 1 — Define what a prompt actually is

This sounds trivial. It wasn't. The first attempt at a schema was:

{ id: string; text: string; category: string }

That lasted two days. The problems:

  • "Category" was too coarse. Prompts needed both a use case (writing, coding) and a model tag (works well with Claude, works well with GPT-4)
  • The raw prompt text was useless without context — when do you use this? What does it produce?
  • Some prompts had variables ([your topic here]). Some didn't. The schema needed to distinguish them.

The schema we shipped:

{
  id: string;
  title: string;           // short name shown in the card
  prompt: string;          // the actual prompt text (may contain [variables])
  description: string;     // when to use this
  explanation: string;     // why it works (the "Plain English" for prompts)
  useCase: string[];       // ["writing", "editing"]
  models: string[];        // ["gpt-4", "claude-3-5-sonnet"]
  hasVariables: boolean;   // drives UI hint
  example?: string;        // an example output, optional
}

Defining the schema before writing any prompts saved roughly three days of backfill work.

Step 2 — Decide on server vs. client rendering for filtering

The first instinct was client-side filtering — fetch all prompts on load, filter in JavaScript. Simple to build. But:

  • 200+ prompts is enough for noticeable filter lag on mid-range phones
  • Unfiltered list pages don't rank for category-specific queries (/prompts?category=coding is not a canonical URL)
  • Client state in the URL means bookmarking and sharing land on an unfiltered page

We went with server-side rendering for category pages and a client-side search for the text filter. The category routing:

app/ai/prompts/page.tsx          → all prompts
app/ai/prompts/[category]/...    → not a route — filtered via search param

Wait, actually: we made each use-case a real searchable path in the sitemap and used generateStaticParams to pre-render the filtered pages. Each category gets its own page, its own <h1>, and its own meta description.

Step 3 — Copy-to-clipboard UX

The most-clicked element on the page. Three versions:

Version 1: a plain "Copy" button. Works. Boring. No feedback.

Version 2: icon button that changes to a checkmark for 1.5 seconds after copy. Better. But the button was 32px × 32px — too small on mobile.

Version 3: the entire prompt card is the target, with a "Copy prompt" CTA in the bottom-right of the card. The card itself has a hover state that signals it's interactive. Touch target meets the 44px minimum.

The key implementation detail:

async function copyPrompt(text: string) {
  if (navigator.clipboard) {
    await navigator.clipboard.writeText(text);
  } else {
    // fallback for older browsers
    const el = document.createElement("textarea");
    el.value = text;
    document.body.appendChild(el);
    el.select();
    document.execCommand("copy");
    document.body.removeChild(el);
  }
  setCopied(true);
  setTimeout(() => setCopied(false), 1500);
}

The execCommand fallback is old, but a meaningful percentage of users on corporate networks have clipboard API blocked. Ship the fallback.

Step 4 — Variable highlighting

Prompts with variables ([your topic], [target audience]) needed visual treatment so users know where to fill in their content. We used a simple regex replacement in the render:

function highlightVariables(text: string) {
  return text.replace(
    /[([^]]+)]/g,
    '<mark class="variable">$1</mark>'
  );
}

Then dangerouslySetInnerHTML — acceptable here because the prompt text comes from our own content store, not user input. Never do this with user-generated content.

Step 5 — The editorial process

The technical work took about a week. Writing and structuring the actual prompts took three. Lessons:

  • Generic prompts perform badly. "Write a blog post about [topic]" is not useful. "Write a 600-word blog post introduction for [topic], using the 'problem-agitate-solve' structure, targeting developers who already know the basics" is useful.
  • The explanation field is the most valuable field. Users don't just want prompts — they want to understand why the prompt works so they can adapt it.
  • Prompts need maintenance. Model behaviour changes with versions. Prompts that worked brilliantly with Claude 2 sometimes need adjustment for Claude 3.5.

The mental model

The mental model for a curated resource library is: the editorial quality determines usefulness; the structure determines discoverability.

A well-structured empty library is useless. A rich, unstructured collection is a wall of text. The job is to nail both — usually in that order. Schema first, then content, then discoverability (SEO, search, filtering).

Key terms

Variable prompt — a prompt with placeholder tokens the user fills in. Increases reusability but requires clear visual indication.

Use case — the task category a prompt is designed for (writing, coding, analysis). Determines which filtered pages the prompt appears on.

Clipboard API — the modern browser API for programmatic clipboard access. Requires HTTPS and, in some contexts, user permission.

Pre-rendered filtered page — a category page built at compile time via generateStaticParams. Indexable, fast, and shareable.

Step-by-step

The launch unfolded in three product problems — schema, discoverability, and copy UX — not just "add a page."

Problem: Notion doc wasn't searchable or shareable

Internal prompts lived in a workspace only the team could see. Traffic to /ai/prompts was zero because the feature didn't exist publicly.

Approach: migrate to the shared Content schema pattern, add use-case tags, pre-render category pages with generateStaticParams.

Outcome: /ai/prompts became a top-ten entry page within six weeks; category URLs started ranking for "coding prompts" long-tail queries.

Problem: users copied prompts without understanding them

Version 1 was a list of raw strings. Copy rate was high; return rate was low — people didn't know how to adapt prompts.

Approach: add description (when to use) and explanation (why it works) as required fields; block publish without both.

Outcome: return visits to the library doubled; support questions about "how do I modify this?" dropped sharply.

Problem: copy button too small on mobile

The 32 px icon failed the 44 px touch-target guideline and sat far from the prompt text users wanted to tap.

Approach: full-card hit area, bottom-right CTA, Clipboard API plus execCommand fallback for locked-down corporate browsers.

Outcome: copy events per session rose ~40% on mobile without increasing bounce rate.

Working examples

A prompt card at its simplest:

<article aria-label={prompt.title}>
  <h3>{prompt.title}</h3>
  <p>{prompt.description}</p>
  <pre
    dangerouslySetInnerHTML={{ __html: highlightVariables(prompt.prompt) }}
  />
  <p className="explanation">{prompt.explanation}</p>
  <CopyButton text={prompt.prompt} />
</article>

The <pre> preserves newlines in multi-line prompts. The aria-label on the article means screen readers announce the card by title.

Patterns

Schema-first content pattern — define the full data shape before writing a single piece of content. The schema forces you to think about what makes each entry useful.

Static category pages pattern — pre-render one page per use-case category. Each page is independently indexable and shareable.

Clipboard fallback pattern — always implement the execCommand fallback alongside the Clipboard API. The API is blocked in more environments than you'd expect.

Common mistakes

Treating prompts as plain text. Without description, explanation, use-case tags, and variable highlighting, a prompt list is just a wall of text. Users copy the first three and never return.

Client-side-only filtering. Filtered views don't get indexed. If someone searches "coding prompts AI" and your /prompts?filter=coding page isn't a real URL with its own meta, you lose the organic traffic.

Prompt rot. Publishing prompts and never revisiting them. Model versions change. Check your top-used prompts after every major model release.

Little tip

Log which prompts get copied using a lightweight analytics event (navigator.sendBeacon to your own endpoint). You'll quickly see which ones users actually find useful vs. which ones you thought were good. The gap is often surprising.

Little tip

Add a lastVerified field to your prompt schema and surface it in the UI as "Tested with [model] [date]". It sets expectations and reminds you to run maintenance sweeps.

Troubleshooting

Copy button works in dev but fails on deployed site. The Clipboard API requires HTTPS. If your staging environment is HTTP, clipboard writes will silently fail. The execCommand fallback handles this case.

Category pages return 404 in production. Check generateStaticParams — it must return all valid category values. If you add a new use case to the schema but don't update the params generator, the page doesn't get pre-rendered.

Variable highlighting breaks for prompts with HTML characters. The regex inserts <mark> tags via dangerouslySetInnerHTML. If prompt text contains < or >, sanitise before rendering or use a text-node-based approach instead.

Checklist

  • [ ] Schema defined with all fields before writing prompts
  • [ ] Use cases mapped to pre-rendered category pages
  • [ ] Clipboard API with execCommand fallback implemented
  • [ ] Touch target for copy button ≥ 44px
  • [ ] Variable tokens visually highlighted
  • [ ] Each category page has a unique <h1> and meta description
  • [ ] At least one working example output per prompt (optional field)
  • [ ] lastVerified or model tag on each prompt
  • [ ] Analytics on copy events to identify most-used prompts

Practice task

Take five prompts you use regularly. Write the full schema record for each one — title, description, explanation, use case, models, variables. Then decide: are these actually different use cases, or are they variations of the same prompt that should be collapsed into one with a variable?

FAQ

Should prompts be in a database or flat files?
Either works at small scale. A database wins when you need filtering, search, and usage analytics without rebuilding static assets. Flat MDX files win when your team is comfortable in git and you have fewer than 50 prompts.

How do you handle prompt quality control?
We review every prompt before publishing, run it against at least two current model versions, and add the output as the example field. Prompts that produce inconsistent results don't ship.

What about user-submitted prompts?
Out of scope for the current version. User-generated prompts need moderation, attribution, and a much more complex editorial pipeline. We'll revisit when the curated library proves the model.

What to learn next

  • MDX for prompt pages — if you want richer formatting in the prompt body
  • Vector search in MongoDB Atlas — for semantic prompt search beyond keyword filtering
  • AI SDK streaming — if you want an inline "try this prompt" feature
  • [Building the Baseline content hub](/case-studies/building-baseline-content-hub)
  • [SEO IA for AI media](/case-studies/seo-ia-for-ai-media)
  • [AI prompts library](/ai/prompts)

Takeaways

The prompt library took three times longer than expected because the editorial work — deciding what makes a prompt actually useful, writing the explanations, maintaining currency with model changes — is genuinely hard. The code was the easy part.

If you remember only one thing: the explanation field is the most valuable thing in your prompt library. Users don't just want the text — they want to understand it well enough to adapt it. Write the explanation before you write the prompt.