mirror of
https://github.com/hanzo-apps/hanzo.ai.git
synced 2026-10-30 14:58:08 +00:00
Pages from /machines to /risk, the model pages, and the kits they are made of
(page-kit, ProductLanding, LayerPage, Stack, the models kit, band's Head) mark
authored copy where it is written and draw it in the reader's language. A server
page marks a literal phrase('…') or wraps it in <T>; a client page calls t. The
kits translate a string prop through useSay (components/marketing/say), so a
page passes phrase('…') and markup passes as written. An arrow that points
turns over right to left (data-i18n-mirror).
Rebased on main: the fold-based heroes (Fold, PageHero, MachinesHero, the
product and layer pages) keep main's structure and copy, with their label,
title and lede marked phrase. /platform is main's CloudLanding; the deleted
/platform/layers and the old referral components stay deleted.
Claude-Session: https://claude.ai/code/session_015XYKLjZtDTJEnMo4eK3AFH
103 lines
5.1 KiB
TypeScript
103 lines
5.1 KiB
TypeScript
'use client'
|
|
|
|
import type { ReactNode } from 'react'
|
|
import { ArrowRight, BarChart3, Clock, Layers, ListOrdered, Repeat, Shield, Zap } from 'lucide-react'
|
|
import { OSSRevenueBanner } from '@/components/oss/OSSRevenueBanner'
|
|
import { ProductLanding } from '@/components/product/ProductLanding'
|
|
import { ProductFooter } from '@/components/products/ProductFooter'
|
|
import { phrase } from '@hanzo/i18n'
|
|
|
|
/**
|
|
* MQ, 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 MQPage({ source }: { source: ReactNode }) {
|
|
return (
|
|
<>
|
|
<ProductLanding
|
|
badge={phrase("Job queue")}
|
|
badgeIcon={ListOrdered}
|
|
title={"Hanzo MQ"}
|
|
tagline={phrase("Background work, done later")}
|
|
lede={phrase("MQ is a TypeScript library, not a server to run. Import it and your jobs live as data structures in Hanzo KV: add one here, and a worker in another process picks it up — with priorities, delays, retries with backoff, a rate limit per queue, and parent jobs that wait on their children. Every state change is a Lua script running inside the store, so two workers never take the same job.")}
|
|
ctas={[
|
|
{ label: "GitHub", href: "https://github.com/hanzoai" },
|
|
]}
|
|
what={{
|
|
title: phrase("The queue is data, the workers are yours"),
|
|
sub: phrase("Nothing sits in the middle deciding. The state is in Hanzo KV and your processes race for it, safely."),
|
|
pillars: [
|
|
{
|
|
icon: Clock,
|
|
title: phrase("Scheduling"),
|
|
body: phrase("A cron expression, a delay in milliseconds, or a job that repeats on an interval — timezone aware, and held in the store rather than in a process that might restart."),
|
|
},
|
|
{
|
|
icon: Zap,
|
|
title: phrase("Rate Limiting"),
|
|
body: phrase("Cap how many jobs a queue may start in a window, and how many a single worker runs at once. The third-party API with a quota stops being the reason your service falls over."),
|
|
},
|
|
{
|
|
icon: Layers,
|
|
title: phrase("Priority Queues"),
|
|
body: phrase("A job carries a priority, so the urgent one goes ahead of the backlog. Inside one priority it stays first in, first out, which is what keeps ordinary work from quietly starving."),
|
|
},
|
|
{
|
|
icon: Repeat,
|
|
title: phrase("Retry & Backoff"),
|
|
body: phrase("Set attempts and a backoff — fixed, exponential, or a function you write. A worker that dies mid-job loses its lock and the job is handed to another, so work is attempted at least once and can be attempted twice. Write it to be idempotent and that is a property rather than a surprise."),
|
|
},
|
|
{
|
|
icon: BarChart3,
|
|
title: phrase("Watch it happen"),
|
|
body: phrase("QueueEvents streams completed, failed, progress and stalled as they occur, so a job's life is something you observe rather than reconstruct from logs afterwards."),
|
|
},
|
|
{
|
|
icon: Shield,
|
|
title: phrase("Failure is a state, not a deletion"),
|
|
body: phrase("A job that runs out of attempts lands in the failed set carrying its error and stack. Read it, fix the cause, retry it. Nothing disappears because it went wrong."),
|
|
},
|
|
],
|
|
}}
|
|
stats={{
|
|
items: [
|
|
{ value: phrase("Library"), label: phrase("No broker to run") },
|
|
{ value: "Cron", label: phrase("Scheduling") },
|
|
{ value: phrase("Retries"), label: phrase("With backoff") },
|
|
{ value: phrase("At-least-once"), label: phrase("Delivery") },
|
|
],
|
|
}}
|
|
code={{
|
|
head: { title: phrase("Add a job here, run it there") },
|
|
name: "worker.ts",
|
|
source,
|
|
}}
|
|
finalCta={{
|
|
title: phrase("Add a job and walk away"),
|
|
sub: phrase("Free tier includes 10K jobs/month. No job size limits."),
|
|
buttons: [
|
|
{ label: phrase("View on GitHub"), href: "https://github.com/hanzoai" },
|
|
],
|
|
}}
|
|
>
|
|
<OSSRevenueBanner />
|
|
</ProductLanding>
|
|
<ProductFooter slug={"mq"} name={"MQ"} />
|
|
</>
|
|
)
|
|
}
|