One subscriber,every platform.
A bilingual reading platform for manga, novels, comics and BD — where a subscription bought on an iPhone, an Android phone or the web is the same subscription everywhere.
A French publisher wanted a single home for four very different formats — Manga, Roman, Comic and BD — readable in French and English, with a free tier, an all-access tier and per-category fan plans.
The difficult part was never the reader. It was money: Apple, Google and Stripe each have their own idea of what a subscription is, and readers move between devices constantly. The system had to give one answer to one question — is this person a subscriber, right now?
Reader apps
iOS and Android readers for EPUB and PDF with bookmarks, highlights, notes and progress sync.
Web reader
The same catalogue and subscription on the web, billed through Stripe.
Admin panel
Catalogue, volumes, authors, plans, coupons, home-feed builder, notifications and blog.
Platform API
One backend behind every surface — entitlements, reading progress, discovery and push.
How it fitstogether.
What made ithard — and how.
One entitlement, three billing systems
App Store purchases, Stripe subscriptions and promotional codes all arrive differently, at different times, with different failure modes.
Every source funnels into one transaction pipeline. A subscription only ever exists after a verified successful transaction — so the reader apps and the web never disagree about access.
Apple server notifications, handled properly
Renewals, failed renewals, expirations and redeemed offers come from Apple as signed payloads, often hours after the user's action.
Payloads are cryptographically verified, stored raw for audit, then routed by type and subtype to extend, pause or expire access. Purchases are re-verified server-side rather than trusted from the device.
A Stripe state machine with no gaps
Web billing has its own edge cases — past-due invoices, card updates, cancellations mid-cycle.
Signature-checked webhooks drive an explicit state machine over invoice and subscription events, including past-due and payment-method recovery paths.
Reading progress the server can trust
Progress feeds rewards, so a client reporting page 900 of a 200-page book can't be allowed to count.
Page totals are corrected per language on the server, out-of-range pages are rejected, and the reward system only accepts completions that come from the progress tracker itself.
Random rails that still paginate
Shuffled home-feed rows usually repeat or skip items when you scroll to the next page.
Rails are shuffled with a seeded hash so the order is random per session but stable across pages — no duplicates, no gaps.
Everythingit does.
Backend
Node.js · TypeScript · FeathersJS · MongoDB · Socket.io
Web & admin
Next.js · React · MUI · EPUB & PDF readers
Payments
Stripe · App Store Server API · In-app purchases
Platform
Docker · CI/CD · AWS S3 · Firebase Cloud Messaging
