mirror of
https://github.com/hanzo-apps/hanzo.ai.git
synced 2026-10-29 07:20:43 +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.
133 lines
5.1 KiB
TypeScript
133 lines
5.1 KiB
TypeScript
'use client'
|
|
|
|
import React, { type ReactNode } from "react";
|
|
import { motion } from "@/components/motion";
|
|
import { Code as Glyph, ArrowRight } from "lucide-react";
|
|
import { View, YStack, XStack } from '@hanzo/ui'
|
|
import { Grid } from '@hanzo/ui/grid'
|
|
import { Line } from '@/components/type'
|
|
import { DOCS } from '@/components/home/nav-data'
|
|
import { Action, Lede, Title } from '@hanzo/ui/marketing'
|
|
|
|
// Define a proper type for the presence event
|
|
interface PresenceEvent {
|
|
action: 'join' | 'leave';
|
|
userData: {
|
|
name: string;
|
|
[key: string]: string | number | boolean;
|
|
};
|
|
}
|
|
|
|
/** A step's number, on its disc. */
|
|
const STEP = {
|
|
width: 24,
|
|
height: 24,
|
|
marginTop: 2,
|
|
borderRadius: 'var(--radius-full)',
|
|
backgroundColor: 'color-mix(in oklab, var(--primary) 10%, transparent)',
|
|
} as const
|
|
|
|
/** `wire` is the protocol sample, highlighted by the server page. */
|
|
const Integration = ({ wire }: { wire: ReactNode }) => {
|
|
return (
|
|
<YStack
|
|
render="section"
|
|
py={80}
|
|
px={16}
|
|
$sm={{ px: 24 }}
|
|
$lg={{ px: 32 }}
|
|
>
|
|
<YStack width="100%" maxW={1280} mx="auto">
|
|
<View
|
|
render={<motion.div initial={{ opacity: 0, y: 20 }} whileInView={{ opacity: 1, y: 0 }} viewport={{ once: true }} transition={{ duration: 0.5 }} />}
|
|
display="block"
|
|
mb={48}
|
|
$platform-web={{ textAlign: 'center' }}
|
|
>
|
|
<Title quiet mb={16}>
|
|
Three calls, then it is live
|
|
</Title>
|
|
<Lede maxW={768} mx="auto" mt="$3.5">
|
|
Mint a grant, spend it to open the stream, say what you want to hear about
|
|
</Lede>
|
|
</View>
|
|
|
|
<Grid columns={{ min: 420, max: 2 }} gap={40} items="center">
|
|
<motion.div
|
|
initial={{ opacity: 0, x: -20 }}
|
|
whileInView={{ opacity: 1, x: 0 }}
|
|
viewport={{ once: true }}
|
|
transition={{ duration: 0.5, delay: 0.2 }}
|
|
>
|
|
<Line render="h3" size="x2" weight="600" display="block" marginBottom={16}>The handshake, in full</Line>
|
|
<Line render="p" tone="soft" display="block" marginBottom={24}>
|
|
There is no hidden protocol here. A grant is minted on a normal
|
|
authenticated request, the stream spends it once, and the client
|
|
id that comes back is how you tell the server which collections
|
|
and records you want. The SDK does all three for you; the raw
|
|
calls are there if you would rather do it yourself.
|
|
</Line>
|
|
|
|
<YStack gap={16} mb={32}>
|
|
<XStack items="flex-start" gap={12}>
|
|
<XStack {...STEP} items="center" justify="center">
|
|
<Line size="sm" weight="700">1</Line>
|
|
</XStack>
|
|
<YStack flex={1} minW={0}>
|
|
<Line render="h4" weight="500" marginBottom={4}>Mint a grant</Line>
|
|
<Line render="p" size="sm" tone="muted">One authenticated request returns a string good for thirty seconds and exactly one stream</Line>
|
|
</YStack>
|
|
</XStack>
|
|
|
|
<XStack items="flex-start" gap={12}>
|
|
<XStack {...STEP} items="center" justify="center">
|
|
<Line size="sm" weight="700">2</Line>
|
|
</XStack>
|
|
<YStack flex={1} minW={0}>
|
|
<Line render="h4" weight="500" marginBottom={4}>Open the stream, name your topics</Line>
|
|
<Line render="p" size="sm" tone="muted">Spend the grant, take the client id it hands back, then post the collections and records you care about</Line>
|
|
</YStack>
|
|
</XStack>
|
|
|
|
<XStack items="flex-start" gap={12}>
|
|
<XStack {...STEP} items="center" justify="center">
|
|
<Line size="sm" weight="700">3</Line>
|
|
</XStack>
|
|
<YStack flex={1} minW={0}>
|
|
<Line render="h4" weight="500" marginBottom={4}>Write a record</Line>
|
|
<Line render="p" size="sm" tone="muted">Any create, update or delete reaches everyone watching whose rule lets them see it</Line>
|
|
</YStack>
|
|
</XStack>
|
|
</YStack>
|
|
|
|
<Action href={DOCS} fill>
|
|
View Documentation <ArrowRight width={16} height={16} />
|
|
</Action>
|
|
</motion.div>
|
|
|
|
<View
|
|
render={<motion.div initial={{ opacity: 0, y: 20 }} whileInView={{ opacity: 1, y: 0 }} viewport={{ once: true }} transition={{ duration: 0.5, delay: 0.3 }} />}
|
|
display="block"
|
|
p={24}
|
|
rounded="var(--radius-xl)"
|
|
borderWidth={1}
|
|
borderColor="var(--neutral-800)"
|
|
bg="var(--surface-card-quiet)"
|
|
>
|
|
<XStack items="center" gap={8} mb={16}>
|
|
<Glyph width={20} height={20} color="var(--foreground)" />
|
|
<Line tone="soft">The wire, without the SDK</Line>
|
|
</XStack>
|
|
|
|
<View maxH={400} overflowX="auto" overflowY="auto" rounded="var(--radius-lg)">
|
|
{wire}
|
|
</View>
|
|
</View>
|
|
</Grid>
|
|
</YStack>
|
|
</YStack>
|
|
);
|
|
};
|
|
|
|
export default Integration;
|