Go to file
Chris Wanstrath f643f8b2eb README+theme
2025-12-29 13:17:19 -08:00
examples README+theme 2025-12-29 13:17:19 -08:00
src FORGE 2025-12-29 12:21:58 -08:00
.gitignore FORGE 2025-12-29 12:21:58 -08:00
bun.lock FORGE 2025-12-29 12:21:58 -08:00
CLAUDE.md FORGE 2025-12-29 12:21:58 -08:00
package.json FORGE 2025-12-29 12:21:58 -08:00
README.md README+theme 2025-12-29 13:17:19 -08:00
server.tsx FORGE 2025-12-29 12:21:58 -08:00
tsconfig.json FORGE 2025-12-29 12:21:58 -08:00

⚒️ forge

╔═╝╔═║╔═║╔═╝╔═╝
╔═╝║ ║╔╔╝║ ║╔═╝
╝  ══╝╝ ╝══╝══╝

overview

Forge is a typed, local, variant-driven way to organize CSS, built around TSX.

css problems

  • Styles are global and open - anything can override anything anywhere.
  • No IDE-friendly link between the class name in markup and its definition.
  • All techniques are patterns a human must know and follow, not APIs.
  • Errors happen silently.

forge solutions

  • All styles are local to your TSX components.
  • Styles defined using TS typing.
  • Component styles are made up of independently styled "Parts".
  • "Variants" replace inline styles with typed, declarative parameters.
  • Style composition is deterministic.
  • Errors and feedback.

examples

import { define } from "forge"

export const Button = define("button", {
  base: "button",

  padding: 20,
  background: "blue",

  variants: {
    status: {
      danger: { background: "red" },
      warning: { background: "yellow" },
    }
  },
})

// Usage
<Button>Click me</Button>
<Button status="danger">Click me carefully</Button>
<Button status="warning">Click me?</Button>

export const Profile = define("div", {
  padding: 50,
  background: "red",

  parts: {
    Header: { display: "flex" },
    Avatar: { base: 'img', width: 50 },
    Bio: { color: "gray" },
  },

  variants: {
    size: {
      small: {
        parts: { Avatar: { width: 20 }}
      }
    }
  },

  render({ props, parts: { Root, Header, Avatar, Bio } }) {
    return (
      <Root>
        <Header>
          <Avatar src={props.pic} />
          <Bio>{props.bio}</Bio>
        </Header>
      </Root>
    )
  },
})

// Usage:
import { Profile } from './whatever'

<Profile pic={user.pic} bio={user.bio} />

see it

Check out the examples/ dir and view them at http://localhost:3300 by cloning this repo and running the local web server:

bun install
bun dev
open http://localhost:3300