Skip to content

feat(templates): add "Open prompt in" dropdown with Replit Agent support#106

Open
thisistonydang wants to merge 4 commits into
mainfrom
thisistonydang/open-prompt-in-button
Open

feat(templates): add "Open prompt in" dropdown with Replit Agent support#106
thisistonydang wants to merge 4 commits into
mainfrom
thisistonydang/open-prompt-in-button

Conversation

@thisistonydang
Copy link
Copy Markdown
Collaborator

@thisistonydang thisistonydang commented May 31, 2026

Summary

  • Templates that ship a replit-prompt.md now render an Open prompt in dropdown next to Copy prompt on the agent usage card. The Replit menu item opens replit.com/?stack=Build&prompt=… with the prompt lz-string-compressed into the URL, so Replit Agent picks it up on landing.
  • The templates index sidebar gets a new Build with > Replit filter that narrows the grid to entries with a Replit prompt. Derived from plugin data — no separate registry flag to maintain.
  • Per-template replit-prompt.md files hold only the unique task (~30-60 lines each). Universal boilerplate (Before Building routing, PAT Fallback, Permission Handling, Style guide, Out of Scope) lives in a single content/replit-shared/preamble.md. readReplitPrompt composes them with a --- separator — same shape as the existing composeAgentPrompt pattern.
  • Built on a small PromptTarget registry in src/lib/prompt-targets.ts — adding future targets is a one-line entry there. Surfaced through a tier-agnostic useReplitPrompt(slug) hook so detail pages don't need to know whether the template is an example, recipe, or cookbook.
  • Replit prompts deliberately live next to goal.md but stay out of ContentSections — they're an export target, not part of the rendered template content, so the content-sections pipeline isn't polluted.
Screenshot 2026-06-01 at 8 19 21 PM Screenshot 2026-06-01 at 8 20 21 PM

What's in scope

  • Plumbing: readReplitPrompt(rootDir, tier, slug) helper in src/lib/content-markdown.ts; replitPromptsBySlug exposed by both plugins/cookbooks.ts and plugins/content-entries.ts; aggregator hooks (useReplitPrompt + useReplitTemplateIds) in src/lib/use-raw-content-markdown.ts. Validator now accepts replit-prompt.md in resource + cookbook folders.
  • UI (detail page): New src/components/open-prompt-in-button.tsx (returns null when no targets, so non-Replit templates are unchanged); new src/components/icons/replit-icon.ts brand mark (Simple Icons, CC0); slug prop threaded through agent-usage-card.tsx.
  • UI (templates index): New "Build with > Replit" checkbox under the existing Services section in the sidebar (template-filters.tsx), plus a removable "Replit" chip in the active-filters bar (active-filters.tsx). Participates in the mobile filter badge count and the "Clear all" action.
  • Prompt composition: Per-template files contain only the unique task. Shared preamble (Before Building, PAT Fallback, Permission Handling, Style guide, Out of Scope) lives in content/replit-shared/preamble.md and is prepended at read time. Mirrors the existing composeAgentPrompt pattern used by Copy prompt.
  • Analytics: track("open_prompt_in", { target, slug, title, permalink }) fires on menu item click — symmetric with the existing copy_prompt event. Action-named UTM (utm_content=open-prompt-in) so analytics history stays continuous if the dropdown is relocated.
  • Bug fix: The Replit URL includes the documented-required stack=Build parameter (per Replit's Open in Replit docs).
  • Cleanup: Three pre-existing aspect-[16/9]aspect-video lint warnings in the detail pages I touched.

Initial 10 Replit prompts

Tier Slug
Example saas-tracker
Example vacation-rentals
Example inventory-intelligence
Example content-moderator
Cookbook genie-analytics-app
Cookbook operational-data-analytics
Recipe genie-conversational-analytics
Recipe genie-multi-space
Recipe medallion-architecture-from-cdc
Recipe volume-file-upload

Templates without a replit-prompt.md are unchanged — the agent usage card hides the dropdown entirely and the filter excludes them.

Tests

Together these protect every regression surface: the stack=Build fix, lz-string encoding, validator allow-list, plugin pipeline, dropdown render conditions, analytics payload contract, prompt composition contract, and filter behavior.

Test plan

  • Manually click Open prompt in → Replit on a Replit-enabled template (e.g. /templates/saas-tracker) and confirm Replit Agent picks up the prompt
  • Confirm a non-Replit template (e.g. /templates/set-up-your-local-dev-environment) still shows only Copy prompt — no dropdown
  • On /templates, check the Build with > Replit filter and confirm the grid narrows to the 10 Replit-enabled templates above
  • Spot-check one of each tier (one example, one recipe, one cookbook) loads cleanly in preview
  • Verify Vercel preview deploy succeeds (lockfile registry URL fix included — see "lockfile note" below)
  • After merge: confirm open_prompt_in event lands in Vercel analytics with target=replit and per-template slug / title / permalink breakdowns

Lockfile note

The added lz-string@^1.5.0 dep had npm install write npm-proxy.cloud.databricks.com into the resolved URL (4th time this has happened on the repo — see 4085dc2, 064497a, b8a7b17). Rewrote it to registry.npmjs.org so Vercel can resolve it. Integrity hash unchanged.

Worth considering a follow-up PR with a repo-level .npmrc pinning registry=https://registry.npmjs.org/ so future engineers don't hit this.

Future targets

Adding future targets later is a one-line push in getPromptTargets({...}). The analytics event already uses a target property keyed by id, so dashboards filtering on that will pick up new targets automatically. The templates-index filter is currently Replit-only — adding more targets there would be a small companion edit to expose them as additional "Build with" checkboxes.

Out of scope

  • Switching CopyPromptButton to a split-button variant — explored in an earlier branch, but Copy and Open-in-X are semantically different actions, so they read cleaner as two siblings.

Templates that ship a replit-prompt.md now render an "Open prompt in"
dropdown next to Copy prompt. The Replit menu item opens replit.com
with the prompt lz-string-compressed into the URL, so Replit Agent
picks it up on landing.

Plumbing:
- readReplitPrompt(rootDir, tier, slug) reads from any of the three
  template tiers (examples, recipes, cookbooks)
- replitPromptsBySlug exposed by both the cookbooks plugin and the
  content-entries plugin
- useReplitPrompt(slug) aggregates across all three plugin sources so
  detail pages stay tier-agnostic
- Replit prompts live next to goal.md but stay out of ContentSections
  -- they're an export target, not rendered content
- Validator accepts replit-prompt.md in resource and cookbook folders

UI:
- New OpenPromptInButton (returns null when no targets are available)
- New PromptTarget abstraction in src/lib/prompt-targets.ts, ready for
  more targets (Cursor, v0, Lovable, ...) via a one-line registry entry
- New ReplitIcon brand mark (Simple Icons CC0)
- Replit URL includes the documented-required stack=Build parameter
- track("open_prompt_in", { target, slug, title, permalink }) on click,
  symmetric with the existing copy_prompt event

Initial 10 Replit prompts:
- Examples: saas-tracker, vacation-rentals, inventory-intelligence,
  content-moderator
- Cookbooks: genie-analytics-app, operational-data-analytics
- Recipes: genie-conversational-analytics, genie-multi-space,
  medallion-architecture-from-cdc, volume-file-upload

Tests:
- prompt-targets.test.ts: target shape, stack=Build, UTM, lz-string
  roundtrip
- validate-content.test.ts: replit-prompt.md allowed in both folder
  types
- e2e/open-prompt-in.spec.ts: dropdown render/hide, URL roundtrip to
  source file, analytics payload contract

Also fixes a pre-existing aspect-[16/9] -> aspect-video lint warning in
three detail pages while touching them.
@thisistonydang thisistonydang marked this pull request as ready for review May 31, 2026 21:41
Comment thread content/cookbooks/genie-analytics-app/replit-prompt.md Outdated
Comment thread src/components/icons/replit-icon.ts
@andrelandgraf
Copy link
Copy Markdown
Collaborator

Screenshot 2026-06-01 at 2 00 19 PM

🤨 alignment?

Using Radix's --radix-dropdown-menu-trigger-width CSS variable makes
the dropdown's width track the "Open prompt in" trigger button exactly,
so the menu tucks under it with matching left and right edges.

Replaces the prior min-w-44 (176px) which overhung the trigger on the
right, then a brief intermediate state where dropping the override
fell back to the shadcn default min-w-[8rem] (128px) and left the
dropdown narrower than the trigger.
…ate files

Addresses review feedback on PR #106 about copy-pasted boilerplate
across the 10 Replit prompt files. Every universal block (Before
Building routing, PAT Fallback Path, Permission Handling, Style guide,
Out of Scope) now lives in a single content/replit-shared/preamble.md.
Per-template files hold only the unique task: title, hero, Data,
optional Additional Secrets, Features, Build Order, optional Notes.

Architecture matches the existing composeAgentPrompt pattern used by
the Copy prompt feature: shared boilerplate + per-template body, joined
by readReplitPrompt() with a fixed --- separator. No markers, no
per-section splicing. Per-template files shrink from ~100-130 lines to
~30-60 lines. Updating any shared section is now a single-file edit
(was 10-file edit).

Content quality improvements while restructuring:
- Normalize heading case to Title Case across all per-template files
- Drop DevHub-template cross-references that don't reach Replit Agent
- Tighten content-moderator Model Serving handling (was mentioned 5x)
- Restructure volume-file-upload Notes into structured sub-points
- Differentiate genie-analytics-app cookbook (full multi-tab app) from
  genie-conversational-analytics recipe (focused panel addition)
- Normalize hero formula and section ordering across all 10 templates
- Concrete env-var names in genie-multi-space Additional Secrets

Reader:
- readReplitPrompt composes preamble + --- + per-template task
- Throws a clear error when the shared preamble file is missing
- e2e roundtrip test now compares URL prompt against composed output

Tests:
- tests/replit-prompt-composition.test.ts (NEW): 8 cases covering
  composition contract, tier coverage, whitespace trimming, and the
  missing-preamble error path
Adds a sidebar filter under a new "Build with" section that narrows the
templates grid to entries with a Replit prompt
(content/<tier>/<slug>/replit-prompt.md). Derived from plugin data via a
new useReplitTemplateIds() hook — no separate registry flag; authors
only need to drop a replit-prompt.md next to their goal.md and it
shows up in the filter automatically.

UI:
- New "Build with > Replit" checkbox in the sidebar, positioned after
  Services
- Removable "Replit" chip in the active-filters bar (Databricks red,
  matches the existing services-chip styling)
- Participates in the mobile filter badge count and Clear all

Tests:
- Two new e2e cases in tests/e2e/resources-filters.spec.ts:
  - Checking "Replit" narrows the grid to templates with a replit
    prompt and shows a removable chip
  - The Replit filter participates in Clear all
@thisistonydang
Copy link
Copy Markdown
Collaborator Author

@andrelandgraf PR has been updated:

  • The shared boilerplate has been pulled out into content/replit-shared/preamble.md and per-template files now hold just the unique task and are composed together.
  • Fixed dropdown alignment issue

In addition, I also added a filter on the /templates so users can easily filter to templates that can be opened in Replit.

I ran a few prompts on Replit for manual test and the build was successful including Genie analytics. :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants