mirror of
https://github.com/hanzo-apps/hanzo.ai.git
synced 2026-10-30 14:58:08 +00:00
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.
102 lines
5.1 KiB
TypeScript
102 lines
5.1 KiB
TypeScript
'use client'
|
|
|
|
import type { ReactNode } from 'react'
|
|
import { ArrowRight, BarChart3, Clock, Layers, Radio, Server, Shield, Zap } from 'lucide-react'
|
|
import { OSSRevenueBanner } from '@/components/oss/OSSRevenueBanner'
|
|
import { ProductLanding } from '@/components/product/ProductLanding'
|
|
import { ProductFooter } from '@/components/products/ProductFooter'
|
|
|
|
/**
|
|
* PubSub, 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 PubSubPage({ source }: { source: ReactNode }) {
|
|
return (
|
|
<>
|
|
<ProductLanding
|
|
badge={"NATS JetStream"}
|
|
badgeIcon={Radio}
|
|
title={"Hanzo PubSub"}
|
|
tagline={"The bus everything else rides"}
|
|
lede={"PubSub moves messages between services on port 4222. Publish to a subject and everyone listening on it — or on a pattern that matches it — has the message. Add a stream and those same messages are written down too, so a consumer that was offline can start from the beginning, from a sequence number, or from a timestamp. Streams, key-value buckets, an object store and request-reply are one server, not four."}
|
|
ctas={[
|
|
{ label: "GitHub", href: "https://github.com/hanzoai/pubsub" },
|
|
]}
|
|
what={{
|
|
title: "More than pub/sub",
|
|
sub: "Durable streams, key-value, an object store and request-reply — one server, one connection, one set of credentials.",
|
|
pillars: [
|
|
{
|
|
icon: Layers,
|
|
title: "Streams write it down",
|
|
body: "A stream captures the subjects you name and keeps them by age, by count or by bytes. A consumer starts at the beginning, at the newest message, at a sequence number or at a wall-clock time, and reads at the original pace or as fast as it can take them.",
|
|
},
|
|
{
|
|
icon: Zap,
|
|
title: "Acked, so nothing goes quiet",
|
|
body: "A message is redelivered until a consumer acknowledges it. Publishers that stamp a message id get duplicates collapsed inside a window — two minutes unless you say otherwise. Ack every message, ack a sequence to cover everything below it, or ask for no acks at all when fire-and-forget is what you meant.",
|
|
},
|
|
{
|
|
icon: Server,
|
|
title: "Key-value buckets",
|
|
body: "A bucket is a stream that keeps the last value per key, so you get watches, per-key history and expiry from the same server and the same connection. It is where Hanzo Stream keeps its consumer offsets.",
|
|
},
|
|
{
|
|
icon: Clock,
|
|
title: "Request-Reply",
|
|
body: "Send to a subject and wait for one answer. Put several instances of a service in a queue group on that subject and each request goes to exactly one of them — load balancing with nothing in front of them doing it.",
|
|
},
|
|
{
|
|
icon: BarChart3,
|
|
title: "Object Store",
|
|
body: "Payloads too big to be a message are chunked into a stream and put back together on the way out, with a watch for when one changes. Same connection, same credentials, no second system to stand up.",
|
|
},
|
|
{
|
|
icon: Shield,
|
|
title: "Accounts, not passwords",
|
|
body: "An account walls one tenant's subjects off from another's. Credentials are nkeys or signed JWTs rather than a shared secret, permissions are granted per subject, and TLS covers the wire.",
|
|
},
|
|
],
|
|
}}
|
|
stats={{
|
|
items: [
|
|
{ value: "4222", label: "Client port" },
|
|
{ value: "Replay", label: "From any point" },
|
|
{ value: "Durable", label: "Written to disk" },
|
|
{ value: "Replicas", label: "Set per stream" },
|
|
],
|
|
}}
|
|
code={{
|
|
head: { title: "Publish and Subscribe" },
|
|
name: "events.go",
|
|
source,
|
|
}}
|
|
finalCta={{
|
|
title: "Put it between your services",
|
|
sub: "Free tier includes 1M messages/month.",
|
|
buttons: [
|
|
{ label: "View on GitHub", href: "https://github.com/hanzoai/pubsub" },
|
|
],
|
|
}}
|
|
>
|
|
<OSSRevenueBanner />
|
|
</ProductLanding>
|
|
<ProductFooter slug={"pubsub"} name={"PubSub"} />
|
|
</>
|
|
)
|
|
}
|