Doc Status: Current for the referral implementation in the Hono backend, landing booking flow, dashboard referral page, partner profile page, and Remotion sticker renderer as of 2026-06-11.

Why This Matters

House of Legends needs referrals that feel natural to guests while still giving operators accurate partner attribution. Hotels, bars, pubs, concierges, and influencers can share a clean public link or QR sticker without exposing the underlying referral code. The backend remains the source of truth for partner identity, discount rules, commission terms, earned commission rows, and payout state. One referral partner can own multiple managed codes and multiple public /go/{slug} or /{locale}/go/{slug} links. Landing only stores hidden attribution and passes it back during booking; dashboard manages partners, codes, links, commercial rules, and operational materials.

How It Works

The guest sees a friendly URL such as:
https://houseoflegends.vn/go/hotel-menu
Dashboard-generated links use the localized English form by default:
https://houseoflegends.vn/en/go/hotel-menu
Legacy and printed root links remain valid and redirect into the English booking flow. Localized links preserve the active locale before redirecting to the configured booking destination. The managed referral code remains internal for QR and partner links. The landing app stores the resolved referralCode and referralLinkId in first-party attribution storage, applies any guest discount in booking preview, shows the partner attribution in checkout, and sends the hidden referralLinkId when creating the reservation. Guests who have a visible promo or referral code can also enter it in the payment step before leaving for OnePay.
The public /go/{slug} and /{locale}/go/{slug} links are intentionally not discount-code URLs. Do not add ?ref= or visible referral-code query parameters to partner links unless the product decision changes.
Partners can also open a dedicated noindex page:
https://houseoflegends.vn/partner/hotel-name
That page redirects to the localized route, renders server-side from GET /api/referral-partners/{slug}/profile, explains the current earning rules, and shows safe aggregate statistics, active codes, and active links. It is public for convenience but excluded from indexing and normal site navigation.

PostHog Attribution

PostHog receives referral context in three places:
Event sourceEventReferral fields
Hono resolverreferral link resolvedreferral_code_id, referral_code, referral_partner_id, referral_partner_name, referral_partner_type, referral_link_id, referral_link_slug, referral_link_channel, attribution_event_id, has_referral
Hono booking and payment eventsreservation created, checkout started, payment completed, payment failed, reservation cancelled, refund processedSame partner/code/link identifiers plus referral_discount_amount_vnd
Landing browser analyticsreferral_connected and later PostHog browser eventsRegistered referral super properties under the same partner/code/link names so checkout behavior can be filtered by partner
The resolver event is the top-of-funnel signal. It fires when a public /go/{slug} or /{locale}/go/{slug} link resolves successfully, even if the visitor never completes checkout.

Operator Workflow

1

Create or update a referral partner

In the dashboard referral page, create the partner once, set its type, status, contact fields, and public slug. The slug controls /partner/{slug}.
2

Attach one or more managed referral codes

Create referral codes under the partner. Each code owns optional guest discount rules and partner commission terms. Active referral codes require a positive commission value.
3

Generate a friendly link

Use the QR links panel to create a public slug, destination path, channel, placement label, and status. Channels include QR sticker, hotel menu, bar, pub, concierge, influencer, and other.
4

Create the sticker artwork

The dashboard previews the QR and provides a Remotion render command. The editor package renders printable PNG stickers from the same /go/{slug} URL.
5

Track paid attribution

When a referred reservation is paid, Hono creates an earned commission row based on the final paid amount and the code’s commission rules.
6

Approve and pay

Operators approve earned commission rows, queue them for payout, then create payout batches by partner.

Commercial Rules

RuleOwnerNotes
Partner identityHonoStored once in hol_referral_partners; multiple codes can point to the same partner.
Guest discountHonoOptional. Can be percentage or fixed VND amount.
Partner commissionHonoRequired for active codes. Can be percentage or fixed VND amount.
Commission basisHonoCurrently final paid amount.
Commission capHonoOptional maximum commission amount in VND.
Partner profile pageHono and Landing/partner/{slug} is public/noindex and shows safe rules, stats, active codes, and active links.
Hidden attribution storageLandingCookie and local storage under first-party House of Legends origin.
QR and sticker artworkDashboard and editorDashboard creates links and previews QR; Remotion renders print assets.
Payout stateHonoDashboard updates commission status and creates payout batches.
Referral discounts and referral commissions are separate values. A partner can receive a commission even when the guest receives no discount.

Data Model

The referral implementation adds these major records:
TablePurpose
hol_referral_partnersPartner identity, status, type, contact fields, notes, and public slug.
hol_referral_codesManaged code rules, guest discount configuration, partner commission configuration, and partner relation.
hol_referral_linksPublic slug, destination path, placement channel, and managed code link.
hol_referral_attribution_eventsResolve-time attribution events for audit and conversion analysis.
hol_referral_commissionsEarned commission rows created after successful paid reservations.
hol_referral_payoutsPayout batches that group approved or payout-pending commissions.
hol_reservation_records.referral_link_idThe hidden link attached to a paid reservation.
Referral code records store partner commission configuration:
type ReferralCommissionConfig = {
  commissionType: "PERCENTAGE" | "FIXED_AMOUNT" | null;
  commissionValue: number | null;
  commissionBasis: "FINAL_PAID_AMOUNT";
  commissionMaxAmount: number | null;
  commissionNotes: string | null;
};

API Surfaces

POST /api/referral-links/resolve/{slug}
Used by the landing /go/{slug} and /{locale}/go/{slug} routes. It resolves a friendly public slug, records attribution metadata, and returns hidden booking attribution for the landing app.

Remotion Sticker Templates

The editor package includes three still templates:
TemplateComposition IDUse case
Classic GoldReferralSticker-ClassicGoldGeneral square sticker or menu placement.
Menu TentReferralSticker-MenuTentVertical table card or menu insert.
Influencer CardReferralSticker-InfluencerCardSocial profile or creator media card.
Render a sticker with:
pnpm --filter @hol/editor render:referral-sticker -- --template classic-gold --url "https://houseoflegends.vn/go/hotel-menu" --title "House of Legends" --output "output/referrals/hotel-menu.png"

Release Audit Notes

Deployment should include only reviewed referral changes. If the worktree contains unrelated landing, Hono, dashboard, asset, or docs changes, do not deploy until those changes are reviewed or isolated.
Focused verification for this implementation should include:
CheckCommand or action
Hono typecheckpnpm --filter @hol/hono typecheck
Hono OpenAPIpnpm --filter @hol/hono generate
Fern clientpnpm --filter @hol/client generate
Landing typecheckpnpm --filter @hol/landing typecheck
Dashboard typecheckpnpm --filter @hol/dashboard typecheck
Sticker renderpnpm --filter @hol/editor render:referral-sticker -- --url "https://houseoflegends.vn/go/test"
AreaOwner files
Backend schema and servicesapps/hono/src/db/schema/referrals.sql.ts, apps/hono/src/services/booking-config/referral-link.service.ts, apps/hono/src/services/booking-config/referral-commission.service.ts
Landing hidden attributionapps/landing/app/go/[slug]/route.ts, apps/landing/app/[locale]/go/[slug]/route.ts, apps/landing/lib/referrals/referral-go-route.ts, apps/landing/lib/referrals/referral-attribution.ts, apps/landing/contexts/booking/booking-context.tsx
Dashboard operationsapps/dashboard/app/dashboard/referrals/referrals-client.tsx, apps/dashboard/components/admin/referrals/referral-link-sticker-panel.tsx, apps/dashboard/components/admin/referrals/referral-commission-ledger.tsx
Sticker rendererapps/editor/src/compositions/referral/referral-sticker.tsx, apps/editor/scripts/render-referral-sticker.ts