Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 79 additions & 0 deletions components/ContributeSection.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import Link from 'next/link'

// Contribute-for-credits landing SECTION.
//
// Placed after the trust summary (the open-source / trust cluster) because
// this is a commons / flywheel message, not a pricing gimmick: contributions
// strengthen the shared hardening corpus that lowers everyone's
// silent-wrong-effect rate. The full mechanism, expanded guarantees, program
// status, and FAQ live on /contribute.
//
// Framing is binding (see the data-for-credits framing brief): lead with the
// guarantees, never "sell/monetize your data", no per-record price. The
// program is EARLY ACCESS (gated on legal terms), so the copy is "request
// access", never "upload now / available today", and never claims any data has
// been collected.

const GUARANTEES = [
'Sanitized, de-identified derivatives only. Raw recordings never leave your machine.',
'You approve every byte through hash-bound local review before anything is shared.',
'Opt-in and off by default. You can stop future contributions at any time.',
'Every contribution must meet the named de-identification standard in the versioned terms, and your organization attests before sharing.',
]

export default function ContributeSection() {
return (
<section
id="contribute"
className="border-b border-hairline bg-ground px-5 py-16 md:py-20"
aria-labelledby="contribute-heading"
>
<div className="mx-auto max-w-4xl">
<div className="flex flex-wrap items-center gap-3">
<p className="eyebrow">Strengthen the commons</p>
<span className="rounded-full border border-hairline bg-panel px-3 py-1 font-mono text-[10px] font-medium uppercase tracking-[0.14em] text-ink-2">
Early access
</span>
</div>
<h2
id="contribute-heading"
className="mt-3 max-w-2xl font-display text-2xl font-semibold tracking-tight text-ink md:text-3xl"
>
Contribute data for credits
</h2>
<p className="mt-4 max-w-2xl text-sm leading-relaxed text-ink-2 md:text-base">
Every sanitized contribution strengthens the shared
hardening corpus, the commons that lowers everyone&apos;s
silent-wrong-effect rate. In return, you earn run credits
that extend your usage allowance.
</p>

<ul className="mt-8 grid gap-4 md:grid-cols-2">
{GUARANTEES.map((item) => (
<li
key={item}
className="flex gap-2.5 rounded-xl border border-hairline bg-panel p-4 text-sm leading-relaxed text-ink-2"
>
<span
aria-hidden="true"
className="mt-[2px] flex-shrink-0 font-mono text-accent"
>
</span>
<span>{item}</span>
</li>
))}
</ul>

<div className="mt-8 flex flex-wrap items-center gap-4">
<Link href="/contribute" className="btn-ink">
Request access to the contributor program
</Link>
<span className="text-xs leading-relaxed text-ink-3">
Early access. Opt-in. Sanitized derivatives only.
</span>
</div>
</div>
</section>
)
}
225 changes: 225 additions & 0 deletions components/ContributorProgramForm.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
import { useState } from 'react'
import Link from 'next/link'

import { trackEmailCapture } from 'utils/conversion'

// Dedicated intake for the contribute-for-credits program.
//
// Posts to the durable Netlify Forms lead path (`/form.html`) under its own
// form name, `contributor-program`, so contributor leads land in their own
// Netlify submissions bucket instead of the generic `contact` queue. The
// hidden form definition lives in public/form.html; Netlify's build-time bots
// read it from there. Registering interest shares only these contact fields;
// it never enables any upload or shares any workflow data.

const INITIAL_FORM = {
name: '',
email: '',
company: '',
role: '',
workflows: '',
message: '',
botField: '',
}

export default function ContributorProgramForm() {
const [form, setForm] = useState(INITIAL_FORM)
const [isSubmitting, setIsSubmitting] = useState(false)
const [isSubmitted, setIsSubmitted] = useState(false)
const [error, setError] = useState('')

const handleChange = (event) => {
const { name, value } = event.target
setForm((prev) => ({
...prev,
[name]: value,
}))
}

const handleSubmit = async (event) => {
event.preventDefault()
setError('')
setIsSubmitting(true)

try {
const formData = new URLSearchParams()
formData.set('form-name', 'contributor-program')
formData.set('name', form.name)
formData.set('email', form.email)
formData.set('company', form.company)
formData.set('role', form.role)
formData.set('workflows', form.workflows)
formData.set('message', form.message)
formData.set('bot-field', form.botField)

const response = await fetch('/form.html', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: formData.toString(),
})

if (!response.ok) {
throw new Error(
`Form submission failed with status ${response.status}`
)
}

// E1 qualified-lead conversion: contributor-program interest
// captured. Carries first-touch utm_* attribution; never any form
// contents.
trackEmailCapture({ location: 'contributor_program_form' })
setIsSubmitted(true)
} catch (submitError) {
console.error(submitError)
setError(
'Submission failed. Please email hello@openadapt.ai directly.'
)
} finally {
setIsSubmitting(false)
}
}

return (
<div className="rounded-2xl border border-hairline bg-panel p-6 md:p-8">
{!isSubmitted ? (
<form
className="space-y-4"
onSubmit={handleSubmit}
data-netlify="true"
netlify-honeypot="bot-field"
name="contributor-program"
>
<input
type="hidden"
name="form-name"
value="contributor-program"
/>
<p className="hidden">
<label>
Do not fill this out if you are human:{' '}
<input
name="bot-field"
value={form.botField}
onChange={(event) =>
setForm((prev) => ({
...prev,
botField: event.target.value,
}))
}
/>
</label>
</p>

<div className="grid gap-4 md:grid-cols-2">
<label className="flex flex-col gap-2 text-sm">
Name *
<input
type="text"
name="name"
required
value={form.name}
onChange={handleChange}
className="rounded-lg border border-ink/30 bg-panel px-3 py-2 text-ink placeholder-ink-3/60 focus:border-accent focus:outline-none"
placeholder="Your Name"
/>
</label>
<label className="flex flex-col gap-2 text-sm">
Work email *
<input
type="email"
name="email"
required
value={form.email}
onChange={handleChange}
className="rounded-lg border border-ink/30 bg-panel px-3 py-2 text-ink placeholder-ink-3/60 focus:border-accent focus:outline-none"
placeholder="name@company.com"
/>
</label>
<label className="flex flex-col gap-2 text-sm">
Organization
<input
type="text"
name="company"
value={form.company}
onChange={handleChange}
className="rounded-lg border border-ink/30 bg-panel px-3 py-2 text-ink placeholder-ink-3/60 focus:border-accent focus:outline-none"
placeholder="Acme Inc"
/>
</label>
<label className="flex flex-col gap-2 text-sm">
Role
<input
type="text"
name="role"
value={form.role}
onChange={handleChange}
className="rounded-lg border border-ink/30 bg-panel px-3 py-2 text-ink placeholder-ink-3/60 focus:border-accent focus:outline-none"
placeholder="Operations Manager"
/>
</label>
</div>

<label className="flex flex-col gap-2 text-sm">
Workflows you would consider contributing
<input
type="text"
name="workflows"
value={form.workflows}
onChange={handleChange}
className="rounded-lg border border-ink/30 bg-panel px-3 py-2 text-ink placeholder-ink-3/60 focus:border-accent focus:outline-none"
placeholder="Claims intake, eligibility checks, order entry"
/>
</label>

<label className="flex flex-col gap-2 text-sm">
Anything else
<textarea
name="message"
rows={4}
value={form.message}
onChange={handleChange}
className="rounded-lg border border-ink/30 bg-panel px-3 py-2 text-ink placeholder-ink-3/60 focus:border-accent focus:outline-none"
placeholder="Systems involved, data sensitivity, questions about the terms"
/>
</label>

{error && (
<p className="rounded-lg border border-red-800/40 bg-red-100 px-3 py-2 text-sm text-red-900">
{error}
</p>
)}

<p className="text-xs leading-relaxed text-ink-3">
Registering interest shares only the contact details
above. It does not enable any upload, share any
workflow data, or accept any terms.
</p>
<div className="flex flex-wrap items-center gap-3">
<button
type="submit"
disabled={isSubmitting}
className="btn-ink disabled:cursor-not-allowed disabled:opacity-60"
>
{isSubmitting
? 'Submitting...'
: 'Request access'}
</button>
<Link href="/" className="btn-ghost-ink">
Back to home
</Link>
</div>
</form>
) : (
<div className="rounded-xl border border-accent/40 bg-accent/10 px-4 py-4">
<p className="text-sm text-accent">
Thanks. You are on the early-access list for the
contributor program. We will reach out when the
versioned terms are finalized and access opens.
</p>
</div>
)}
</div>
)
}
31 changes: 31 additions & 0 deletions components/Pricing.js
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,37 @@ export default function Pricing({ hostedOffer = null }) {
</aside>
</div>

{/*
* Option A (chosen): a credits callout under the tiers, not a
* fourth "pay-with-data" tier. Frames credits as extending
* your monthly run cap, which is what the mechanism does.
* Marked early access; links to /contribute for the full
* program, guarantees, and terms status.
*/}
<div className="mx-auto mt-10 max-w-3xl rounded-2xl border border-hairline bg-panel p-6 md:p-7">
<div className="flex flex-wrap items-center gap-3">
<p className="eyebrow">Earn credits by contributing</p>
<span className="rounded-full border border-hairline bg-ground px-3 py-1 font-mono text-[10px] font-medium uppercase tracking-[0.14em] text-ink-2">
Early access
</span>
</div>
<p className="mt-3 text-sm leading-relaxed text-ink-2">
Contribute a sanitized, de-identified derivative to the
shared hardening corpus and earn run credits that
extend your monthly run cap. Raw recordings never
leave your machine, you approve every byte, and it
stays opt-in; you can stop future contributions at any
time. The program opens once its versioned terms are
finalized.{' '}
<Link
href="/contribute"
className="text-accent underline"
>
Request access to the contributor program.
</Link>
</p>
</div>

<p className="mx-auto mt-8 max-w-3xl text-center text-xs leading-relaxed text-ink-3">
{hostedOfferAvailable
? 'The Cloud subscription price comes directly from Stripe and is confirmed again at checkout.'
Expand Down
Loading
Loading