Lynqfy
Creator digital storefront — React 19 + Vite SPA, Firebase platform, Stripe Connect Express for creator payouts, SendGrid for delivery. Multi-tenant SaaS with a card-based landing-page builder and Free/Pro subscription tiers.
Top → bottom
Browser · React 19 + Vite + TypeScript + React Router 7
Feature-slice SPA — 8 domains, Zustand for state, no SSR, no Next.js
Firebase Platform
Auth (Google + email) · Firestore · Storage (product files) · Hosting (SPA rewrites) · Analytics
Cloud Functions v2 · Node.js 22 + TypeScript
Stripe webhook · checkout sessions · Connect Express · signed URLs · SendGrid email
External services
Stripe Connect Express
Creator payouts · platform fees · subscription billing
SendGrid
Download links · email retry · transactional delivery
Custom domain / DNS
Branded creator emails (Zoho) · vanity URLs
Each slice owns its components/ hooks/ pages/ services/
auth
Firebase email/password + Google sign-in. Username setup modal on first login. Plan validation hook gates pro features.
dashboard
Revenue chart, recent purchases/donations, products & pages overview. Each widget has its own Firestore-backed service + hook.
products
Create, edit, delete digital products. File upload to Firebase Storage. Price, title, download cap, visibility settings.
landing
Card-based drag-and-drop page builder. 6 card types, theme presets (Free/Pro), SEO config, draft/published status.
plans
Free vs Pro tier UI. Subscription checkout via subscriptionCheckout function. Upgrade prompts gated by planTier.
stripe
Stripe Connect Express onboarding (createConnectAccount). Platform fee: 5% Free / 0% Pro. Connect account status polling.
onboarding
Step-by-step wizard for new creators: profile setup, product creation, landing page, Connect Express linking.
marketing
Public-facing site: hero, pricing, FAQ, social proof, theme gallery, trust section. Separate from the auth bundle.
A landing page is a LandingConfig with an ordered array of typed cards. Each card carries type, order, visible, planTier, and type-specific data.
headerAvatar, display name, bio — the top identity block.
productRenders selected products with buy buttons and style variants.
galleryImage grid or carousel with configurable max count.
link-buttonSingle CTA link with customizable label and URL.
social-gridPlatform icon row/grid with per-platform visibility toggle.
support-meDonation / tip button backed by optional Stripe price.
Theme system
Each page has a ThemePreset: colors, fonts, spacing, corner radius, shadow, background (solid / gradient / pattern / image), special effects (matrix rain, particles). Free plan gets base presets; Pro unlocks all. Slug routing uses publicLandings/{mappingId} for vanity URLs.
application_fee_amount field in the checkout session — no manual accounting needed.createConnectAccount initiates the Stripe Express onboarding flow.getConnectStatus polls account verification state. Creators can only receive payouts once their Connect account is fully verified.Products and landing pages are nested under each user's document
email, username, plan (free|pro), stripeConnectId, createdAt
title, price, fileRef (Storage path), downloadCap, visible, ownerId
username, cards[], themePresetId, seo{}, status (draft|published)
username → userId mapping for public slug routing
productId, buyerEmail, stripeSessionId, paid, downloadCount, createdAt
Written by stripeWebhook on checkout.session.completed
orderId, buyerEmail, timestamp — download analytics
orderId, status, sentAt — SendGrid delivery tracking
userId, event, stripeSubscriptionId, createdAt
Revenue aggregates per creator
Webhook is the source of truth — fulfillment happens server-side, not on client redirect.
Checkout
createCheckoutSession → Stripe session
Payment
Stripe confirms, fires webhook event
stripeWebhook
Cloud Function validates signature
Persist
Order written to orders/{id}
getDownloadLink
Signed URL from Firebase Storage
SendGrid
emailDownloadLink delivers to buyer
getDownloadLink generates a time-limited signed URL from Firebase Storage. Each call decrements downloadCount on the order; once the cap is hit the function returns 403. Storage rules deny all public reads.emailDownloadLink sends the signed URL via SendGrid immediately after the webhook. emailRetry is a separate function for manual resend — useful when SendGrid delivery fails. Both log to email_logs.Stripe webhook events: checkout.session.completed · payment_intent.succeeded · invoice.payment_failed · customer.subscription.updated/deleted