mirror of
https://github.com/hanzo-apps/hanzo.ai.git
synced 2026-10-30 14:58:08 +00:00
The page drew the beta waitlist: a board, twenty follow and star buttons, and a link rewritten to /beta?ref= over the service's own. A failed read of GET /v1/referral was swallowed, so the share card simply never appeared and the counts read 0. It was also withheld as an empty page while carrying copy. Now the fold's words beside a window that is the service's answer: the link it mints, Copy, the device's share sheet and seven channels each through tagged(link, channel, 'referral'), the counts as Referred, Pending and Qualified, the newest referees, and Change your code (PUT /v1/referral). Signed out the same window stands empty beside Get your link and Sign in, and nothing is asked. A refused read says why with Try again. No amount anywhere: a referral pays nothing, and the line under the words sends paid referrals to /affiliate, which links back. The page is published, and the gate serves the service's answers: both sessions, every channel's tag, the clipboard, the refusal, the rename, no money, no unserved referral address, and a phone.
147 lines
5.3 KiB
TypeScript
147 lines
5.3 KiB
TypeScript
import Link from 'next/link'
|
||
import { phrase } from '@hanzo/i18n'
|
||
import { T } from '@hanzo/i18n/react'
|
||
import { Cta, Page, PageHero, Prose, Section } from '@/components/marketing/page-kit'
|
||
import { pageMeta } from '@/lib/page-meta'
|
||
import { Earn } from '@/components/affiliate/Earn'
|
||
|
||
/**
|
||
* What an affiliate is paid, as hanzoai/cloud apps/affiliate pays it.
|
||
*
|
||
* The commission is a share of Hanzo's MARGIN on a referred org's metered
|
||
* spend, never of the customer's bill, so the customer's price does not move.
|
||
* The constants are that package's own defaults: `defaultRateBps` 2000 for a
|
||
* direct referral, `defaultL2RateBps` 500 and `defaultL3RateBps` 200 up the
|
||
* chain, over `defaultMarginBps` 4000. A share of the bill is derived from them
|
||
* here rather than typed, so the two columns cannot disagree.
|
||
*/
|
||
const MARGIN_BPS = 4000
|
||
const LEVELS = [
|
||
{ level: phrase('Direct'), bps: 2000, who: phrase('An org that signed up through your link.') },
|
||
{ level: phrase('Second'), bps: 500, who: phrase('An org one of your referrals brought.') },
|
||
{ level: phrase('Third'), bps: 200, who: phrase('One step further. Nothing accrues past three.') },
|
||
]
|
||
|
||
const pct = (bps: number) => `${Number((bps / 100).toFixed(1))}%`
|
||
const ofBill = (bps: number) => pct((bps * MARGIN_BPS) / 10000)
|
||
|
||
export const metadata = pageMeta({
|
||
title: 'Affiliates',
|
||
description: 'Earn recurring revenue sharing on customer referrals. High-commission affiliate program for developers, creators, and agencies.',
|
||
path: '/affiliate',
|
||
})
|
||
|
||
export default function Affiliate() {
|
||
const direct = LEVELS[0].bps
|
||
return (
|
||
<Page>
|
||
<PageHero
|
||
eyebrow={phrase('Affiliates')}
|
||
title={`${ofBill(direct)} of what your referrals spend`}
|
||
lede={
|
||
<T values={{ share: pct(direct) }}>
|
||
{'A direct referral pays you {share} of Hanzo’s margin on its metered spend, every period it spends.'}
|
||
</T>
|
||
}
|
||
visual={<Earn levels={LEVELS.map(({ level, bps }) => ({ level, bps }))} margin={MARGIN_BPS} />}
|
||
>
|
||
<Cta href="mailto:[email protected]">
|
||
<T>Apply</T>
|
||
</Cta>
|
||
</PageHero>
|
||
<Section title={phrase('How it works')}>
|
||
<Prose>
|
||
<ol>
|
||
<li>
|
||
<T values={{ apply: <code>POST /v1/affiliate/apply</code>, email: '[email protected]' }}>
|
||
{'Apply with {apply}, or write to {email}.'}
|
||
</T>
|
||
</li>
|
||
<li>
|
||
<T values={{ link: <code>https://hanzo.ai/?aff=<code></code> }}>{'Once approved you have a code and a link, {link}.'}</T>
|
||
</li>
|
||
<li>
|
||
<T>{'An org that signs up through the link is yours: first touch, one affiliate per org, never your own.'}</T>
|
||
</li>
|
||
<li>
|
||
<T>{'Each period, commission accrues on that org’s metered spend, once per org per period.'}</T>
|
||
</li>
|
||
<li>
|
||
<T>{'Payouts are recorded against what has accrued, as Hanzo credits or in cash.'}</T>
|
||
</li>
|
||
</ol>
|
||
</Prose>
|
||
</Section>
|
||
<Section title={phrase('Rates')} lede={phrase('Each level is a share of Hanzo’s margin on the referred org’s spend.')}>
|
||
<Prose>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>
|
||
<T>Level</T>
|
||
</th>
|
||
<th>
|
||
<T>Share of margin</T>
|
||
</th>
|
||
<th>
|
||
<T>Of the bill, at the default margin</T>
|
||
</th>
|
||
<th>
|
||
<T>Who</T>
|
||
</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
{LEVELS.map((l) => (
|
||
<tr key={l.level}>
|
||
<td>
|
||
<T>{l.level}</T>
|
||
</td>
|
||
<td>{pct(l.bps)}</td>
|
||
<td>{ofBill(l.bps)}</td>
|
||
<td>
|
||
<T>{l.who}</T>
|
||
</td>
|
||
</tr>
|
||
))}
|
||
</tbody>
|
||
</table>
|
||
</Prose>
|
||
</Section>
|
||
<Section title={phrase('What you can read')}>
|
||
<Prose>
|
||
<p>
|
||
<T
|
||
values={{
|
||
me: <code>GET /v1/affiliate/me</code>,
|
||
earnings: <code>GET /v1/affiliate/me/earnings</code>,
|
||
links: <code>GET /v1/affiliate/me/links</code>,
|
||
}}
|
||
>
|
||
{'{me} answers your standing, what has accrued, what is pending and what has been paid. {earnings} shows each period’s margin and the commission taken from it, and {links} the clicks, signups and conversions behind each link.'}
|
||
</T>
|
||
</p>
|
||
<p>
|
||
<T
|
||
values={{
|
||
referral: (
|
||
<Link href="/referral">
|
||
<T>referral</T>
|
||
</Link>
|
||
),
|
||
royalty: (
|
||
<Link href="/oss">
|
||
<T>the royalty page</T>
|
||
</Link>
|
||
),
|
||
}}
|
||
>
|
||
{'A {referral} on its own pays nothing; what a qualified referral is worth is this commission. Authors of open source are paid on a separate schedule, described on {royalty}.'}
|
||
</T>
|
||
</p>
|
||
</Prose>
|
||
</Section>
|
||
</Page>
|
||
)
|
||
}
|