Samuel Hulla / Software engineer

Good software.
From the
inside out.

I build products, lead engineering teams, and turn the useful parts into open source. Based in Prague. Working everywhere.

While the dust settles

Let's stay in touch.

View my CVExperience, projects & what I do.

Open-source TypeScript / @hulla

HTTP contracts, live PostgreSQL views, and UI source you can edit.

Change a shared contract and see what breaks. Edit inventory and watch two views react. These are the packages I maintain, with working examples you can try before opening the docs.

@hulla/api

Rename a field. Find every broken consumer.

Your handler and your UI should agree on what comes back from an API. Change the shared contract below: TypeScript points to both places that need updating, before you send a request.

Edit any project file below, or load a breaking change with a shortcut.

Edit any file. TypeScript checks all three together.

Editable
TypeScript · Ready

Real TypeScript and @hulla/api declarations. Code is type-checked locally; no API request or AI agent runs.

@hulla/db

Buy in the app. Watch the database change.

Your app writes through the server; subscribed queries publish the committed result. Keep your own PostgreSQL database and let the client follow changes from either side.

Edit a table cell, rename a product in the app, or buy one. This workspace models the database and server locally.

Edit the table or the app. Both writes go through the server model.

Databaseproducts table
Servervalidate · commit · publish
Clientsubscribed storefront

products

Edit a name or stock level directly.

namestock

Committed revision 0

Storefront

Rename a product, or buy one to change stock.

5 available
2 available
Sold out

Subscribed to products.list · revision 0

Try setting the first row’s stock to 10, then buy one in the storefront.

Local model with separate client and database state connected by message ports. No PostgreSQL connection.

@hulla/style

An override should mean the same thing everywhere.

A variant builder and a class helper can quietly apply different merging rules. Give cn() and vn() the same processor, compose independent style maps, and carry one policy through every component.

Edit the styling code. Watch the three consumers and the composed class output follow.

Edit the source. One processor drives all three previews.

style.ts
Editable
import { style } from '@hulla/style'
import { cn as mergeClasses } from 'cn'

const { cn, vn } = style({ composer: mergeClasses })

const $tone = vn({
  accent: 'text-primary-text',
  muted: 'text-muted-foreground',
})
const $space = vn({ compact: ['px-2', 'px-4'] })

export const compose = (extra = '') =>
  cn('py-2', $tone('accent'), $space('compact'), extra)

export const preview = {
  notice: compose(),
  activity: compose('font-semibold'),
  cell: compose('px-6'),
}

export const trace = {
  variant: $space('compact'),
  override: compose('px-6'),
}

Live preview

Up to date

Notice

Your deployment is ready.

Activity

Production updated by Ada

Table cell · local px-6 override

Release v2.0 · healthy

variantpx-4

overridepy-2 text-primary-text px-6

Uses the installed @hulla/style package and this site’s CSS.

@hulla/ui

Change frameworks. Keep your component API.

A React app, a Solid app, and an Astro site can share the same tokens, variants, and interaction rules. Install the source into each project and make the implementation your own.

Use the shipped components below. Add a task or navigate the form with your keyboard.
Release checklist0 / 2 complete
  • Review the schema
  • Ship the release

Uses this site's shipped Solid components. Try adding tasks and moving through the form with your keyboard.

Parsing, failures, templates & source

The work around your application deserves better tools, too.

@hulla/control

Catch a bad deployment config before the next step runs.

Return typed success or failure values so callers can handle expected errors before transforming the result.

Read @hulla/control docs

Edit the config and see where the deployment stops.

deploy.json
Editable
{
  "replicas": 3
}

Deployment pipeline

  1. 1. Parse JSONOk
  2. 2. Validate configOk
  3. 3. Build deployment planOk

3 replicas ready for deployment

Runs @hulla/control locally. Thrown syntax errors and explicit validation failures both become results. Nothing is deployed.

@hulla/args

Reject --port nope before starting your preview server.

Parse flags, positionals, and nested commands into typed values, with Zod validation and access to the raw input.

Read @hulla/args docs

Type arguments for your preview command.

Ready to start storefront

Parsed arguments
Generated output
{
  "project": "storefront",
  "port": 8080,
  "open": true
}

The supplied port is a number. Original input: --port 8080.

Runs @hulla/args + Zod. Space-separated tokens; no shell quoting or server startup.

@hulla/gittar

One template repository. As many editable starters as you need.

Copy a repository folder into a starter project, with a separate cache and an explicit refresh policy.

Read @hulla/gittar docs

Edit options for the local acme/starters template.

download.options.json
Editable
{
  "subpath": "web",
  "update": "never",
  "outDir": "./project-1"
}

Cache: 0 simulated downloads · full web/ + api/ snapshot

Copy a starter, change its title, then use a new destination. The next copy starts from the unchanged cache.

Local filesystem model; no downloads or files written. Reusing a destination replaces that copy, as a real copy operation would.

hulla CLI

Need to change the component? Open the source in your app.

Copy UI components into your project as editable source, then review updates through the same CLI.

Read hulla CLI docs

Edit the command to change the install plan.

Terminal
Editable
hulla ui add --framework astro button
Source entering your repository
Generated output
src/components/button/button.astro
src/components/button/button-group.astro

Install preview for button and dialog using default project paths. Registry support files are additional. No CLI command is run or files written.