Files
zeekayandGitHub 949608fd9d i18n: pages and components c–l draw their copy through @hanzo/i18n (#67)
Calculator, captable, careers, cloud, compare, contact and contact-sales,
customers, dashboards, dataroom, datastore, dev, download, enso,
enterprise, extension, family, integrations, investors, kai, learn,
legal and their components say their words through t() in client code,
<T> in server components and phrase() where copy is held as data; one
sentence is one key, figures and links its arguments.

Rebased on main: in every conflict main's file stands (its copy, layout
and styling) and only the wrapping is added back, including copy main
added since.

Claude-Session: https://claude.ai/code/session_015XYKLjZtDTJEnMo4eK3AFH
2026-10-30 01:15:31 -07:00

105 lines
5.2 KiB
TypeScript

'use client'
import type { ReactNode } from 'react'
import { ArrowRight, Filter, Flag, FlaskConical, LineChart, Play, Users } from 'lucide-react'
import { OSSRevenueBanner } from '@/components/oss/OSSRevenueBanner'
import { ProductLanding } from '@/components/product/ProductLanding'
import { ProductFooter } from '@/components/products/ProductFooter'
import { useI18n } from '@hanzo/i18n/react'
/**
* Insights, through the ONE product kit.
*
* One of NINE pages — console, insights, kms, kv, mq, pubsub, sql, storage,
* stream — that shared a class set 100%: the same hero, stat row, six-card
* grid, terminal and call to action, written out nine times in ~310 utility
* classes each. They now pass one typed props object to `ProductLanding` and
* carry zero layout classes. See LLM.md, "Tailwind is NOT gone", for the rule.
*
* EVERY WORD IS THE ONE THAT WAS HERE, the four stat tiles included: 28 of the
* group's 36 carry a port, a version, a licence or a coding the prose does not
* (measured), so unlike /ledger's four they are not restatements and they stay.
*
* One fix the move makes by construction: ProductFooter sat INSIDE the final
* card's `max-w-4xl` wrapper on all nine, so the OSS attribution and deploy
* block rendered narrower here than on every other product page.
*/
export default function InsightsPage({ source }: { source: ReactNode }) {
const { t } = useI18n()
return (
<>
<ProductLanding
badge={"insights.hanzo.ai"}
badgeIcon={LineChart}
title={"Hanzo Insights"}
tagline={t("Product analytics and feature flags")}
lede={t("Every event your product emits lands in one place, and the questions you ask of it are the same ones you would ask of a database — funnels and retention when a chart will do, SQL when it will not. The flag that turned a feature on and the recording of someone using it are in that same place, so \"did this change work\" is one product rather than three.")}
ctas={[
{ label: t("Open Insights"), href: "https://insights.hanzo.ai", icon: ArrowRight },
]}
what={{
title: t("Ship it, then find out"),
sub: t("The rollout and the measurement are the same product, so the loop closes."),
pillars: [
{
icon: LineChart,
title: t("Events, and SQL when you need it"),
body: t("Autocapture gets you data before you have instrumented anything, and named events get you data you can trust. When a chart cannot express the question, write the query instead — it is the same table underneath."),
},
{
icon: Flag,
title: t("Feature flags"),
body: t("Roll out to a percentage, a cohort, or one account. The flag is also a kill switch, which is the reason to reach for one: turning a feature off should not require a deploy at the worst possible moment."),
},
{
icon: Play,
title: t("Session replay"),
body: t("Watch what actually happened. Heatmaps and scroll depth tell you where attention went; a replay tells you why someone gave up, which no funnel ever will."),
},
{
icon: FlaskConical,
title: t("Experiments"),
body: t("An experiment is a flag with a metric attached to it. Pick the goal before you start, and let it run until the result means something rather than until it looks good."),
},
{
icon: Filter,
title: t("Funnels, retention and paths"),
body: t("Funnels show where people stop, retention shows whether they came back, and paths show the route nobody designed. The third one is usually where the surprise is."),
},
{
icon: Users,
title: t("Errors and LLM cost"),
body: t("Error tracking sits beside the analytics, so a spike in rage clicks and the exception behind it are one investigation. If your product calls a model, the traces, latency and cost per generation land here too."),
},
],
}}
stats={{
items: [
{ value: t("Events"), label: t("Auto-capture") },
{ value: t("Flags"), label: t("Feature flags") },
{ value: "A/B", label: t("Experiments") },
{ value: "OSS", label: t("Self-hosted") },
],
}}
code={{
head: { title: t("The flag and the event, in one provider") },
name: "app.tsx",
source,
}}
finalCta={{
title: t("Start with autocapture"),
sub: t("Drop the provider in and you have data by this afternoon. Name the events that matter once you know which ones those are. There is a free tier, and the whole thing is open source if you would rather run it yourself."),
buttons: [
{ label: t("Try Hanzo"), href: "/login", icon: ArrowRight },
{ label: t("View on GitHub"), href: "https://github.com/hanzoai/insights" },
],
}}
>
<OSSRevenueBanner />
</ProductLanding>
<ProductFooter slug={"insights"} name={"Insights"} />
</>
)
}