Marryio
Indonesian wedding invitation SaaS in production. 17 templates, 3 user roles, real Indonesian payment rails — built solo end-to-end.
- 17 Wedding templates
- 3 User roles
- 5 Production add-ons
- 8+ Transactional emails
- 8 Wedding planner tabs
- 1 SaaS in production
The brief.
Indonesian wedding invitations sit between two extremes: cheap WhatsApp graphics with zero UX, and bespoke custom-coded sites that cost millions of rupiah and take weeks. Multi-tenant SaaS was the obvious gap, but no one filled it because the market is messy — 17 regional preferences, family-religious-event variations, and payment rails that international tools don't speak.
Marryio fills it. One platform, three roles (Client, Reseller, Superadmin), 17 templates with their own scene systems and animations, and Indonesian payment rails that actually clear — QRIS, GoPay, virtual accounts, refund flows.
The stack.
Frontend
- Next.js 16
- React 19
- TypeScript
- Tailwind v4
- Shadcn UI + Magic UI
Animation
- GSAP + ScrollTrigger (templates)
- Framer Motion (UI)
- Lenis smooth scroll
Backend & Data
- Supabase (auth, Postgres, RLS)
- Server Actions
- React.cache for auth dedup
Payments
- Midtrans Snap API
- QRIS · GoPay · VA · ShopeePay
- Webhook signature verification
Infrastructure
- Cloudflare R2 (media)
- Upstash Redis (rate-limit)
- Vercel + standalone Docker
Ops
- Resend (transactional email)
- Pino structured logging
- Cron (expiry · cleanup)
What it does.
-
Multi-tenant architecture
Three roles (Client, Reseller, Superadmin) sharing the same database with row-level security. Reseller has its own credit ledger, mutation history, and bypass logic for addon gates. RLS policies enforce isolation at the database — not the application.
-
17 distinctive templates
Each template has its own scene system, palette per scene, custom GSAP scroll choreography, and unique mobile experience. Layouts range from split-screen to pinned scroll, scene carousel, sticky card stack, arc slider, and an interactive Minangkabau map with POIs.
-
Wedding Planner add-on
A separate workspace with 8 tabs: checklist (60+ default tasks, 6 cultural task packs), budget (12 categories with auto-sync from invitation orders + vendors), savings tracker with velocity projection, vendor mini-CRM, documents, outfits, traditional seserahan, and 2-way timeline sync with the invitation rundown.
-
E-Invitation card system
Canvas-rendered shareable cards in 5 designs (Noir Prestige, Blush Garden, Sage Botanica, Minimalist Mono, Royal Gold) × 3 sizes (portrait 4:5, square 1:1, story 9:16). Optional QR code embedded for guest check-in.
-
QR Check-in flow
Each guest auto-receives an 8-character unique QR code. On the wedding day, hosts use a public scanner (browser camera + jsQR) to update check-in time. RSVP and physical check-in tracked independently — confirmation online vs attendance offline.
-
Reseller credit ledger
Resellers buy credit packages (Satuan / Starter / Growth / Pro), spawn client invitations from their pool, and the addon gate auto-includes 'analytics + extend_forever' so reseller-managed invitations live forever. Three-layer defense against expiry-bug regressions in publishInvitationAction.
Architecture highlights.
-
Auto-lock protection
Published invitations lock automatically — clients can't accidentally edit a live wedding page on the morning of the event. Name-change detection forces a re-lock so a manual unlock can't quietly publish the wrong couple's names.
-
Per-tenant data isolation
Every query carries the tenant's scope at the database level. A reseller sees only their own client invitations and credit ledger. A client sees only their own invitation, RSVPs, and gallery. Isolation is enforced by the database, not the application — there is no path that bypasses it.
-
Resilient by default
Slow auth backend, rate-limiter outage, or webhook hiccup never takes the public invitation page down for a viewing guest. Auth and rate-limit checks fail open when their dependency is degraded; the guest still gets their invitation.
-
Wedding Planner sync at planner-speed
Budget, vendors, outfits, and timeline stay in sync as the invitation order grows. Adding a venue, a Wedding Planner add-on, or a custom outfit reflects across the planner workspace in under a second — no manual refresh, no inconsistent rows between tabs.
-
Real payment-rail integration
QRIS, GoPay, virtual accounts, and refund flows that actually clear with Indonesian banks. Webhook signature verification, refund status polling across T+1 to T+3 settlement windows, and idempotent order updates — the parts a global payment SDK doesn't ship.
-
Self-host friendly
The platform runs on a managed cloud today, but the same build is deployable as a self-contained container. Useful for the client who wants their wedding data on their own infrastructure, or for the reseller who wants to white-label without depending on a third-party tenant.
What I learned.
-
Constraints sharpen craft
Indonesia-only, solo, no funding — every constraint forced a sharper decision. The seventeen-template constraint pushed a reusable scene-and-palette system, not seventeen forked codebases.
-
Indonesian payment rails are a moat
Webhook authentication, refund status polling across multi-day settlement windows, QRIS dynamic QR generation — none of this is in a tutorial. The debugging is institutional knowledge a global competitor has to rebuild from scratch.
-
Accessibility is recruiter-grade work
Reseller and Superadmin dashboards meet WCAG focus, semantics, and contrast standards. Recruiter-grade portfolios get audited; a wedding SaaS that ignores accessibility loses the family member with a screen reader who's trying to read the invitation.
Need a build like this?
I'm open to full-time, freelance, and corporate engineering work — SaaS, AI integration, and motion-rich web. Discovery call is free.