Promptshelf Vibe-Coded Gallery · 20 before/after pairs
Vibe-coded gallery · 20 pairs

Before and after — 20 vague prompts, rewritten as engineered instructions.

Each card shows a vibe-coded prompt on the left and the engineered version on the right. The rationale line explains what the vague version leaves for the model to guess. Filter by category; click any card for the full pair with a shareable permalink. Twenty pairs, six categories, one point: vague prompts make the model flip a coin.

Filter:

Showing 20 of 20 pairs

Vague-vs-engineered prompt pairs

Frontend

Button styling

VagueMake the button look better.
EngineeredRefactor the primary button to match our design tokens: 8px border-radius, hover state at --accent-hover, disabled state at 40% opacity, focus ring using the existing --ring CSS variable. Apply to all button[data-variant='primary']. Preserve click handlers.
Frontend

Responsive fix

VagueMake it work on mobile.
EngineeredThe pricing grid breaks below 640px because the 4-column layout overflows. Change to grid-template-columns: 1fr below 640px and stack the comparison chips vertically. Preserve the sticky CTA on scroll. Test on iPhone SE viewport (375×667).
Frontend

Accessibility

VagueAdd accessibility.
EngineeredAudit the modal against WCAG 2.1 AA: add role='dialog' and aria-modal='true', trap focus inside when open, restore focus to the trigger on close, support Escape to close, and ensure the close button has aria-label='Close dialog'. Do not change visual design.
Frontend

Smooth animation

VagueAdd a smooth animation.
EngineeredFade the dropdown in over 150ms using opacity + translateY(-4px → 0). Honor prefers-reduced-motion. Ease: cubic-bezier(0.2, 0, 0, 1). Remove the existing transition: all which re-triggers layout on every property.
Backend

Add login

VagueAdd login.
EngineeredEmail/password login against users (Postgres, users.email unique, users.password_hash bcrypt cost 12). Issue a signed JWT (HS256, 24h) as an httpOnly SameSite=Strict cookie. Rate-limit failures to 5/min per IP. Return 401 without leaking which field was wrong.
Backend

Pagination

VagueMake it faster for big results.
Engineered/api/items loads all 50k rows into memory. Switch to cursor-based pagination: ?cursor=<id>&limit=50 (max 200), return {items, nextCursor}. Use the existing id DESC index. Preserve the current items shape; only add nextCursor.
Backend

Rate limit

VagueAdd rate limiting.
EngineeredToken-bucket on /api/notify using Redis: bucket size 60, refill 1/sec per user ID. On miss: 429 with Retry-After header. Use the existing Redis pool. Log throttled requests at INFO with user_id + bucket state.
Backend

Caching

VagueCache the response.
EngineeredCache /api/pricing in Redis with 5-min TTL. Key: pricing:v1:<tier_hash>. Invalidate on tier_update pub/sub. Stampede-safe (30s lock). On Redis error, fall back to DB — do NOT fail open.
Infra

Deploy broken

VagueThe deploy is broken, fix it.
EngineeredVercel deploy fails with Module not found: 'sharp', starting after Node 18→20 bump. Hypothesis: sharp binaries pinned to Node 18. Candidate fix: npm rebuild sharp --platform=linux --arch=x64 in build, or pin sharp to 0.33.x. Verify on preview URL before promoting.
Infra

Env var

VagueSet up the API key.
EngineeredAdd STRIPE_SECRET_KEY to Vercel prod env (use a test key for preview). Do NOT commit to .env. Update README to list required vars without values. Rotate if the key has ever been in a commit (git log -S 'sk_live_').
Infra

Scaling

VagueHandle more traffic.
EngineeredPeaks at 40 req/s at p99 800ms. Target: 200 req/s at p99 < 300ms. Measure first — add p99 histogram to the 3 slowest routes. If DB-bound: read replica + ORM routing. If CPU-bound: horizontal scale. Don't optimize blind.
Refactor

Rename

VagueRename X to Y.
EngineeredRename fetchDataloadUserDashboard across: 1) declaration in src/api/user.ts, 2) all call sites via rg 'fetchData' src/, 3) test mocks, 4) JSDoc. Do NOT touch data-* HTML attrs or vendor code. Run npm test after.
Refactor

Extract function

VagueClean up this file.
EngineeredThe 800-line checkout.ts mixes validation, tax, shipping, total. Extract each to src/checkout/*.ts with named exports. Preserve the public API processCheckout(cart) → receipt. Delete commented-out code. No business-logic changes.
Refactor

Simplify

VagueThis feels over-engineered.
EngineeredConfigProvider has 3 layers (factory → context → hook) for 4 static keys. Replace with export const config = {...}. Update the 7 call sites to import directly. Remove factory + context files. Keep the TypeScript type export.
Bug-fix

Memory leak

VagueThe app is slow.
EngineeredRSS grows 15MB/hour, OOMs at ~12h. Hypothesis: unclosed EventEmitter listener. Take heap snapshots at 0h/1h/2h; grep for .on( without matching .off(. Likely culprit: src/services/websocket.ts adds a listener per request. Use .once() or .off() in the finalizer.
Bug-fix

Race condition

VagueSometimes it returns the wrong data.
EngineereduseUser(id) returns the previous user's data when id changes quickly: the fetch resolves after id changed. Fix: AbortController tied to effect cleanup. Secondary guard: ignored = true flag. Write a test that fires 2 renders within 10ms and asserts only the latest result is committed.
Bug-fix

Flaky test

VagueThis test is flaky, retry it.
Engineereduser.test.ts fails ~1 in 20 with 'active' ≠ 'pending'. Do NOT add a retry. Fix: await the state update inside act(...); replace setTimeout with queueMicrotask; use waitFor. If timer-specific, add vi.useFakeTimers().
Tests

Unit tests

VagueAdd tests for this.
EngineeredUnit-test parseAddress(input) in src/utils/address.ts. Cases: valid US, valid UK postcode, empty, whitespace-only, 1000-char (no hang), unicode (Ñ, 北京), mixed-case postcode normalization. Use vitest table-driven. Target 90%+ branch coverage.
Tests

Integration tests

VagueTest it end-to-end.
EngineeredPlaywright signup flow: navigate to /signup, fill email+password, submit, assert redirect to /onboarding, verify welcome email (test SMTP), assert user row with email_verified=false. Run against docker-compose Postgres + MailCatcher. Use page.waitForURL, not sleep.
Tests

Mocking

VagueMock the API.
EngineeredReplace the real Stripe client with MSW handlers: 1) POST /v1/charges → 200 with fixed charge ID, 2) same endpoint with amount < 50 → 400 amount_too_small. Use msw/node in setupFiles. Don't jest.mock('stripe') — SDK shape changes version-to-version.

FAQ

What is a "vibe-coded" prompt?
A prompt that describes an outcome in feeling-words instead of engineering decisions. "Make it look better." "Clean this up." "Handle more traffic." The model has to guess every missing decision, and it will guess wrong roughly as often as a coin flip. The engineered version names the specific tokens, thresholds, files, edge cases, and preservation contracts so the model has a single correct answer to produce.
Is the vague column always wrong?
Not wrong, under-specified. In a short session with a model that knows your codebase, vague prompts can be fine because context fills the gaps. Across sessions, across collaborators, or with a fresh context, the vague version leaves too many decisions to guessing. The engineered version is a contract the model can reproduce under any conditions.
Why these six categories?
Frontend, backend, infrastructure, refactor, bug-fix, and tests cover the six most common surfaces where vague prompts fail noisily in AI-assisted coding. They are not exhaustive — security, data modeling, and docs are also common surfaces, but the six here compound with our other tools (Promptle, Playground, Hall of Fame).
How is a pair's "engineered" version derived?
Author-curated, not primary-source-verified. Each engineered version reflects the engineering trade-offs a senior developer would spell out: named files, exact thresholds, preservation contracts, verification gates, and explicit anti-patterns to avoid. You will disagree with specific calls — that is the point. The rationale line gives you a target to argue with.
How do I share a specific card?
Click any card, then click the Copy link button inside it. The share URL is a hash-fragment permalink of the shape promptshelf.vercel.app/vibe-coded-gallery#/card/<slug>, which your browser resolves client-side without reloading. Paste the URL anywhere — email, chat, or a bookmark — and clicking it opens that card directly.
Does this page send any data?
Almost nothing. Filter state, selected card, and copy-to-clipboard are all client-side — no analytics, no telemetry, no script tags of our own beyond Google Fonts CSS, which loads from fonts.googleapis.com and fonts.gstatic.com on each page view. Those two requests expose your IP, User-Agent, and referrer to Google; if that matters, block those domains in your browser and the page degrades gracefully to system fonts. Beyond that, nothing leaves your browser unless you copy a permalink and paste it yourself.
How do I suggest a new pair?
Email hansng1988+gallery@gmail.com with the vague prompt, the engineered version, the category, and a one-line rationale. Gmail plus-aliases route natively — no new account needed on our end. High-quality pairs get added on the next ship cycle.
Why 20 pairs?
Twenty gives enough coverage to see the pattern across categories without card fatigue. Thirty would dilute; ten would under-sample. Each pair is chosen to be independently representative, not redundant with the others in its category.

This page useful? Tip the maker in BTC — no account, no signup, just paste.

BTC bc1qs04leape97ner4wqa98n94l9n0gv9aa84eg4ux