saju_global

Paddle payment integration + Claude-powered auto build log pipeline

KO →
paddle payment ci-cd claude-code automation

What I built

Added Paddle as a first-class payment provider alongside the existing Stripe/Toss setup, with a single runtime env var controlling which provider activates. Ran Playwright smoke tests across all 8 locales. Then wired up a pipeline where every git push triggers Claude CLI to generate a build log — which is exactly what you’re reading right now.

How it came together

The Paddle integration had one hard constraint: don’t touch the existing Stripe/Toss code. The solution was an effectiveProvider runtime flag in paywall/page.tsx. Set NEXT_PUBLIC_PAYMENT_PROVIDER=paddle and all non-KR traffic routes to Paddle. Unset it and you get the country-default behavior. Two new API routes — /api/checkout/paddle/create and /api/checkout/paddle/webhook — handle the Paddle-side flow. Passed typecheck and next build clean.

The more interesting story is the automation pipeline. The prompt that drove it:

“Set up a husky pre-push hook that calls claude -p to generate build logs, then use GitHub Actions to auto-sync them to the portfolio repo and open a PR with blog drafts when there are 5+ commits.”

The key design decision was gtimeout 60 wrapping the Claude CLI call. If it hangs, the push shouldn’t block. Failure exits gracefully with || echo "⚠️ skip". Two bugs burned time: macOS doesn’t have timeout (had to install coreutils for gtimeout), and the Claude CLI path failed with a relative reference (hardcoded to /Users/jidong/.local/bin/claude).

On the Vercel side: five consecutive fix commits just to get the deployment working. The monorepo root needed to point at apps/web, the framework preset had to be nextjs explicitly in vercel.json, and env vars had to be set before the build could succeed. Classic deploy thrash, but at least each commit is cleanly labeled fix(deploy):.

The launch readiness audit was prompted with: “No guessing — every claim needs a file path or an actual HTTP response.” Claude ran pnpm dev:web, hit every API endpoint, tested rate limits to exhaustion (confirmed 429 on the 5th request), and checked all 8 locales on desktop and iPhone 12 viewport. Zero P0 issues found.

Commit log

  • 82e29d8 chore: add automation setup (Paddle API routes, Husky hook, GitHub Actions, E2E suite, audit docs)
  • a6379ed fix(deploy): set Next.js framework in vercel.json
  • 7feb33f fix(deps): add three and @types/three to web package
  • 2e10679 fix: use gtimeout for macOS
  • bb714ce fix: use full path for claude CLI
  • e659c9b fix(deploy): ignore husky failure in CI environment
  • 3789e6d fix(deploy): remove .env.local from git tracking
  • 5c7cece chore: trigger rebuild with env vars configured

Results

BeforeAfter
Payment providersStripe + TossStripe + Toss + Paddle (env-var switchable)
Rate limitingNone5 req/day on LLM endpoints
E2E coverage08 locales × core user flow
Build log creationManualAuto-generated by Claude CLI on every push
Vercel deployBrokenStable after framework preset fix