Files
hanzo.ai/app/(marketing)/insights/view.tsx
zeekay 11265a21fd Highlight every code sample with shiki in the code theme
Code on hanzo.ai was plain monospace: 285 blocks across 200 pages, one of
them hand-inked in four greys. components/code now renders each sample
at build with shiki and @hanzo/ui's codeTheme (Dracula dark, GitHub
Light light), every colour written as light-dark() so the page's
color-scheme picks it, on the theme's own ground. The page ships the
coloured spans and no highlighter; e2e/gates/code.spec.ts holds both.

A client page that shows code is split into a server page.tsx that owns
the sample and a client view.tsx that takes the highlighted node:
ProductLanding's code.source, the blockchain pages' codeExamples, the
models kit Sample, the guest-key card, realtime, analytics, payments,
sdks and the rest. Transcripts, agent prompts and ASCII diagrams are not
code and keep their markup.

Takes @hanzo/ui 8.27.83 for codeTheme and @hanzo/design 0.5.35 with it,
regenerates app/gui.css for the new theme keys, and lowers the raw-colour
allowance to 58: the samples' literal inks are gone.
2026-10-05 01:31:58 -07:00

103 lines
5.0 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'
/**
* 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 }) {
return (
<>
<ProductLanding
badge={"insights.hanzo.ai"}
badgeIcon={LineChart}
title={"Hanzo Insights"}
tagline={"Product analytics and feature flags"}
lede={"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: "Open Insights", href: "https://insights.hanzo.ai", icon: ArrowRight },
]}
what={{
title: "Ship it, then find out",
sub: "The rollout and the measurement are the same product, so the loop closes.",
pillars: [
{
icon: LineChart,
title: "Events, and SQL when you need it",
body: "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: "Feature flags",
body: "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: "Session replay",
body: "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: "Experiments",
body: "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: "Funnels, retention and paths",
body: "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: "Errors and LLM cost",
body: "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: "Events", label: "Auto-capture" },
{ value: "Flags", label: "Feature flags" },
{ value: "A/B", label: "Experiments" },
{ value: "OSS", label: "Self-hosted" },
],
}}
code={{
head: { title: "The flag and the event, in one provider" },
name: "app.tsx",
source,
}}
finalCta={{
title: "Start with autocapture",
sub: "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: "Try Hanzo", href: "/login", icon: ArrowRight },
{ label: "View on GitHub", href: "https://github.com/hanzoai/insights" },
],
}}
>
<OSSRevenueBanner />
</ProductLanding>
<ProductFooter slug={"insights"} name={"Insights"} />
</>
)
}