Skip to content

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

Open
thisistonydang wants to merge 2 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 2 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.
  • 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-05-31 at 2 33 21 PM

What's in scope

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.

Tests

  • tests/prompt-targets.test.ts — empty / single target shape, stack=Build presence, UTM attribution, lz-string lossless roundtrip
  • tests/validate-content.test.tsreplit-prompt.md accepted in both resource and cookbook folders
  • tests/e2e/open-prompt-in.spec.ts — dropdown renders on Replit-enabled template + URL decodes back to source file byte-identically; dropdown hides on non-Replit template; open_prompt_in analytics event fires with the exact payload

Together these protect every regression surface I could think of: the stack=Build fix, lz-string encoding, validator allow-list, plugin pipeline, dropdown render conditions, and analytics payload contract.

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
  • 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.

Out of scope

  • The Replit Apps filter on the templates index (PR 87 added it). Easy follow-up — adds a useReplitTemplateIds hook that walks the same three plugin-data sources we already expose, plus a checkbox in template-filters.tsx.
  • 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
@@ -0,0 +1,100 @@
# Build a Genie Analytics App with Databricks on Replit
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this be:

content/replit-preamble.md + optional content/<content-piece>/replit.md + content/<content-piece>/something-else-generic-that-may-be-useful-to-add.md

Seems like a bunch of copy-pasted content right now. Maybe we can split it up and concatenate?

const REPLIT_PATH =
"M2 1.5A1.5 1.5 0 0 1 3.5 0h7A1.5 1.5 0 0 1 12 1.5V8H3.5A1.5 1.5 0 0 1 2 6.5ZM12 8h8.5A1.5 1.5 0 0 1 22 9.5v5a1.5 1.5 0 0 1-1.5 1.5H12ZM2 17.5A1.5 1.5 0 0 1 3.5 16H12v6.5a1.5 1.5 0 0 1-1.5 1.5h-7A1.5 1.5 0 0 1 2 22.5Z";

export function ReplitIcon(props: SVGProps<SVGSVGElement>) {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lol AI is so silly sometimes. Not worth changing but just funny

@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.
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