ShadowJS is a fast, minimal JSX framework with fine-grained reactivity. It provides a modern, reactive programming model while maintaining excellent performance and a small bundle size.
- π― Fine-grained reactivity - Only re-render what changes
- β‘ Fast compilation - Built on SWC for optimal build performance
- π¨ JSX-first - Familiar React-like syntax with powerful extensions
- π¦ Small bundle - Minimal runtime with tree-shaking support
- π§ TypeScript ready - Full TypeScript support out of the box
| Package | Description |
|---|---|
@shadow-js/core |
Core reactivity + DOM runtime |
@shadow-js/compiler |
JSX transforms for reactive expressions |
@shadow-js/vite |
Vite plugin for seamless development |
npm create shadow-app my-app
cd my-app
npm install
npm run devnpm install @shadow-js/core @shadow-js/vitevite.config.ts
import { defineConfig } from "vite";
import shadow from "@shadow-js/vite";
export default defineConfig({
plugins: [shadow()],
});src/App.tsx
import { useStore, Show, For } from "@shadow-js/core";
function App() {
const [count, setCount] = useStore(0);
const [items, setItems] = useStore(["Shadow", "JS", "Reactivity"]);
return (
<div>
<h1>ShadowJS Counter</h1>
<button onClick={() => setCount((c) => c + 1)}>Count: {count()}</button>
<Show when={count() > 5} fallback={<p>Keep clicking!</p>}>
<p>π You reached {count()}!</p>
</Show>
<ul>
<For each={items()}>{(item) => <li>{item}</li>}</For>
</ul>
</div>
);
}import { useStore } from "@shadow-js/core";
function Counter() {
const [count, setCount] = useStore(0);
return <button onClick={setCount((c) => c + 1)}>{count()}</button>;
}import { Show } from "@shadow-js/core";
function UserStatus({ user }) {
return (
<Show when={user()} fallback={<div>Please log in</div>}>
<div>Welcome, {user().name}!</div>
</Show>
);
}import { For } from "@shadow-js/core";
function TodoList({ todos }) {
return (
<ul>
<For each={todos()}>{(todo, index) => <li>{todo.title}</li>}</For>
</ul>
);
}import { useEffect, onMount } from "@shadow-js/core";
function Timer() {
const [time, setTime] = useStore(new Date());
onMount(() => {
console.log("Component mounted");
});
const interval = setInterval(() => {
setTime(new Date());
}, 1000);
return <h1>Current time: {time().toLocaleTimeString()}</h1>;
}ShadowJS/
βββ packages/
β βββ core/ # Core framework
β β βββ src/
β β β βββ reactivity/ # Reactive system
β β β βββ runtime/ # DOM runtime & components
β β β βββ index.ts # Public API
β βββ compiler/ # JSX transformations
β βββ vite/ # Vite integration
βββ turbo.json # Build configuration
# Install dependencies
npm ci
# Build all packages
npm run build
# Type checking
npm run typecheck
# Linting
npm run lint
# Code formatting
npm run format
npm run format:check
# Create a changeset for release
npx changeset# Watch mode for a specific package
cd packages/core
npm run dev
# Test changes in playground
cd playground
npm run dev- API Reference - Complete API documentation
- Contributing - How to contribute to ShadowJS
We welcome any contributions! Please see our Contributing Guide for details.
- Fork the repository
- Create a feature branch:
git checkout -b feature/amazing-feature - Make your changes and add tests
- Run
npm run typecheck && npm run lint - Create a changeset:
npx changeset - Push your branch and create a Pull Request
MIT License - see LICENSE for details.
ShadowJS is inspired by modern reactive frameworks and aims to provide the best of both worlds: the familiarity of JSX with the performance of fine-grained reactivity.
Built by Jehaad AL-Johani using TypeScript, SWC, and modern web standards.