Go to file
2025-12-27 21:14:58 -08:00
examples big stuff 2025-12-27 21:14:58 -08:00
src big stuff 2025-12-27 21:14:58 -08:00
.gitignore FORGE 2025-12-26 19:11:01 -08:00
bun.lock FORGE 2025-12-26 19:11:01 -08:00
CLAUDE.md claude 2025-12-26 22:22:08 -08:00
package.json big stuff 2025-12-27 21:14:58 -08:00
README.md update 2025-12-26 22:22:12 -08:00
server.tsx big stuff 2025-12-27 21:14:58 -08:00
tsconfig.json big stuff 2025-12-27 21:14:58 -08:00

Forge

Why Forge?

CSS is powerful, but hostile to humans at scale.

Problems with CSS

  • Styles are global and open — anything can override anything.
  • Theres no link between a class in markup and its definition.
  • Inline styles exist because theres no structured way to vary styles per instance.
  • Overrides are silent — conflicts happen without feedback.
  • Complex components require selector gymnastics and reach-in styling.

What Forge Does Instead

  • Styles are local to components and attached by generated handles, not strings.
  • Parts give components named sub-targets without selectors.
  • Variants replace inline styles with typed, declarative parameters.
  • Style composition is deterministic (known merge order, last-wins).
  • Overlapping changes are warned about in dev, not silently ignored.

What Forge Is

  • A typed, local, variant-driven way to author CSS.
  • A system that optimizes for people typing at a keyboard, not selectors in a cascade.

What Forge Is Not

  • Not a new component model.
  • Not a new language.
  • Not a CSS replacement — it compiles to CSS, but removes the chaos.

Example:

import { define } from "forge"

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

  padding: 20,
  background: "blue",

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

// Usage
<Button>Click me</Button>
<Button kind="danger">Click me carefully</Button>
<Button kind="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} />