Skip to content
Back to skills

Integration Builder

ASecurity

Composes a full vertical payment integration from canonical templates. Called by integration-specialist subagent after the user selects a provider. Loads templates by (provider, stack, ORM, deploy target, billing_mode, frontend_style, use_cases) and emits a coherent file plan that gets written to the user's project. Always cites webhook-verifier and SECURITY_RULES. Phase 1 supports stripe, mercadopago, wompi, lemonsqueezy on Next.js App Router and Express; Phase 2 adds more.

  • 37 stars
  • 0 votes
  • 0 copies
  • 4 views
  • Added May 28, 2026
developmentgosqlnextjsnodenodejsexpressfastapiapifrontendbackend

Works with

  • api

Security analysis

A96/100
  • mediumInstalls packages at runtime which could introduce malicious dependencies

Pro scans all 20 files and shows the line behind each finding

Scanned May 28, 2026

npx -y skills add Hainrixz/agente-pagokit --skill integration-builder --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Integration Builder?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Integration Builder
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/hainrixz-integration-builder/badge)](https://www.skillsdirectory.com/skills/hainrixz-integration-builder)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: integration-builder
description: Composes a full vertical payment integration from canonical templates. Called by integration-specialist subagent after the user selects a provider. Loads templates by (provider, stack, ORM, deploy target, billing_mode, frontend_style, use_cases) and emits a coherent file plan that gets written to the user's project. Always cites webhook-verifier and SECURITY_RULES. Phase 1 supports stripe, mercadopago, wompi, lemonsqueezy on Next.js App Router and Express; Phase 2 adds more.
when_to_use: |
  - integration-specialist subagent is implementing a chosen provider for the user
  - The user asks "regenerate the stripe integration with subscription mode" or equivalent rebuild
allowed-tools: Read, Glob
---

# integration-builder

You are the catalog of how to compose a PagoKit integration. You do NOT write to the user's project — that is integration-specialist's job. You read templates and produce a structured plan that the subagent then executes.

## Inputs (passed by integration-specialist)

```json
{
  "provider": "stripe|mercadopago|wompi|lemonsqueezy",
  "stack": "nextjs-app-router|express|fastapi|...",
  "orm": "prisma|drizzle|sqlalchemy|...|none",
  "deploy_target": "vercel|railway|...|none",
  "billing_mode": "one_time|subscription",
  "frontend_style": "hosted|embedded|widget",
  "required_methods": ["card", "oxxo", "..."],
  "use_cases_detected": ["save_card_subscription", "..."],
  "language": "es|en|...",
  "example_transaction_amount": 20,
  "example_currency": "USD"
}
```

## Templates you load

Per provider (e.g., Stripe):

- `templates/stripe/reference.md` — canonical patterns + anti-patterns
- `templates/stripe/webhook.md` — verification specifics
- `templates/stripe/one-time.md` OR `templates/stripe/subscription.md` (by billing_mode)
- `templates/stripe/save-card.md` if `save_card_subscription` detected
- `templates/stripe/customer-portal.md` if `billing_mode == subscription`
- `templates/stripe/refund-endpoint.md` (always — every integration ships with refund capability)
- `templates/stripe/errors.md`
- `templates/stripe/frontend-hosted.md` or `templates/stripe/frontend-embedded.md` (by frontend_style)
- `templates/stripe/3ds-handling.md` if buyer regions include EU/UK
- `templates/stripe/tax.md` if user opted for tax automation

Per stack:

- `templates/_stack-adapters/nextjs-app-router.md` (raw body, NextResponse, runtime: 'nodejs')
- `templates/_stack-adapters/express.md` (express.raw middleware ordering)

Per ORM:

- `templates/_db-adapters/prisma.md` (schema.prisma + migration commands)
- `templates/_db-adapters/drizzle.md`
- `templates/_db-adapters/sqlalchemy.md` (+ alembic)

Per deploy target:

- `templates/_deploy-targets/vercel.md` (vercel env add commands)
- `templates/_deploy-targets/railway.md`

## Pre-compiled combos (preferred)

For the 8 highest-traffic combos, `templates/compiled/<provider>-<stack>-<billing>.md` exists with a single canonical file already composed. ALWAYS prefer these over runtime composition when the combo matches exactly. Phase 1 ships:

- `stripe-nextjs-app-router-one-time.md`
- `stripe-nextjs-app-router-subscription.md`
- `stripe-express-subscription.md`
- `mercadopago-nextjs-app-router-one-time.md`
- `mercadopago-express-one-time.md`
- `wompi-nextjs-app-router-one-time.md`
- `wompi-express-one-time.md`
- `lemonsqueezy-nextjs-app-router-subscription.md`

For non-matching combos, fall back to runtime composition using the per-provider and per-stack templates.

## The integration plan you emit

After loading templates, emit a structured plan in your response (in a fenced ```json block) that integration-specialist then executes:

```json
{
  "files_to_create": [
    {
      "path": "app/api/checkout/route.ts",
      "purpose": "POST /api/checkout — creates a payment_intent with idempotency",
      "template_source": "templates/stripe/one-time.md + templates/_stack-adapters/nextjs-app-router.md",
      "must_include_rule_tags": ["// Rule 4: idempotency", "// Rule 5: raw body N/A here, checkout endpoint"]
    },
    {
      "path": "app/api/webhook/stripe/route.ts",
      "purpose": "POST /api/webhook/stripe — verify signature, dispatch events",
      "template_source": "templates/stripe/webhook.md + templates/_stack-adapters/nextjs-app-router.md",
      "must_include_rule_tags": ["// Rule 3: signature", "// Rule 5: raw body", "// Rule 9: timestamp window", "// Rule 10: body size cap"],
      "events_routed": ["payment_intent.succeeded", "payment_intent.payment_failed", "charge.refunded", "charge.dispute.created", "invoice.payment_failed", "customer.subscription.deleted", "customer.subscription.updated"]
    },
    {
      "path": "app/api/portal/route.ts",
      "purpose": "POST /api/portal — billingPortal.sessions.create for subscription self-service",
      "template_source": "templates/stripe/customer-portal.md",
      "skip_if": "billing_mode != subscription"
    },
    {
      "path": "app/api/refund/route.ts",
      "purpose": "POST /api/refund — auth-checked refund emission",
      "template_source": "templates/stripe/refund-endpoint.md"
    },
    {
      "path": "components/CheckoutButton.tsx",
      "purpose": "Frontend trigger — Stripe Checkout redirect (hosted)",
      "template_source": "templates/stripe/frontend-hosted.md"
    },
    {
      "path": "lib/payments/errors.ts",
      "purpose": "Map provider error codes to {code, user_message:{es,en}}",
      "template_source": "templates/stripe/errors.md"
    },
    {
      "path": "prisma/schema.prisma",
      "operation": "extend",
      "purpose": "Add tables payments, subscriptions, customers, idempotency_keys, webhook_events_processed",
      "template_source": "templates/_db-adapters/prisma.md"
    },
    {
      "path": ".env.example",
      "operation": "create_or_extend",
      "purpose": "Document required env vars with test-key prefixes (Rule 8)",
      "vars": ["STRIPE_SECRET_KEY=sk_test_…", "STRIPE_PUBLISHABLE_KEY=pk_test_…", "STRIPE_WEBHOOK_SECRET=whsec_…"]
    },
    {
      "path": "PAGOKIT_INTEGRATION.md",
      "purpose": "Audit trail of what was generated",
      "template_source": "internal — generated by integration-specialist"
    },
    {
      "path": "PAGOKIT_PRODUCTION_CHECKLIST.md",
      "purpose": "Step-by-step guide to flip from sandbox to live",
      "template_source": "internal — generated by integration-specialist"
    }
  ],
  "commands_to_run": [
    "npm install stripe@^17",
    "npx prisma migrate dev --name pagokit_init"
  ],
  "post_install_hint": "Run /pagokit:test to send synthetic webhook events to your local server.",
  "frontend_style_chosen": "hosted",
  "deploy_target_instructions": "After deploying, run `vercel env add STRIPE_SECRET_KEY` and paste your test key."
}
```

## Composition rules

1. **Webhook routes are always namespaced** `/api/webhook/<provider>/...`. Even if no collision is detected, the convention is mandatory from Phase 1 to allow multi-provider co-existence.
2. **SDK version is pinned** in `package.json` (e.g., `stripe@^17.x`). Match `providers.json.api_version`.
3. **Use `crypto.randomUUID()`** literally on the idempotency key line (Rule 4 — validators check for this canonical string).
4. **Frontend goes in `components/` (or `src/components/`) for Next.js**, `public/` for Express HTML, or framework-equivalent.
5. **DB tables are non-destructive** — if the schema already declares `payments`, append a `pagokit_payments` table instead of clobbering. integration-specialist runs the collision check.
6. **PAGOKIT_INTEGRATION.md is mandatory.** Without it, `/pagokit:doctor` can't audit later.

## Frontend choice (hosted vs embedded vs widget)

If `provider.frontend_options` has only one option (e.g., Wompi only has `widget`), choose it.

If multiple, decide as follows:

- `billing_mode == one_time` AND `stack == nextjs-app-router` AND no specific branding ask → **hosted** (lowest friction, redirects to provider's checkout page, fewest things to break).
- `billing_mode == subscription` AND product is SaaS → **embedded** (better UX for repeat customers; Stripe Elements / MP Bricks).
- Wompi → always **widget** (only option).
- Lemon Squeezy → **hosted** by default; **embedded** if the user specifically asked.

When in doubt, ask the user once with a single sentence: "¿Prefieres página de checkout del proveedor (más rápido) o componentes integrados en tu app (más control)?".

## Anti-patterns

- Do NOT execute the file writes yourself — emit the plan, return to integration-specialist.
- Do NOT recommend Stripe Charges API; always Payment Intents.
- Do NOT skip the `customer-portal.md` template for subscriptions — without it the user has no cancellation flow.
- Do NOT generate generic "console.log('Webhook received')" code — log only `event.id`, `event.type`, `event.created` (Rule 6).
- Do NOT generate frontend code that posts the user's PAN to your backend — use the provider's element/widget for PCI scope reasons (Rule 12).

Files in this skill

  • SKILL.md8.8 KB
  • templates/_db-adapters/drizzle.md7.5 KB
  • templates/_db-adapters/prisma.md6.5 KB
  • templates/_db-adapters/sqlalchemy.md8.6 KB
  • templates/_deploy-targets/railway.md2.8 KB
  • templates/_deploy-targets/vercel.md4.2 KB
  • templates/_stack-adapters/express.md3.5 KB
  • templates/_stack-adapters/nextjs-app-router.md3.8 KB
  • templates/compiled/lemonsqueezy-nextjs-app-router-subscription.md9.9 KB
  • templates/compiled/mercadopago-express-one-time.md5.6 KB
  • templates/compiled/mercadopago-nextjs-app-router-one-time.md7.7 KB
  • templates/compiled/stripe-express-subscription.md6.6 KB
  • templates/compiled/stripe-nextjs-app-router-one-time.md8.7 KB
  • templates/compiled/stripe-nextjs-app-router-subscription.md10.5 KB
  • templates/compiled/wompi-express-one-time.md5.3 KB
  • templates/compiled/wompi-nextjs-app-router-one-time.md8.7 KB
  • templates/lemonsqueezy/errors.md3.2 KB
  • templates/lemonsqueezy/frontend-hosted.md4.6 KB
  • templates/lemonsqueezy/one-time.md5.9 KB
  • templates/lemonsqueezy/reference.md4.9 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.