An open API service indexing awesome lists of open source software.

https://github.com/minimact/minimact

Minimact is a lightweight, server-first reactive UI framework that compiles TSX into C#, predicts DOM changes with Rust, and syncs state in real time via SignalR β€” all while letting you write components with familiar hooks like useState and useEffect.
https://github.com/minimact/minimact

client-side-stored-procedures dom-patching posthydrationist predictive-rendering reactive rust-reconciliation server-side-react virtual-dom

Last synced: 20 days ago
JSON representation

Minimact is a lightweight, server-first reactive UI framework that compiles TSX into C#, predicts DOM changes with Rust, and syncs state in real time via SignalR β€” all while letting you write components with familiar hooks like useState and useEffect.

Awesome Lists containing this project

README

          


Minimact Logo

Minimact


The Posthydrationist Framework


Server-first React with zero hydration, predictive patches, and Rust-powered performance for ASP.NET Core.


The cactus doesn't hydrate β€” it stores. 🌡


Documentation
Netlify Status
License: MIT
Rust
.NET
SignalR
TypeScript

They’re treading water in a sea of hydration, clinging to their VDOM life vests while Minimact is out here desert-gliding on predictive patches like some kind of reactive dune worm🌡
Seriously thoughβ€”client hydration has become the default religion in web dev, and not because it's ideal. It’s just familiar. You’re tossing a wrench (made of Rust, no less πŸ¦€) into that belief system and saying:
β€œWhat if we didn’t need to hydrate anything at all because we already know what’s going to happen?”


Minimact brings the familiar React developer experience to server-side rendering with ASP.NET Core, powered by a Rust reconciliation engine and intelligent predictive updates.

---

## πŸ“š Quick Nav

πŸš€ [Quick Start](#quick-start) β€’
πŸ’‘ [Why Minimact?](#why-minimact) β€’
🧠 [Core Innovations](#core-innovations) β€’
🌐 [SPA Mode](#-single-page-application-spa-mode) β€’
🌳 [Lifted State](#-lifted-state-components) β€’
πŸͺ [Custom Hooks](#-custom-hooks-hooks-as-components) β€’
πŸ” [Protected State](#-useprotectedstate) β€’
🎨 [Swig IDE](#-minimact-swig---desktop-ide-for-minimact) β€’
πŸ—οΈ [Architecture](#architecture-overview) β€’
πŸ“Š [Comparison](#comparison) β€’
πŸ§ͺ [Examples](#examples)

---

## What is Minimact?

**Write React. Render on the server. Update instantly with predictive patches.**

```typescript
import { useState } from '@minimact/core';

export function Counter() {
const [count, setCount] = useState(0);

return (
setCount(count + 1)}>
Count: {count}

);
}
```

**That's it.** Write familiar React code, get server-rendered HTML with 2-3ms perceived latency.

> **The cactus doesn't hydrate β€” it stores.** 🌡

## How It Works (in 5 seconds)

```
User clicks β†’
[Browser checks prediction cache] β†’
βœ… Patch found β†’
⏱️ 2ms DOM update β†’
πŸš€ Server verified in background
```

**No hydration. No diffing. Just pure speed.**

---

## 🧩 The Minimact Principle

```
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ DECLARATIVE UI β”‚
β”‚ ↓ β”‚
β”‚ Exposes structure (JSX makes tree explicit) β”‚
β”‚ Exposes state (useState makes slots explicit) β”‚
β”‚ ↓ β”‚
β”‚ DETERMINISTIC UI β”‚
β”‚ ↓ β”‚
β”‚ Same state β†’ Same output (pure function) β”‚
β”‚ Finite states β†’ Enumerable space β”‚
β”‚ ↓ β”‚
β”‚ PREDICTIVE UI β”‚
β”‚ ↓ β”‚
β”‚ Pre-compute all outputs (build-time analysis) β”‚
β”‚ Runtime becomes lookup (0-2ms) β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
```

**The progression is INEVITABLE once you recognize:**
```
Declarative β†’ Structure
Structure β†’ Determinism
Determinism β†’ Pre-computability
```

React stopped at declarative. Minimact took it all the way to predictive.

---

## 🧩 Minimact: Problem-Solution Matrix

| ❌ Problem | βœ… Minimact's Solution | πŸ§ͺ How It Works | 🧠 Why Others Struggle |
|-----------|----------------------|-----------------|----------------------|
| **1. Hydration Slowness** | No hydration at all 🌡 | Predictive patches render instantly | React/Next.js re-hydrates entire DOM; costly |
| **2. Prop Drilling Hell** | Lifted State Components | Auto-lifted state with full tree access | React/Redux requires boilerplate or context abuse |
| **3. Client-side Logic Leaks** | Server-first execution | All logic runs server-side unless specified | CSR frameworks must expose logic to client |
| **4. Slow First Interaction** | ~2ms latency on first click | Precomputed patches + cache | SSR/CSR require JS boot or roundtrips |
| **5. State Loss on Hot Reload** | State survives reloads πŸ”₯ | Hex Paths + Lifted State mapping | React Fast Refresh loses local state |
| **6. Global State Bloat** | Localized, queryable state | Scoped lifted state, useProtectedState | Redux/Zustand/global context leaks over time |
| **7. Razor Lock-in for .NET Devs** | Full React DX with C# backend | TSX transpiled β†’ C# | Blazor forces Razor syntax, slow to adopt |
| **8. DX Disconnect Between Frontend/Backend** | TS ↔ C# type safety | Shared schema + transpilation | API routes are brittle and disjointed |
| **9. Flicker from DOM Rewrites** | Targeted micro-patches | Hex path diffing + VNull nodes | HTMX, traditional SSR re-render full nodes |
| **10. Debugging React State Is Opaque** | Visual state tree in Swig IDE | SignalR-backed live state inspector | React DevTools doesn't show prop origins or server state |
| **11. Complex Interop Between MVC + React** | Drop-in MVC embedding | MVC Controllers β†’ ViewModels β†’ React | React + MVC usually fight each other |
| **12. Large Bundle Sizes** | 12.0 KB runtime ⚑ | Minimal SignalM WebSocket client | React 45KB+, Vue 34KB+, Blazor ~300KB |
| **13. Untrackable Component Drift** | Predictive metrics in real-time | Hit rate, rollback %, false positives | Most frameworks don't measure this at all |
| **14. CSS/DOM State Blindness** | DOM as reactive source | useDomElementState() (80+ props) | React treats DOM as opaque output |
| **15. Developer Setup Time** | 2-minute setup w/ Swig | Desktop IDE w/ hot reload, TSX editor | Next.js/Blazor setups often slow and brittle |
| **16. Poor Offline Support** | Cached patches, local state | Prediction-first runtime | SSR apps break offline, HTMX needs server |
| **17. Dev/Prod Divergence** | Single runtime model | Same prediction engine used in both | Many frameworks do hydration/dev tricks |
| **18. No Secure Way to Hide Internal State** | useProtectedState() πŸ”’ | Cannot be accessed by parents/devtools | Most state is inspectable if global/lifted |
| **19. Inconsistent Re-rendering from Conditions** | VNull conditional representation | Structural placeholders for predictability | React reconciler shifts indices, leading to bugs |
| **20. Implicit DOM identity issues** | Stable Hex Paths | Elements never re-identified | Key/index bugs in React are common |

---

## ✨ Why Minimact?

Traditional UI frameworks like React must reconcile every state change on the client, leading to CPU overhead and slower interactions β€” especially on low-end devices or in high-frequency apps.

**Minimact flips the model:**
- You write UI in **TSX/JSX**
- Minimact compiles it to **C# classes**
- C# renders the HTML on the server
- A **Rust engine predicts state changes** and pre-sends patches to the client
- Client caches predicted patches **before user interaction**
- User clicks β†’ **Client applies cached patch instantly (0ms network latency)**
- **SignalR verifies in background** and corrects only if needed
- **No diffing, no runtime VDOM, zero client reconciliation**

### For React Developers
- βœ… **Familiar syntax** - Write JSX/TSX like you always have
- βœ… **React hooks** - `useState`, `useEffect`, `useRef`, plus powerful semantic hooks
- βœ… **No hydration** - No client-side JavaScript frameworks to load
- βœ… **Instant feedback** - Hybrid client/server state for optimal UX

### For .NET Developers
- βœ… **ASP.NET Core integration** - Use EF Core, dependency injection, and your favorite .NET tools
- βœ… **Type safety** - Full TypeScript β†’ C# type inference
- βœ… **Secure by default** - Business logic stays on the server
- βœ… **Easy deployment** - Standard ASP.NET Core hosting
- βœ… **Performance:** 2-3ms interactions vs 47ms traditional SSR

### For End Users
- βœ… **Fast initial load** - 12.0 KB client (73% smaller than React)
- βœ… **Instant interactions** - Predictive updates feel native
- βœ… **Works without JS** - Progressive enhancement built-in
- βœ… **Low bandwidth** - Only patches sent over the wire

### For CTOs
**Solve the "React DX + .NET backend" problem.** One stack, one deployment, full type safety from database to DOM. Rust-powered performance makes ASP.NET Core shine.

**Comparison:**
- React 18: 45 KB gzipped
- Vue 3: 34 KB gzipped
- **Minimact: 12.0 KB gzipped** (73% smaller than React)

---

## πŸ€” Why React Critics Were Right (Without Knowing Why)

Many developers felt React was overcomplicated β€” they just couldn't articulate it:

> *"Re-rendering seems wasteful."*
> *"Virtual DOM feels unnecessary."*
> *"It's declarative, but... heavy."*

Here's what they were sensing:

**🧭 JSX + useState = a finite state automaton.**

- Every `useState` creates a known state space.
- JSX describes a static view for each state.

That means:
- βœ… You can precompute all transitions.
- 🚫 You don't need runtime diffing or reconciliation.

**But React built a ship β€” Virtual DOM β€” to navigate a path that could have been walked directly with precomputed patches.**

Minimact is that direct path:

- **No hydration**
- **No reconciliation**
- **Finite state β†’ Predictive patches β†’ Instant updates (2–3ms)**

**React gave you the compass. Minimact teaches you how to use it.**

---

### Better Than Blazor
Blazor requires learning Razor syntax. Minimact uses React β€” the syntax millions of developers already know. Lower barrier, faster adoption, bigger talent pool.

### SSR vs CSR vs Minimact

| Feature | React (CSR) | Next.js (SSR) | Minimact (Prediction) |
|---------|-------------|---------------|----------------------|
| **First Paint** | ⚠️ Depends on JS | βœ… Fast | βœ… Fast |
| **Interactivity** | βœ… JS required | ⚠️ Re-hydration | βœ… Instant (2-3ms) |
| **State Sync** | πŸ”„ Manual | πŸ”„ Manual | βœ… Auto |
| **Bundle Size** | ~45 KB | ~45 KB | **12.0 KB** |
| **Server Logic** | ❌ None | ⚠️ API routes | βœ… Native C# |
| **Offline Friendly** | βœ… Yes | ⚠️ Partial | ⚠️ Prediction-only |

### Key Benefits
- ⚑ **2-3ms interactions** - Predictive patches cached before user clicks
- πŸ“¦ **12.0 KB bundle** - 73% smaller than React
- πŸ—οΈ **Familiar syntax** - Write JSX/TSX with React hooks
- πŸ” **Secure by default** - Business logic stays on server
- πŸš€ **15Γ— faster** than traditional SSR on 3G networks

---

## Quick Start

**Minimact uses the familiar ASP.NET MVC pattern as the default architecture.** Controllers pass ViewModels to React components - zero learning curve for .NET developers.

### The Standard Pattern (MVC Bridge)

**1. Controller (C#) - Familiar MVC**
```csharp
public class ProductsController : ControllerBase
{
[HttpGet("{id}")]
public async Task Details(int id)
{
var viewModel = new ProductViewModel
{
ProductName = product.Name, // Immutable (server authority)
Price = product.Price, // Immutable (server authority)
InitialQuantity = 1 // [Mutable] (client can change)
};

return await _renderer.RenderPage(viewModel);
}
}
```

**2. Component (TSX) - Mix MVC State + Client State**
```typescript
import { useMvcState, useMvcViewModel } from '@minimact/mvc';
import { useState } from '@minimact/core';

interface ProductViewModel {
productName: string;
price: number;
isAdminRole: boolean;
initialQuantity: number; // [Mutable] in C#
}

export function ProductPage() {
// From ViewModel (server-controlled)
const [productName] = useMvcState('productName'); // Immutable
const [price] = useMvcState('price'); // Immutable
const [isAdmin] = useMvcState('isAdminRole'); // Immutable
const [quantity, setQuantity] = useMvcState('initialQuantity'); // Mutable

// Pure client state (never sent to server)
const [cartTotal, setCartTotal] = useState(0);
const [showDetails, setShowDetails] = useState(false);

const handleAddToCart = () => {
setCartTotal(price * quantity); // Client-only calculation
};

return (


{productName}


${price.toFixed(2)}

setQuantity(quantity + 1)}>
Quantity: {quantity}


Add to Cart - ${cartTotal.toFixed(2)}

{/* Server-controlled visibility */}
{isAdmin && Edit Product}

{/* Client-controlled visibility */}
setShowDetails(!showDetails)}>
{showDetails ? 'Hide' : 'Show'} Details


);
}
```

**That's it!** Standard MVC Controllers + React Components + Instant Updates (2-3ms).

**Key Pattern:**
- `useMvcState` β†’ Bound to ViewModel property (from controller)
- `useState` β†’ Component-owned state (not from ViewModel)
- **Both sync to server** for accurate rendering and prediction

---

## πŸš€ Single Page Application (SPA) Mode

**Minimact SPA combines server-side rendering with client-side navigation for instant page transitions (10-50ms) while keeping layouts mounted.**

### What is Minimact SPA?

Traditional SPAs (React Router, Next.js) re-mount the entire app on navigation. Minimact SPA keeps your shell (header, sidebar, footer) **persistent** and only swaps the page content.

**Key Features:**
- ⚑ **10-50ms navigation** - Via SignalR, not HTTP
- 🎯 **Shell persistence** - Layouts stay mounted across navigation
- 🎨 **Server-driven routing** - Controllers decide which page to render
- πŸ“¦ **12.5 KB bundle** - `@minimact/spa` package
- πŸ”„ **Browser history support** - Back/forward buttons work seamlessly

### Quick Start with SPA Template

```bash
# Create SPA project
swig new SPA MySpaApp

# The template includes:
# - Controllers/HomeController.cs & ProductsController.cs
# - ViewModels/HomeViewModel.cs & ProductViewModel.cs
# - Shells/MainShell.tsx (persistent layout with )
# - Pages/HomePage.tsx & ProductDetailsPage.tsx
# - Auto-installed @minimact/spa module

cd MySpaApp
swig watch # Auto-transpile
swig run # Launch app
```

### How It Works

**1. Shell Component** - Persistent layout with navigation:
```tsx
import { Page, Link } from '@minimact/spa';
import { useMvcState } from '@minimact/mvc';

export default function MainShell() {
const [appName] = useMvcState('__ShellData.AppName');
const [userName] = useMvcState('__ShellData.UserName');

return (



{appName}


Welcome, {userName}!


Home
Product 1
Product 2


{/* Pages inject here */}

Β© 2025 My App


);
}
```

**2. Controller** - Returns ViewModel with shell metadata:
```csharp
[ApiController]
[Route("products")]
public class ProductsController : ControllerBase
{
[HttpGet("{id}")]
public IActionResult Details(int id)
{
var viewModel = new ProductViewModel
{
ProductId = id,
ProductName = "Widget",
Price = 99.99m,

// Shell metadata
__Shell = "Main", // Which shell to use
__ShellData = new // Data for shell
{
AppName = "My SPA App",
UserName = "Demo User"
},
__PageTitle = "Product Details"
};

return Ok(viewModel); // ✨ Auto-extracted by SPARouteHandler
}
}
```

**3. Page Component** - Rendered inside shell:
```tsx
import { useMvcState, useState } from '@minimact/mvc';
import { Link } from '@minimact/spa';

export default function ProductDetailsPage() {
const [productName] = useMvcState('ProductName');
const [price] = useMvcState('Price');
const [quantity, setQuantity] = useState(1);

return (


← Back to Home

{productName}


${price}

setQuantity(quantity + 1)}>
Quantity: {quantity}

Next Product


);
}
```

### The Navigation Flow

```
User clicks
↓
Client: SignalR.invoke('NavigateTo', '/products/2')
↓
Server:
- Routes to ProductsController.Details(2)
- Extracts ViewModel
- Same shell? β†’ Render page only
- Different shell? β†’ Render shell + page
- Rust reconciler computes patches
↓
Client: Apply patches (10-50ms!)
↓
Browser: URL updated via history.pushState
↓
Done! Shell stayed mounted ✨
```

### Performance Comparison

| Scenario | Traditional SPA | Minimact SPA |
|----------|----------------|--------------|
| **Same Layout Navigation** | 100-200ms (re-mount) | **10-50ms** (shell persists) βœ… |
| **Different Layout** | 100-200ms (re-mount) | 20-100ms (still faster) |
| **Full Page Reload** | 200-500ms | 200-500ms (same) |
| **Initial Load** | 200-500ms | 200-500ms (same) |

**Why so fast?**
- βœ… No JavaScript bundle parsing (already loaded)
- βœ… No React reconciliation (Rust does it server-side)
- βœ… Only DOM patches sent (not full HTML)
- βœ… **Shell stays mounted** (no layout re-render)
- βœ… SignalR WebSocket (no HTTP overhead)

### Setup (Program.cs)

```csharp
var builder = WebApplication.CreateBuilder(args);

builder.Services.AddMinimact();
builder.Services.AddMinimactMvcBridge();
builder.Services.AddMinimactSPA(); // ✨ Enable SPA support

builder.Services.AddControllersWithViews();
builder.Services.AddSignalR();

var app = builder.Build();

app.UseStaticFiles();

// Serve mact_modules for @minimact/spa
app.UseStaticFiles(new StaticFileOptions
{
FileProvider = new PhysicalFileProvider(
Path.Combine(app.Environment.ContentRootPath, "mact_modules")),
RequestPath = "/mact_modules"
});

app.UseMinimact(); // Auto-discovers shells and pages
app.MapControllers();
app.MapHub("/minimact");

app.Run();
```

### Advanced Features

**Multiple Shells:**
```csharp
// Admin pages use AdminShell
if (User.IsInRole("Admin"))
viewModel.__Shell = "Admin";

// Public pages use PublicShell
else
viewModel.__Shell = "Public";
```

**No Shell (Page-Only):**
```csharp
// Landing pages, login screens
viewModel.__Shell = null; // No shell layout
```

**Conditional Rendering Based on Shell:**
```tsx
export default function ProductPage() {
const [shell] = useMvcState('__Shell');

if (shell === 'Admin') {
return ;
}

return ;
}
```

**Prefetching (Optimize for Predicted Navigation):**
```tsx

View Product

```

### Benefits

βœ… **10-50ms navigation** - Feels like a native app
βœ… **Shell persistence** - Sidebars, headers stay mounted
βœ… **Server-driven routing** - Controllers decide pages
βœ… **Auto-discovery** - Shells and pages automatically registered
βœ… **Browser history** - Back/forward buttons work
βœ… **Type-safe** - TypeScript β†’ C# type inference
βœ… **Zero configuration** - Just `return Ok(viewModel)`

**[πŸ“± Complete SPA Guide β†’](./docs/SPA_IMPLEMENTATION_COMPLETE.md)**

### Using Minimact Swig IDE

```bash
# Clone and run Swig - the official Minimact IDE
git clone https://github.com/minimact/swig
cd swig
npm install
npm start
```

Once Swig launches:

1. **Create Project** - Click "New Project" and choose a directory
2. **Edit Components** - Write TSX in Monaco editor (auto-transpiles to C#)
3. **Build** - Click "Build" to compile your app
4. **Run** - Click "Run" and open in browser

From zero to running app in under 2 minutes.

**Modular runtime architecture:**
- `@minimact/core` β€” **12.0 KB gzipped** (Core runtime with SignalM WebSocket)
- `@minimact/core/r` β€” **23.94 KB gzipped** (Core runtime with full SignalR + fallbacks)
- `@minimact/core/hot-reload` β€” **+5.15 KB** (Hot reload for development)
- `@minimact/core/playground` β€” **+376 B** (Swig IDE integration)
- `@minimact/core/power` β€” **+5.37 KB** (Advanced features: useServerTask, useComputed, usePaginatedServerTask, etc.)

**πŸ“¦ Real-world examples:**
- [βœ… TodoMVC](./examples/todo) - Classic todo app
- [πŸ“Š Dashboard](./examples/dashboard) - Admin dashboard with templates
- [πŸ“ Blog](./examples/blog) - Markdown blog with EF Core
- [πŸ“‹ Forms](./examples/forms) - Validation and semantic hooks

**[πŸ“š Full Getting Started Guide β†’](./docs/getting-started.md)**

---

## Why You'll Love Minimact

🧠 **React syntax, C# backend** β€” No Razor needed
⚑ **Instant interactions** β€” <3ms click-to-DOM
🌡 **No hydration** β€” Predictive updates instead
πŸ› οΈ **Desktop IDE** with live state + TSX editing
🧬 **Full state tree visibility** β€” Perfect prediction
πŸ” **Secure by default** β€” Logic runs server-side
πŸ“¦ **73% smaller** than React (12.0 KB vs 45 KB)
πŸ”Œ **Modular architecture** β€” Import only what you need
πŸ”₯ **Plugin system** via NuGet packages

---

## πŸ“¦ Modular Architecture - Import Only What You Need

Minimact's modular design means you only ship code your app actually uses:

### **Core Package (12.0 KB)**
```typescript
import { Minimact, useState, useEffect, useRef } from '@minimact/core';
```
Essential hooks and runtime - perfect for most apps.

### **Power Features (+5.37 KB)**
```typescript
import { useServerTask, useComputed, usePaginatedServerTask } from '@minimact/core/power';
```
Advanced features for complex apps:
- `useServerTask` - Execute async tasks on server
- `useServerReducer` - Redux-like state management
- `usePaginatedServerTask` - Built-in pagination
- `useComputed` - Client-side computation with browser APIs
- `usePub`, `useSub` - Pub/Sub messaging
- `useSignalR` - Direct SignalR access
- `useContext` - Context API for shared state
- `useMarkdown` - Render markdown
- Task scheduling hooks

### **Development Tools**
```typescript
// Enable hot reload in development
import { enableHotReload } from '@minimact/core/hot-reload'; // +5.15 KB
if (import.meta.env.DEV) {
enableHotReload();
}

// Playground bridge for Swig IDE
import { PlaygroundBridge } from '@minimact/core/playground'; // +376 B
```
Auto tree-shaken in production builds via bundler!

### **Example: Simple App**
```typescript
// Just the essentials - 12.0 KB
import { useState } from '@minimact/core';

export function Counter() {
const [count, setCount] = useState(0);
return setCount(count + 1)}>Count: {count};
}
```

### **Example: Complex App with Pagination**
```typescript
// Core + power features - 17.4 KB total
import { useState, useEffect } from '@minimact/core';
import { usePaginatedServerTask, useComputed } from '@minimact/core/power';

export function DataGrid() {
const [page, setPage] = useState(1);
const data = usePaginatedServerTask('/api/data', { page });
return

{/* Render paginated data */}
;
}
```

**Why This Matters:**
- βœ… Most apps use **12.0 KB** (just core)
- βœ… Complex apps add **+5.37 KB** (still smaller than competitors)
- βœ… Dev tools **auto tree-shake** in production
- βœ… No bundle bloat from unused features

---

## πŸ“¦ Zero-Config Module Management with Swig CLI

Minimact includes a **zero-config module system** for managing client-side dependencies. No CDN links, no manual script tags, no build configuration - just simple CLI commands.

### Quick Start

```bash
# Initialize modules with interactive selection
swig init

# Or install specific modules
swig import lodash
swig import @minimact/power

# List installed modules
swig list

# Update modules
swig update --all

# Remove a module
swig uninstall lodash
```

### How It Works

1. **Global Cache** - Modules download to AppData (like Swig GUI installation)
2. **Project Copy** - Copies from cache to your project's `mact_modules/`
3. **Auto-Serve** - ASP.NET Core automatically serves and includes modules
4. **Smart Control** - Use `[ModuleInfo]` attribute to optimize per-component

**Example - All modules auto-included:**
```csharp
public class MyDashboard : MinimactComponent
{
// All mact_modules/ automatically included
}
```

**Example - Opt-out for performance:**
```csharp
[ModuleInfo(OptOut = true)]
public class LandingPage : MinimactComponent
{
// Core only (12 KB), no extra modules
}
```

**Example - Selective inclusion:**
```csharp
[ModuleInfo(Include = new[] { "@minimact/power", "lodash" })]
public class DataProcessorPage : MinimactComponent
{
// Only power and lodash included
}
```

### Available Modules

**Minimact Modules:**
- `@minimact/power` - Advanced features (useServerTask, useComputed, etc.)
- `@minimact/mvc` - MVC Bridge (useMvcState, useMvcViewModel)
- `@minimact/spa` - Single Page Application (instant navigation, shell persistence)
- `@minimact/punch` - DOM state tracking (useDomElementState)
- `@minimact/md` - Markdown rendering (useMarkdown)

**External Libraries:**
- `lodash` - Utility library (24 KB)
- `moment` / `dayjs` - Date manipulation
- `axios` - HTTP client
- `chart.js` - Charting library
- ...and any npm package with a browser bundle!

### Benefits

βœ… **Zero Configuration** - No webpack, no bundlers, pure simplicity
βœ… **Offline-First** - Global cache means fast installs after first download
βœ… **Version Control Friendly** - Check in `mact_modules/` to Git
βœ… **NPM-Powered** - Uses `npm install` under the hood
βœ… **Automatic Integration** - ASP.NET Core auto-scans and serves modules

**[πŸ“¦ Complete Module Management Guide β†’](./docs/SWIG_CLI_MODULES_GUIDE.md)**

---

## Core Innovations

### 🎯 Template Prediction System
Pre-computed parameterized patches for 100% state coverage:

```typescript
// First interaction: Extracts template "Count: {0}"
// All future clicks: Instant update with any value
Count: {count}
```

**Benefits:**
- βœ… 100% coverage from first render (zero cold start)
- βœ… 98% memory reduction vs cached predictions
- βœ… Babel extracts templates at build time
- βœ… Works with loops, conditionals, expressions

**[πŸ“ Template System Details β†’](./docs/TEMPLATE_PATCH_SYSTEM.md)**

---

### 🌳 Lifted State Components
All child state automatically lives in parent. Zero prop drilling:

```
Dashboard
└── UserProfile (Component)
β”œβ”€β”€ isEditing (lifted βœ… visible)
β”œβ”€β”€ username (lifted βœ… visible)
└── cache (lifted πŸ”’ protected)

Access: state["UserProfile.isEditing"]
```

```typescript
// Parent sees ALL child state
function Dashboard() {
const isEditing = state["UserProfile.isEditing"]; // Just read it!

return (



);
}

// Child accesses seamlessly
function UserProfile() {
const isEditing = state.isEditing; // Auto-prefixed
setState('isEditing', true); // Updates parent!
}
```

**Benefits:**
- βœ… Zero prop drilling, no callbacks
- βœ… Parent can observe/control any child state
- βœ… Perfect prediction (full state tree visible)
- βœ… Hot reload preserves state

**[🌳 Lifted State Guide β†’](./docs/LIFTED_STATE_COMPONENT_SYSTEM.md)**

---

### πŸͺ Custom Hooks (Hooks as Components)
Create reusable stateful logic with UI - hooks return both values AND JSX:

```typescript
// Define a hook (note the required namespace parameter!)
function useCounter(namespace: string, start: number = 0) {
const [count, setCount] = useState(start);

const increment = () => setCount(count + 1);
const decrement = () => setCount(count - 1);
const reset = () => setCount(start);

// Hooks can return JSX! (unlike React)
const ui = (


-
{count}
+
Reset

);

return [count, increment, decrement, reset, ui];
}

// Use the hook with multiple independent instances
function Dashboard() {
const [count1, increment1, , , counterUI1] = useCounter('counter1', 0);
const [count2, increment2, , , counterUI2] = useCounter('counter2', 10);

return (


Counter 1: {count1}


External +1
{counterUI1}

Counter 2: {count2}


External +1
{counterUI2}

);
}
```

**Under the hood:** Custom hooks are **child components with syntactic sugar**. The `useCounter('counter1', 0)` call compiles to a `VComponentWrapper` - reusing the Lifted State infrastructure with zero runtime overhead!

**Benefits:**
- βœ… Multiple independent instances with unique namespaces
- βœ… Can return JSX UI (unlike React hooks)
- βœ… Reuses VComponentWrapper + Lifted State Pattern
- βœ… Parent can observe child hook state: `State["counter1.count"]`
- βœ… Type-safe C# classes with `[Hook]` attribute
- βœ… Hot reload preserves hook state

**[πŸͺ Custom Hooks Guide β†’](./docs/CUSTOM_HOOKS_IMPLEMENTATION.md)**

---

### πŸ”’ useProtectedState
Lifted state with access control:

```typescript
function Counter() {
const [count, setCount] = useState(0); // Public
const [animationQueue, setQueue] = useProtectedState([]); // Protected
}

// Parent can't touch protected state!
const queue = state["Counter.animationQueue"]; // ❌ Runtime error
```

**[πŸ”’ Protected State Details β†’](./docs/USE_PROTECTED_STATE.md)**

---

### 🎨 Minimact Swig IDE
Desktop development environment with real-time component inspection:


Minimact Swig IDE

**Features:**
- Monaco editor with full TSX support
- Auto-transpilation watch mode
- Live component state inspector
- Visual prediction analytics
- Integrated terminal and file tree

**Quick Start:**
```bash
git clone https://github.com/minimact/swig
cd swig
npm install
npm start
```

**What Makes Swig Special:**
- **Hot reload preserves state** - State lives in parent, survives reloads
- **Real-time component inspector** - See state changes as they happen via SignalR
- **Visual prediction analytics** - Green/red cache hit overlay shows prediction accuracy
- **Performance dashboard** - Hit rate, latencies, and metrics in real-time
- **Zero configuration** - From clone to running app in 2 minutes

**[🎨 Swig IDE Guide β†’](./docs/MINIMACT_SWIG_ELECTRON_PLAN.md)**

---

### 🍹 Minimact Punch
DOM as a reactive data source - 80+ properties as state:

```typescript
const box = useDomElementState('.container');

{box.childrenCount > 5 && }
{box.isIntersecting && }
{box.vals.avg() > 100 && }
```

**[🍹 Minimact Punch Details β†’](./docs/USEDOMELEMENTSTATE_IMPLEMENTATION_PLAN.md)**

---

## Official Extensions

**The Minimact Quantum Stack** - Transform the DOM into a queryable, reactive, distributed database.

| Extension | Description | Key Feature |
|-----------|-------------|-------------|
| **πŸ₯Š minimact-punch** | DOM as reactive data source (80+ properties) | `useDomElementState('.card')` |
| **πŸ—ƒοΈ minimact-query** | SQL for the DOM with full query syntax | `.from('.card').where().orderBy()` |
| **🌌 minimact-quantum** | Multi-client DOM identity sync (7-17ms) | Mutation vectors, not data sync |
| **🎯 minimact-bundle** | Declarative control without wrappers | Apply styles/classes to any selector |
| **πŸ“ minimact-spatial** | Viewport regions as 2D database | Query spatial areas reactively |
| **🌳 minimact-trees** | Universal decision trees (0-1ms predicted) | XState but declarative & minimal |

**Philosophy:** *"The DOM is no longer a view layer - it's a queryable, reactive, distributed database."*

**[🌌 Explore Extensions β†’](./extensions)**

---

## Advanced Features

### πŸ”Œ Plugin System - Extend via NuGet
**Distribute reusable UI components as NuGet packages. Auto-discovered. Type-safe. Zero config.**

```bash
# Install plugin
dotnet add package Minimact.Plugin.Clock

# Use in TSX

```

**Benefits:**
- βœ… Auto-discovery via `[MinimactPlugin]` attribute
- βœ… Type-safe state contracts (JSON Schema validation)
- βœ… Versioned assets with cache optimization
- βœ… Works with template prediction system
- βœ… Server-rendered, no client JavaScript required

**[πŸ”Œ Plugin System Guide β†’](./docs/PLUGIN_SYSTEM_PHASE2_COMPLETE.md)**

### More Advanced Features

| Feature | Description | Learn More |
|---------|-------------|------------|
| **useServerTask** | TypeScript β†’ C#/Rust transpilation for async tasks | [πŸ“„ Docs](./docs/server-tasks.md) |
| **useContext** | Redis-like server-side cache (session/request/url scoped) | [πŸ“„ Docs](./docs/use-context.md) |
| **useComputed** | Client-side computation with server rendering | [πŸ“„ Docs](./docs/use-computed.md) |
| **MVC Bridge** | Integrate with traditional ASP.NET MVC | [🎯 MVC Bridge](./docs/MVC_BRIDGE_IMPLEMENTATION_PLAN.md) |
| **Semantic Hooks** | High-level abstractions (useModal, useDropdown, etc.) | [🎯 Hooks API](./docs/api-reference.md) |

---

## Architecture Overview

```
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Developer writes TSX with React hooks β”‚
β”‚ ↓ β”‚
β”‚ Babel: TSX β†’ C# + Extract templates β”‚
β”‚ ↓ β”‚
β”‚ ASP.NET Core renders HTML β”‚
β”‚ ↓ β”‚
β”‚ Rust: Predicts patches, sends to clientβ”‚
β”‚ ↓ β”‚
β”‚ [Client has patches cached] β”‚
β”‚ ↓ β”‚
β”‚ User clicks β†’ 0ms (cache hit!) β”‚
β”‚ ↓ β”‚
β”‚ Server verifies in background β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
```

**7 Main Components:**
1. **Babel Plugin** - TSX β†’ C# transformation
2. **C# Runtime** - ASP.NET Core integration
3. **Rust Engine** - High-performance reconciliation
4. **Client Library** - 12.0 KB modular runtime
5. **Lifted State** - Automatic state architecture
6. **Minimact Punch** - DOM state extensions
7. **Minimact Swig** - Desktop IDE

### Technical Innovations

**SignalM - Minimal WebSocket Protocol**
- Custom lightweight protocol (vs full SignalR)
- **12.0 KB** core runtime with SignalM
- **23.94 KB** core runtime with full SignalR (fallbacks for older browsers)
- Real-time bidirectional communication
- Optimized for patch delivery

**Modular Architecture**
- **Core** (12.0 KB) - Essential runtime only
- **Hot Reload** (+5.15 KB) - Development tools (auto tree-shaken in production)
- **Playground** (+376 B) - Swig IDE integration
- **Power Features** (+5.37 KB) - Advanced hooks (useServerTask, useComputed, usePaginatedServerTask, etc.)

**Hex Paths - Stable Element Identifiers**
- Hexadecimal gap-based allocation (0x10000000, 0x20000000, 0x30000000...)
- Example: "10000000.30000000.20000000" (stable IDs, not DOM indices)
- Elements keep stable IDs across insertions/deletions
- Enables precise DOM targeting without re-indexing
- PathConverter translates hex paths β†’ DOM indices (accounts for VNull)

**VNull Nodes - Explicit Conditionals**
- Represents `{condition && }` explicitly in VNode tree
- Rust reconciler understands conditional rendering
- Patches target exact positions, not shifting indices
- Eliminates "DOM shift" bugs from traditional reconcilers

**[πŸ“– Complete Architecture β†’](./docs/MINIMACT_COMPLETE_ARCHITECTURE.md)**

**[πŸ“ Architecture Deep Dive (Substack) β†’](https://ameritusweb.substack.com/p/reverse-scalable-systems-achieving)** - A comprehensive analysis of Minimact's reverse scalability principles and architectural innovations.

---

## Core Technical Innovations

### Hex Paths - Stable Element Identity
Every element gets a persistent hex path ID (e.g., `1.2.F.3`). Unlike DOM indices that shift when elements are added/removed, hex paths use **gap-based allocation** to maintain stability.

**Why it matters:**
- Patches target exact elements, even as DOM changes
- Hot reload works perfectly (paths don't shift)
- Prediction system can reference elements precisely

### VNull Nodes - Explicit Conditional Rendering
Minimact represents `{condition && }` with explicit `VNull` nodes instead of omitting them from the tree.

**Why it matters:**
- PathConverter can accurately map hex paths β†’ DOM indices
- Accounts for conditionally rendered elements
- Makes reconciliation deterministic and predictable

**[πŸ”§ Technical Deep Dive β†’](./docs/HEX_PATH_SYSTEM.md)**

---

## Runtime Comparison: SignalM vs SignalR

Minimact offers two runtime versions optimized for different scenarios:

| Feature | `@minimact/core` (SignalM) | `@minimact/core/r` (SignalR) |
|---------|---------------------------|------------------------------|
| **Size** | **12.0 KB gzipped** | **23.94 KB gzipped** |
| **Protocol** | Custom WebSocket | Full SignalR with fallbacks |
| **Use Case** | Modern browsers, micro-patches | IE11+, corporate networks |
| **Fallbacks** | None | Long polling, SSE, forever frame |
| **Latency** | ~2ms | ~3-5ms |

**SignalM** is a custom WebSocket protocol optimized specifically for Minimact's patch delivery system. It's 50% smaller than SignalR and designed for predictive micro-patch streaming.

**When to use SignalM:**
- Modern browser support (Chrome 90+, Firefox 88+, Safari 14+)
- Public-facing apps with controlled environments
- Maximum performance is critical

**When to use SignalR:**
- Enterprise environments with older browsers
- Corporate networks with WebSocket restrictions
- Need guaranteed compatibility

---

## Performance

| Metric | Value |
|--------|-------|
| **Initial Load** | **12.0 KB** (73% smaller than React) |
| **Time to Interactive** | < 100ms |
| **Interaction Latency** | ~2-5ms (with prediction) |
| **Cache Hit Rate** | 95-98% (after warmup) |
| **Memory vs Caching** | 98% reduction (templates vs concrete patches) |

**[πŸ“Š Benchmarks β†’](./docs/benchmarks.md)**

---

## Comparison

| Feature | Minimact | Next.js | Blazor Server | HTMX |
|---------|----------|---------|---------------|------|
| **Bundle Size** | **12.0 KB** | ~45 KB | ~300 KB | ~14 KB |
| **Syntax** | React JSX | React JSX | Razor C# | HTML attrs |
| **Hydration** | None | Required | None | None |
| **Update Model** | **Predictive (client)** | Reactive (client) | Reactive (server) | **Triggered (server)** |
| **Prediction** | βœ… Rust | ❌ | ❌ | ❌ |
| **Hybrid State** | βœ… | ❌ | ❌ | Manual |
| **Type Safety** | βœ… TSβ†’C# | βœ… TS | βœ… C# | ❌ |
| **Client Interactivity** | βœ… Full | βœ… Full | βœ… Full | ❌ Server-only |
| **Modular** | βœ… Opt-in features | ❌ All-in-one | ❌ All-in-one | βœ… Minimal |

### Why Minimact > HTMX

**HTMX is server-triggered** (user clicks β†’ server responds β†’ HTML swaps)
**Minimact is predictively client-updated** (patches pre-cached β†’ instant apply)

**Key differences:**
- βœ… **No flicker** - Patches already cached, apply instantly
- βœ… **No hydration** - But full client interactivity (unlike HTMX)
- βœ… **Optimistic updates** - UI responds before server confirms
- βœ… **95-98% instant** - Most interactions hit cache, no network wait
- βœ… **React DX** - Familiar hooks and component model

**HTMX use case:** Simple server-driven apps, minimal JS
**Minimact use case:** Complex UIs with instant feedback and React DX

---

## Project Status

**Current Phase:** Production-Ready Core + Advanced Features βœ…

### Recently Completed (2025)
- βœ… Template Prediction System (Phases 1-9)
- βœ… Lifted State Component System
- βœ… useProtectedState Hook
- βœ… Custom Hooks (Hooks as Child Components with UI return)
- βœ… Minimact Swig IDE
- βœ… Minimact Punch (Base Features)
- βœ… State Synchronization (client β†’ server)
- βœ… Mact Modules System (Zero-config module management with Swig CLI)
- βœ… SPA Mode (Single Page Application with shell persistence and 10-50ms navigation)

### In Progress
- 🚧 Minimact Punch Advanced Features (Parts 2-5)
- 🚧 Semantic Hooks Library

**[πŸ“‹ Full Status & Roadmap β†’](./docs/roadmap.md)**

---

## Examples

- **[Todo App](./examples/todo)** - Classic TodoMVC
- **[Blog](./examples/blog)** - Markdown blog with EF Core
- **[Dashboard](./examples/dashboard)** - Admin dashboard with templates
- **[Forms](./examples/forms)** - Validation and semantic hooks

---

## Documentation

πŸ“š **[docs.minimact.com](https://docs.minimact.com)** - Complete guides and API reference

### Quick Links
- [Getting Started](./docs/getting-started.md)
- [Architecture Overview](./docs/MINIMACT_COMPLETE_ARCHITECTURE.md)
- [API Reference](./docs/api-reference.md)
- [Babel Plugin Guide](./docs/babel-plugin.md)
- [Deployment Guide](./docs/deployment.md)

---

## 🎡 The Mactic Experience

```
╔════════════════════════════════════════════════════════════╗
β•‘ β•‘
β•‘ 🌟 PRESENTING 🌟 β•‘
β•‘ β•‘
β•‘ β–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β•‘
β•‘ β–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ•‘β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ•”β•β•β•β•β•β•šβ•β•β–ˆβ–ˆβ•”β•β•β•β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•”β•β•β•β•β• β•‘
β•‘ β–ˆβ–ˆβ•”β–ˆβ–ˆβ–ˆβ–ˆβ•”β–ˆβ–ˆβ•‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘ β•‘
β•‘ β–ˆβ–ˆβ•‘β•šβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘ β•‘
β•‘ β–ˆβ–ˆβ•‘ β•šβ•β• β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β•šβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β•šβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β•‘
β•‘ β•šβ•β• β•šβ•β•β•šβ•β• β•šβ•β• β•šβ•β•β•β•β•β• β•šβ•β• β•šβ•β• β•šβ•β•β•β•β•β• β•‘
β•‘ β•‘
β•‘ THE MUSICAL β•‘
β•‘ β•‘
β•‘ "A WHOLE NEW WORLD OF RENDERING" β•‘
β•‘ β•‘
β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•

🎡 A WHOLE NEW WORLD 🎡
(Minimact Edition)

I can show you the world
Shining, shimmering, mactic
Tell me, developer, now when did
You last let hydration go?

I can open your eyes
Take you render by render
Over, sideways and under
On a mactic carpet ride

A whole new world
A new fantastic point of view
No one to tell us "no"
Or where to go
Or say we're only hydrating

A whole new world
A dazzling place I never knew
But when I'm way up here
It's crystal clear
That now I'm in a whole new world with you
(Now I'm in a whole new world with Minimact)

Unbelievable sights
Indescribable feeling
Soaring, flying, wheeling
Through an endless server-side sky

A whole new world
(Don't you dare close your eyes)
A hundred thousand things to see
(Hold your breath, it gets better)
I'm like a shooting star
I've come so far
I can't go back to where I used to be

A whole new world
With new horizons to pursue
I'll chase them anywhere
There's time to spare
Let me share this whole new world with you

🌡✨ Minimact: Where every navigation is a mactic carpet ride ✨🌡
```

**The Mactic Lexicon:**
- **Mactnificent** (adj.) - Magnificent, but for Minimact
- **Mactical** (adj.) - So magical it feels like server-side sorcery
- **Mactic** (adj.) - When patches predict your clicks before you make them

*It's not magic. It's mactic.* πŸͺ„

**[🎭 Experience the Full Musical β†’](./docs/MUSICAL.md)**

**The Complete Setlist:**
1. 🎡 "Part of Your World" - The Developer's Lament
2. 🎡 "Under the Server" - Life below the client
3. 🎡 "Let It Go (The Hydration)" - Embracing server-side rendering
4. 🎡 "How Far I'll Go" - Avoiding client-side rendering
5. 🎡 "You're Welcome" - From SignalR
6. 🎡 "Circle of Life" - The Component Lifecycle
7. 🎡 **"A Whole New World"** - The Mactic Experience
8. 🎡 "One Day More" - Until Production

*Plus: The Minimact Cinematic Universe, MinimactLand Theme Park, and more!* 🎭✨

---

## Why the Name Minimact?

**Minimact** stands for **MINIMal Anticipatory Client Technology**.

- **Minimal** β€” Tiny 12.0 KB runtime, minimal client logic
- **Anticipatory** β€” Predictive patches pre-sent before user interaction
- **Client Technology** β€” Smart client that applies cached patches instantly

And yes β€” the cactus 🌡 doesn't hydrate. It stores.

---

## Contributing

We welcome contributions! See [CONTRIBUTING.md](./CONTRIBUTING.md) for guidelines.

**Join the discussion:**
- [GitHub Discussions](https://github.com/minimact/minimact/discussions)
- [Discord Server](https://discord.gg/EKPDh6v7)

---

## License

MIT License - see [LICENSE](./LICENSE) for details

---

## Acknowledgments

Inspired by **React**, **Blazor**, **HTMX**, **Vue**, and **SolidJS**.

Built with **Rust**, **ASP.NET Core**, **Babel**, and **TypeScript**.

---


Built with ❀️ for the .NET and React communities


⭐ Star this repo if you're interested in server-side React for .NET!