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.

contract.tsEditable
import { defineContract, route, response } from '@hulla/api'

export const contract = defineContract({
  routes: {
    profile: route.get('/profile', {
      responses: {
        200: response.json<{ name: string }>(),
      },
    }),
  },
})

TypeScript

Ready

Rename name in the response type, or use the shortcut. The handler and caller will need to follow.

    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.tsEditable
    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.jsonEditable
    {
      "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 argumentsGenerated 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.jsonEditable
    {
      "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.

    TerminalEditable
    hulla ui add --framework astro button
    Source entering your repositoryGenerated 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.