Show HN: Effect UI – PoC of a reactive UI framework built with Effect

4 hours ago 2

Effect UI is a declarative, reactive UI framework built on top of Effect TS and inspired by SolidJS. It provides fine-grained reactivity, dependency injection, and a fully Effect-driven component lifecycle with JSX support.

@m9tdev

  • Effect-First: All state, events, lifecycle, and side effects are managed via Effect
  • Fine-Grained Reactivity: DOM updates are precise and efficient using SubscriptionRef for reactive state
  • Type-Safety (🔜): Leverages TypeScript and Effect for robust, correct UIs with compile-time guarantees
  • Dependency Injection: Built-in support for Effect Context for service injection and theming
  • Developer Experience: Supports JSX for familiar, declarative UI authoring with custom JSX runtime
  • Reactive State: Uses SubscriptionRef for fine-grained reactive updates
  • Effect-based Components: Components are Effect computations that can access services and manage resources
  • Dependency Injection: Built-in Context support for themes, services, and configuration
  • Custom JSX Runtime: Tailored JSX implementation that works seamlessly with Effect
  • Hot Module Replacement: Development server with HMR powered by Bun
  • Full-Stack Ready: Includes both frontend framework and backend API routes

The core framework logic resides in the src/core directory, which contains the essential building blocks of Effect UI. The other files and folders primarily demonstrate how to use the framework in real-world applications.

effect-ui/ ├── package.json ├── tsconfig.json ├── bunfig.toml └── src/ ├── core/ # Framework Core │ ├── jsx-runtime.ts # Custom JSX implementation │ ├── jsx-dev-runtime.ts # JSX dev runtime │ ├── renderer.ts # Reactive rendering engine │ └── props.ts # Type utilities for reactive props ├── index.tsx # Development server with API routes ├── frontend.tsx # Frontend entry point ├── index.html # HTML template ├── index.css # Styles └── components/ # UI Components ├── App.tsx # Main application component ├── Counter.tsx # Reactive counter example ├── LabeledCounter.tsx # Counter with props ├── ThemeProvider.tsx # Theme context and provider └── ThemedButton.tsx # Component using dependency injection
  1. Install dependencies:

  2. Run the development server:

  3. Open your browser: Navigate to the URL shown in the terminal (typically http://localhost:3000)

A simple counter component:

import { Effect } from "effect"; import { ref, update } from "@/core/props"; export const Counter = () => Effect.gen(function* (_) { const count = yield* ref(_, 0); const increment = update(count, (n) => n + 1); return <button onClick={increment}>You clicked {count} times</button>; });

See src/components/App.tsx for an example of how to use the framework.

Effect-UI combines several powerful concepts:

  • Reactive Rendering: Uses Effect SubscriptionRef for automatic DOM updates when state changes
  • Effect-based Lifecycle: Components are Effect computations that can manage resources, handle errors, and access services
  • Context System: Built on Effect Context for dependency injection and service management
  • Custom JSX: Tailored JSX runtime that understands Effect computations and reactive values
  • Scoped Resources: Automatic cleanup of subscriptions and resources when components unmount

This project demonstrates how Effect can power a modern, reactive UI framework with fine-grained updates, dependency injection, and a declarative API. It showcases the potential for Effect to provide a robust foundation for frontend applications.

Read Entire Article