Skip to main content
Quill is a Substack-for-Nigeria: writers publish paid publications, readers subscribe monthly in naira, and creators get paid to a bank account. It is a complete, standalone product with its own accounts, editor, feed, and video. What makes it interesting here is the part it does not build: none of the money. Every subscription, every recurring charge, every failed-payment recovery, every payout, and every airtime top-up is delegated to Duro over its public API. That makes Quill the reference integration for Duro. It is not a smoke test that calls one endpoint. It is a second, independent codebase (NestJS + Drizzle + Next.js) that consumes Duro the way a real merchant would: create a customer, ensure a plan, open a hosted checkout, verify by polling, receive signed webhooks, route payouts through transfers, and buy bills through VAS. If Duro’s managed-subscriptions thesis holds, Quill is the proof that a team can ship a monetised product on top of it without writing a billing engine.
Quill is a hackathon build that uses Duro; it is not part of the Duro monorepo. The backend lives in quill-backend, the frontend in quill-frontend. For the demo, DURO_MODE selects between a MockDuroAdapter (deterministic, offline) and an HttpDuroAdapter that hits a real Duro instance in sandbox with an sk_test key. See Duro Integration.

What Quill owns vs. what Duro owns

The boundary is the whole point. Quill keeps product state; Duro keeps money state. Quill mirrors just enough of Duro’s state (ids and status) to render its own UI and gate content.

Quill owns

Users and roles (reader / creator / admin), publications, posts (TipTap/Markdown), premium-gated video (HLS), comments, the creator dashboard, and an append-only ledger_entries table that records recognised revenue for its own earnings/recovery views.

Duro owns

The customer, the plan, the checkout session, the subscription state machine, the renewal + dunning engine, the recovery decisions, bank transfers (payouts), and VAS/bill vending. Quill never charges a card or moves money itself.

Why it is a strong reference integration

Exercises the managed-subscriptions path end to end

subscribe → checkout → verify → webhook activation → renewal → past_due → recover all run through Duro’s public REST surface (/customers, /plans, /checkout/sessions, /subscriptions/*), with Idempotency-Key on every POST.

Consumes the recovery-first product, not just billing

Quill surfaces a creator recovery view (at-risk MRR, recovered revenue, recovery rate) driven by Duro’s subscription_past_due / subscription_payment_recovered webhooks. Recovery is a feature of the host product, so it becomes a feature of Quill for free.

Uses Duro for money-out and bills too

Creator payouts route through Duro transfers; airtime, data, betting, cable TV, and electricity route through Duro VAS; bank lists and name resolution come from Duro. One processor, four money flows.

Same-origin BFF, clean trust boundary

The Next.js app never talks to the API directly from the browser. A catch-all proxy (app/api/[...path]/route.ts) forwards to the NestJS backend and relays the httpOnly session cookie, mirroring Duro’s own BFF pattern.

The lifecycle in one glance

Two independent activation paths converge on the same result: the synchronous verify poll (for the reader who is still on the page) and the asynchronous signed webhook (the source of truth). Both are idempotent on the ledger, so activation happens exactly once. This dual-path design is detailed in Subscriptions & Recovery.

How to read this section

1

Architecture

Architecture is the whole system at altitude: NestJS modules, the Drizzle schema, the same-origin BFF, BullMQ workers, and R2 media.
2

Duro Integration

Duro Integration is the core: the DuroClient interface, the HTTP adapter’s exact calls, idempotency, and the signed webhook receiver.
3

Subscriptions & Recovery

Subscriptions & Recovery walks the status machine and the recovery-first creator metrics.
4

Payouts & VAS

Payouts & VAS covers money-out (bank accounts, OTP, T+1 settlement) and bill vending, both via Duro.