Stop rewriting the same components.
kraft-ui is a typed component library for Go, Templ, HTMX, and Tailwind CSS. Every component is a Go struct with typed props, consistent design, and zero JavaScript dependencies.
An input field with a label and an error.
Something you write on every form page. Here is the difference.
<div class="flex flex-col gap-1.5">
<label class="text-sm font-medium text-text-primary">
Email
</label>
<input
type="email"
placeholder="you@example.com"
class="rounded-md border border-error-500
px-3 py-2 text-sm bg-surface
text-text-primary
placeholder:text-text-muted
focus:outline-none focus:ring-2
focus:ring-error-500
focus:border-error-500
transition-colors"
/>
<p class="text-xs text-error-600">
Invalid email address
</p>
</div>
<!-- Repeat this. On every form field.
Every dev on your team does it
differently. -->@input.Input(input.Props{
Type: "email",
Label: "Email",
Error: "Invalid email address",
})
// Same markup. Same styles.
// Consistent across every field.
// IDE guides you through every prop.
// One place to update when design changes.11 fewer lines. But that is not the real win.
The real win is that every developer on your team writes it the same way. No one argues about class order. No one forgets the error state. No one uses a different focus ring on a different page. When the design changes, you update one file.
1
source of truth
0
class debates
A button that triggers an HTMX request.
Raw Tailwind means memorising 10+ utility classes for every button state. kraft-ui handles the styles. You handle the logic.
<button
type="button"
class="inline-flex items-center justify-center
gap-2 rounded-md px-4 py-2
text-sm font-medium
bg-brand-500 text-white
hover:bg-brand-600 active:bg-brand-700
focus:outline-none focus:ring-2
focus:ring-brand-500 focus:ring-offset-2
disabled:opacity-50
disabled:cursor-not-allowed
transition-colors"
hx-post="/api/save"
hx-target="#result"
>
Save changes
</button>@button.Button(button.Props{
Variant: button.VariantPrimary,
Attrs: templ.Attributes{
"hx-post": "/api/save",
"hx-target": "#result",
},
}) { Save changes }
// Every hx-* attribute works.
// Disabled state, loading state,
// sizes, variants — all typed.Pass any hx-*, data-*, or x-* attribute via templ.Attributes. The components are built for the full GOTH stack from day one.
Typed props, always
Every component takes a Go struct. Your IDE autocompletes variants, sizes, and states. No class strings to memorise or typo.
HTMX-first design
Pass any hx-* attribute via templ.Attributes. Components are built for server-driven interactions from the start.
Own your code
Use as a Go module or copy components directly into your project. No black box. MIT licensed. Readable source.
See what you get
Buttons
Badges and Alerts
Info
Done
Warning
Card and Inputs
Typed components
Consistent design across your whole app.
Update one component, every instance in the app reflects the change.
We never share your email.
Too short