Component library

Every component on this site is written in the dialect under site/app/ui/, styled with Tailwind classes. They are shared components: one source, compiled to Go on the server and to DOM instructions on the client, so they can appear in pages and in islands alike. The API deliberately looks like MUI / shadcn; the implementation is entirely its own.

Why not MUI
MUI is dynamic JS running on the React runtime (forwardRef, Emotion, spreading {...props}); it can't pass the subset check and can't compile to Go. A dialect library must be written in the dialect — just as AssemblyScript can't use npm packages directly.

Button

ui/Button.tsx · variant / size / href / disabled / onClick

As a link
usage
<Button>Primary</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="outline">Outline</Button>
<Button variant="ghost">Ghost</Button>
<Button size="sm">Small</Button>
<Button size="lg" href="/docs">As a link</Button>
ui/Button.tsx (excerpt): destructured defaults + a ternary choosing the element type
import type { Node } from "gotsx";

export default function Button({ variant = "primary", size = "md", href = "", onClick, children }: ButtonProps) {
  const cls = `inline-flex items-center rounded-lg font-medium ${sizeCls(size)} ${variantCls(variant)}`;
  return href !== ""
    ? <a href={href} class={cls}>{children}</a>
    : <button class={cls} onClick={onClick}>{children}</button>;
}

Use the same Button inside an island — its children are reactive text, prerendered by the server and taken over by the browser:

Badge

ui/Badge.tsx · color

Defaultbrandgreenamberred
usage
<Badge>Default</Badge>
<Badge color="brand">brand</Badge>
<Badge color="green">green</Badge>
<Badge color="amber">amber</Badge>
<Badge color="red">red</Badge>

Card / Stat / Callout

Three containers for server-side layout

Card

A container with an icon and title; children is any node.
30 µs
Stat: a number + a caption

Nested

Components nest arbitrarily
Callout
kind = info | tip | warn. What you're reading is one.

CodeBlock / CodeTabs

Highlighting is done by a tokenizer written in Go (host:hl); the dialect only renders spans

The server component CodeBlock calls the host directly; the island CodeTabs receives the token arrays the page tokenized on the server (props), so both sides only render — client code never touches Go.

<Button>Primary</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="outline">Outline</Button>
<Button variant="ghost">Ghost</Button>
<Button size="sm">Small</Button>
<Button size="lg" href="/docs">As a link</Button>

Accordion

islands/Accordion.client.tsx · items: { q, a }[]