Expert guide for automated and manual Web Accessibility (a11y) testing — axe-core, Pa11y, Playwright a11y, screen reader testing, and WCAG 2.2 Level AA/AAA compliance / Panduan ahli pengujian aksesibilitas web.
日本語の概要は準備中です。原文の説明を表示しています。
Implement and audit SaaS billing systems, subscription state machines, secure webhooks, and local database synchronization / Implementasi dan audit sistem billing SaaS, state machine langganan, webhook aman, dan sinkronisasi database lokal.
インストールする前に、エージェントに与えられる指示の中身を確認できます。
<a name="english"></a>
Connects and orchestrates with relevant domain skills like brainstorming, zero-to-prod-orchestrator, and session-memory-manager to ensure cohesive execution.
Expert guide for implementing and auditing SaaS billing systems. Covers subscription state machines, secure webhook handling, atomic database synchronization, and the 2026 billing landscape including Stripe, Polar.sh (open-source, developer-first), LemonSqueezy, Paddle, DOKU (Checkout & SNAP BI), and Midtrans (for Southeast Asia).
| Provider | Best For | Open Source | Merchant of Record |
|---|---|---|---|
| Stripe | Enterprise, global, complex billing | ❌ | ❌ |
| Polar.sh | Developer-first, open-source products | ✅ | ✅ (optional) |
| LemonSqueezy | Indie hackers, simple pricing, global | ❌ | ✅ |
| Paddle | B2B SaaS, EU VAT compliance | ❌ | ✅ |
| DOKU (Checkout & SNAP BI) | Indonesia & SE Asia enterprise, QRIS, VA, Multi-channel | ❌ | ❌ |
| Midtrans | Southeast Asia / Indonesia | ❌ | ❌ |
| PayPal | Global, consumer trust | ❌ | ❌ |
Merchant of Record (MoR): The provider handles tax compliance (VAT, GST), chargebacks, and legal liability — ideal for small teams without a finance department.
Polar.sh is the modern, open-source alternative to Gumroad/LemonSqueezy, purpose-built for developers and open-source projects:
import { Polar } from "@polar-sh/sdk";
const polar = new Polar({ accessToken: process.env.POLAR_ACCESS_TOKEN });
// Create a checkout session
const checkout = await polar.checkouts.custom.create({
productId: "prod_xxxx",
successUrl: "https://myapp.com/success?checkout={CHECKOUT_ID}",
customerEmail: user.email,
metadata: { userId: user.id },
});
// Redirect to checkout
return redirect(checkout.url);
// Webhook handler (Next.js App Router)
import { validateEvent, WebhookVerificationError } from "@polar-sh/sdk/webhooks";
export async function POST(req: Request) {
const body = await req.text();
const signature = req.headers.get("webhook-signature") ?? "";
try {
const event = validateEvent(body, req.headers, process.env.POLAR_WEBHOOK_SECRET!);
switch (event.type) {
case "subscription.created":
case "subscription.updated":
await syncSubscription(event.data);
break;
case "subscription.canceled":
await cancelSubscription(event.data.id);
break;
}
return new Response(null, { status: 200 });
} catch (e) {
if (e instanceof WebhookVerificationError) {
return new Response("Invalid signature", { status: 403 });
}
throw e;
}
}
FREE ──subscribe──> TRIALING ──trial_ends──> ACTIVE
│
┌───────────────┤
│ │
payment fails cancel
│ │
PAST_DUE CANCELED
│
3 failed retries
│
CANCELED
// app/api/webhooks/stripe/route.ts
import Stripe from 'stripe';
import { db } from '@/lib/db';
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);
export async function POST(req: Request) {
const body = await req.text(); // Raw body is mandatory
const sig = req.headers.get('stripe-signature')!;
let event: Stripe.Event;
try {
event = stripe.webhooks.constructEvent(body, sig, process.env.STRIPE_WEBHOOK_SECRET!);
} catch {
return new Response('Invalid signature', { status: 400 });
}
// Idempotency: Atomic insert on unique constraint to guarantee zero race conditions
try {
await db.webhookEvent.create({
data: {
stripeEventId: event.id,
eventType: event.type,
processedAt: new Date(),
},
});
} catch (err: any) {
// Unique violation (e.g. Prisma code P2002) means this event is ALREADY processed or currently processing
return new Response(JSON.stringify({ message: 'Event already received' }), { status: 200 });
}
// Process event safely knowing this invocation is guaranteed unique
switch (event.type) {
case 'customer.subscription.created':
case 'customer.subscription.updated': {
const sub = event.data.object as Stripe.Subscription;
await db.subscription.upsert({
where: { stripeSubId: sub.id },
create: { stripeSubId: sub.id, status: sub.status, userId: sub.metadata.userId },
update: { status: sub.status, currentPeriodEnd: new Date(sub.current_period_end * 1000) },
});
break;
}
case 'invoice.payment_failed': {
const invoice = event.data.object as Stripe.Invoice;
await sendDunningEmail(invoice.customer_email!);
break;
}
}
return new Response(null, { status: 200 });
}
// Report usage at end of billing period
await stripe.subscriptionItems.createUsageRecord(subscriptionItemId, {
quantity: apiCallsThisMonth,
timestamp: Math.floor(Date.now() / 1000),
action: 'set', // 'set' or 'increment'
});
PayPal remains a trusted global standard for one-off payments and subscriptions.
// app/api/paypal/create-order/route.ts
import { paypalClient } from '@/lib/paypal';
import paypal from '@paypal/checkout-server-sdk';
export async function POST() {
const request = new paypal.orders.OrdersCreateRequest();
request.prefer("return=representation");
request.requestBody({
intent: 'CAPTURE',
purchase_units: [{ amount: { currency_code: 'USD', value: '29.99' } }]
});
const response = await paypalClient().execute(request);
return Response.json({ id: response.result.id });
}
// app/api/paypal/capture-order/route.ts
import { db } from '@/lib/db';
import { paypalClient } from '@/lib/paypal';
import paypal from '@paypal/checkout-server-sdk';
export async function POST(req: Request) {
const { orderID, userId } = await req.json();
const request = new paypal.orders.OrdersCaptureRequest(orderID);
request.requestBody({});
const response = await paypalClient().execute(request);
if (response.result.status === 'COMPLETED') {
// Grant access or update subscription in DB
await db.subscription.create({
data: { userId, provider: 'paypal', status: 'active' }
});
return Response.json({ success: true });
}
return Response.json({ success: false }, { status: 400 });
}
For Indonesian developers without an official Payment Gateway account, you can create a "Dynamic" QRIS experience using a single Static QRIS combined with unique payment amounts and a bank mutation checking service (e.g., Moota, Cekmutasi) via webhook.
// Add a unique 3-digit code to the base price
export async function createQrisTransaction(userId: string, basePrice: number) {
// Generate a random code between 1 and 999
const uniqueCode = Math.floor(Math.random() * 999) + 1;
const totalAmount = basePrice + uniqueCode;
const transaction = await db.transaction.create({
data: {
userId, basePrice, uniqueCode, totalAmount,
status: 'pending', provider: 'qris_static',
expiresAt: new Date(Date.now() + 15 * 60 * 1000) // 15 mins expiry
}
});
return {
transactionId: transaction.id,
totalAmount,
qrisUrl: "https://myapp.com/static-qris.png" // User must manually input totalAmount
};
}
// app/api/webhooks/mutation/route.ts
import { db } from '@/lib/db';
import { pusherServer } from '@/lib/pusher';
export async function POST(req: Request) {
const signature = req.headers.get("signature");
// TODO: Verify signature from mutation service (e.g., Moota)
const mutations = await req.json();
for (const mutation of mutations) {
if (mutation.type === 'CR' && mutation.amount > 0) {
// Atomic Update: Only update if still pending
const updateResult = await db.transaction.updateMany({
where: {
totalAmount: mutation.amount,
status: 'pending',
provider: 'qris_static',
expiresAt: { gt: new Date() }
},
data: { status: 'paid' }
});
if (updateResult.count > 0) {
const tx = await db.transaction.findFirst({ where: { totalAmount: mutation.amount, status: 'paid' } });
if (tx) {
await db.subscription.create({
data: { userId: tx.userId, provider: 'qris_static', status: 'active' }
});
// Trigger real-time notification to frontend
await pusherServer.trigger(`payment-${tx.id}`, 'payment-success', { success: true });
}
}
}
}
return new Response("OK", { status: 200 });
}
// Drizzle ORM — supports Stripe, Polar, LemonSqueezy, PayPal, DOKU, QRIS Static
export const subscriptions = pgTable('subscriptions', {
id: text('id').primaryKey(),
workspaceId: text('workspace_id').references(() => workspaces.id).notNull(),
provider: text('provider').$type<'stripe' | 'polar' | 'lemonsqueezy' | 'doku' | 'paypal' | 'qris_static'>().notNull(),
externalCustomerId: text('external_customer_id').notNull(),
externalSubId: text('external_sub_id').notNull().unique(),
status: text('status').$type<'active' | 'trialing' | 'past_due' | 'canceled' | 'paused'>().notNull(),
plan: text('plan').$type<'free' | 'pro' | 'enterprise'>().default('free').notNull(),
currentPeriodEnd: timestamp('current_period_end'),
cancelAtPeriodEnd: boolean('cancel_at_period_end').default(false),
createdAt: timestamp('created_at').defaultNow().notNull(),
updatedAt: timestamp('updated_at').defaultNow().notNull(),
});
<a name="bahasa-indonesia"></a>
Terhubung dan mengorkestrasi skill domain yang relevan seperti brainstorming, zero-to-prod-orchestrator, dan session-memory-manager untuk memastikan eksekusi yang kohesif.
Panduan ahli untuk mengimplementasikan dan mengaudit sistem billing SaaS. Mencakup state machine langganan, penanganan webhook aman, sinkronisasi database, dan lanskap billing 2026 termasuk Stripe, Polar.sh (open-source, developer-first), LemonSqueezy, Paddle, DOKU (Checkout & SNAP BI), dan Midtrans (untuk Asia Tenggara).
| Provider | Terbaik Untuk | Open Source | Merchant of Record |
|---|---|---|---|
| Stripe | Enterprise, global, billing kompleks | ❌ | ❌ |
| Polar.sh | Developer-first, produk open-source | ✅ | ✅ (opsional) |
| LemonSqueezy | Indie hackers, harga sederhana | ❌ | ✅ |
| Paddle | B2B SaaS, kepatuhan PPN EU | ❌ | ✅ |
| DOKU (Checkout & SNAP BI) | Indonesia & Asia Tenggara, QRIS, Virtual Account, Multi-kanal | ❌ | ❌ |
| Midtrans | Asia Tenggara / Indonesia | ❌ | ❌ |
| PayPal | Global, kepercayaan konsumen (consumer trust) | ❌ | ❌ |
Merchant of Record (MoR): Provider menangani kepatuhan pajak (PPN, GST), chargeback, dan tanggung jawab hukum — ideal untuk tim kecil tanpa departemen keuangan.
Polar.sh adalah alternatif open-source modern untuk Gumroad/LemonSqueezy, dirancang khusus untuk developer dan proyek open-source. Mendukung checkout, webhook, dan manajemen langganan dengan SDK TypeScript yang bersih.
PayPal sering digunakan sebagai gateway alternatif atau utama karena tingginya kepercayaan konsumen global.
create-order dan capture-order di backend (menggunakan @paypal/checkout-server-sdk) untuk memastikan keamanan dan mencegah manipulasi harga di sisi klien.Kelola transisi status: FREE → TRIALING → ACTIVE → PAST_DUE → CANCELED → (reaktivasi).
Selalu verifikasi tanda tangan webhook dari raw body. Gunakan insert unik atomic di database (bukan sekadar findUnique) agar request retry simultan tidak menyebabkan penambahan saldo atau perpanjangan langganan ganda. Jika terdeteksi duplikat, langsung kembalikan status HTTP 200 OK.
Laporkan penggunaan API dengan stripe.subscriptionItems.createUsageRecord() di akhir periode billing.
Bagi pengguna/developer di Indonesia yang belum memiliki Payment Gateway (seperti Midtrans/DOKU), Anda dapat membuat pengalaman QRIS "Dinamis" menggunakan satu gambar QRIS statis biasa.
pending dengan batas waktu kadaluarsa (misal 15 menit). Tampilkan gambar QRIS beserta instruksi transfer sesuai nominal unik./api/webhooks/mutation) setiap kali ada uang masuk.CR), sistem memperbarui transaksi pending secara atomik. Jika cocok, sistem menandai tagihan sebagai lunas (paid) dan mengaktifkan langganan.Rancang tabel subscriptions yang mendukung beberapa provider (stripe, polar, lemonsqueezy, doku, paypal, qris_static) dengan kolom provider dan ID eksternal yang terpisah.
まだレビューはありません。使ってみた感想をお寄せください。
概要と使いどころ
Expert guide for automated and manual Web Accessibility (a11y) testing — axe-core, Pa11y, Playwright a11y, screen reader testing, and WCAG 2.2 Level AA/AAA compliance / Panduan ahli pengujian aksesibilitas web.
日本語の概要は準備中です。原文の説明を表示しています。
Expert guide for intelligent model cascading and routing — complexity-scored task routing from Flash/Haiku to Sonnet/Opus/Astra, dynamic escalation with quality gates, 40-60% token cost reduction while maintaining output quality / Panduan ahli untuk kaskade dan routing model cerdas — routing tugas berbasis skor kompleksitas dari Flash/Haiku ke Sonnet/Opus/Astra, eskalasi dinamis dengan gerbang kualitas, pengurangan biaya token 40-60% dengan kualitas output terjaga.
日本語の概要は準備中です。原文の説明を表示しています。
Expert guide for Affective Computing, emotional AI, and real-time sentiment analysis through native multimodal tokens (voice intonation and facial micro-expressions) / Panduan ahli komputasi afektif, AI emosional, dan analisis sentimen real-time melalui token multimodal native.
日本語の概要は準備中です。原文の説明を表示しています。
Expert guide for AI-assisted coding workflows — agentic code generation, multi-agent code swarms, self-healing CI/CD, automated PR review, spec-to-code pipelines, codebase knowledge graphs, and human-in-the-loop approval gates / Panduan ahli untuk workflow pengkodean berbasis AI — generasi kode agentic, code swarm multi-agen, CI/CD self-healing, review PR otomatis, pipeline spec-to-code, knowledge graph codebase, dan gate persetujuan human-in-the-loop.
日本語の概要は準備中です。原文の説明を表示しています。
Expert guide for long-term episodic memory integration (Mem0 v2, Letta/MemGPT, Zep v2), memory tier architecture, pgvector HNSW storage, and unified context management for autonomous AI agents / Panduan ahli untuk integrasi memori episodik jangka panjang (Mem0 v2, Letta/MemGPT, Zep v2), arsitektur tier memori, penyimpanan pgvector HNSW, dan manajemen konteks terpadu untuk agen AI otonom.
日本語の概要は準備中です。原文の説明を表示しています。
Expert guide for designing Machine-to-Machine (M2M) micro-economies, autonomous agent wallets, and swarm budget allocation / Panduan ahli merancang ekonomi mikro antar-agen (M2M), dompet agen otonom, dan alokasi anggaran swarm.
日本語の概要は準備中です。原文の説明を表示しています。