duply

How it works.

Four conventions make the kit run end-to-end with zero credentials. Learn these and you can read any screen.

Mock data

Each screen imports its data from src/data/mock/<name>.ts and renders fully from it, no dead, blank, or "coming soon" states. The reference screen is src/routes/app/index.tsx, reading src/data/mock/overview.ts.

// src/routes/app/billing.tsx
import { plans, invoices } from '#/data/mock/billing'
// the screen renders these whether or not Stripe is wired

The 🔌 INTEGRATION seam

Directly above the component that would call a real service sits exactly one greppable line, naming the service and the skill that wires it.

// 🔌 INTEGRATION: Stripe, see agent-skills/wire-billing.md
function Billing() { /* ... */ }

# find every seam still mocked:
grep -rn "🔌 INTEGRATION" src/

Demo mode (isWired)

A seam is "wired" only when its env var(s) are set. The gate lives in src/lib/demo-mode.ts:

import { isWired } from '#/lib/demo-mode'

if (isWired('VITE_SUPABASE_URL', 'VITE_SUPABASE_ANON_KEY')) {
  // real call
} else {
  // mock data + <StarterNote>
}

The kit ships working in demo mode and flips to live with no code change, just an env var. You never edit a component to "turn on" a feature.

The agent skills

The seam comment points at a file in agent-skills/, the source of truth for one integration: provider choice, env var names, seam location, steps, and security defaults. Your agent loads that file before writing any code, so it never improvises a provider.

See the full trigger table on the Agent skills page, and the seam to env-var map on Wiring.

Why this shape

You get a finished-feeling product to demo on day one, one command (grep -rn "🔌 INTEGRATION" src/) that shows exactly what's left, and a clean path to production where each piece goes live independently.