๐ŸŒต๐Ÿ“Š

Minimact Architecture Diagrams

Visual documentation for Minimact and Minimact Punch

About These Diagrams

This page contains comprehensive visual documentation for the Minimact architecture, showing how components interact, data flows, messaging patterns, and the integration of the Minimact Punch extension.

๐ŸŽฏ Core Architecture

System components from TSX to DOM

โšก Data Flows

Request/response cycles and messaging

๐Ÿ”ฎ Predictions

Cache hit/miss logic and hint queues

๐Ÿ”„ State Sync

NEW auto-sync pattern preventing stale data

๐Ÿš€ Lifecycle NEW

Initial SSR through SignalR connection

๐Ÿง  Learning NEW

Pattern detection and confidence scoring

๐Ÿ”ง Babel NEW

TSX โ†’ C# transformation with examples

๐Ÿ”’ Security NEW

Multi-layer authorization and validation

โšก Hot Reload NEW

Template-based 3-5ms updates, 98% less memory

๐Ÿ’ป Developer Workflow NEW

Setup, dev loop, debugging, integrations

Minimact Core Architecture

System components showing all layers from TSX development to DOM rendering, including the Babel compilation pipeline, ASP.NET Core runtime, Rust reconciliation engine, and client-side SignalR integration.

graph TB subgraph "Developer Layer" TSX[TSX/JSX Components] TS[TypeScript] end subgraph "Compilation Layer" BABEL[Babel Plugin] CODEGEN[Code Generator] end subgraph "Server Runtime (.NET)" COMP[MinimactComponent] STATE[State Manager] RENDER[Render Engine] HUB[MinimactHub SignalR] RUST[Rust Reconciler FFI] end subgraph "Rust Engine" RECON[Reconciliation Engine] PRED[Prediction Engine] DIFF[VNode Differ] end subgraph "Client Runtime (Browser)" SIGNALR[SignalR Manager] PATCHER[DOM Patcher] HOOKS[Hook System] QUEUE[Hint Queue] BRIDGE[Playground Bridge] end subgraph "Client DOM" DOM[Browser DOM] EVENTS[Event Delegation] end TSX --> BABEL TS --> BABEL BABEL --> CODEGEN CODEGEN --> COMP COMP --> STATE STATE --> RENDER RENDER --> RUST RUST --> RECON RECON --> DIFF DIFF --> PRED PRED --> HUB RENDER --> HUB HUB --> SIGNALR SIGNALR --> PATCHER SIGNALR --> QUEUE PATCHER --> DOM QUEUE --> PATCHER HOOKS --> SIGNALR DOM --> EVENTS EVENTS --> SIGNALR PATCHER --> BRIDGE QUEUE --> BRIDGE

Complete Data Flow

Sequence diagram showing the complete request/response cycle, from initial render through predictive pre-caching to user interactions with both cache hits and misses.

sequenceDiagram participant User participant DOM participant EventDel as Event Delegation participant SignalR as SignalR Manager participant Hub as MinimactHub participant Comp as Component participant Rust as Rust Engine participant Predictor participant Queue as Hint Queue participant Patcher as DOM Patcher Note over User,Patcher: Initial Render Comp->>Rust: Render() โ†’ VNode Rust->>Rust: Generate patches Rust->>Hub: Send patches Hub->>SignalR: ApplyPatches SignalR->>Patcher: Apply to DOM Patcher->>DOM: Update elements Note over User,Patcher: Predictive Pre-Caching Predictor->>Rust: Predict state changes Rust->>Rust: Pre-compute patches Rust->>Hub: Send predictions Hub->>SignalR: QueueHint SignalR->>Queue: Cache patches Queue-->>Queue: Ready for instant use Note over User,Patcher: User Interaction (Cache Hit) User->>DOM: Click button DOM->>EventDel: Capture event EventDel->>Queue: Check for hint Queue-->>Queue: ๐ŸŸข CACHE HIT! Queue->>Patcher: Apply cached patches Patcher->>DOM: Instant update (0ms) EventDel->>SignalR: Notify server (background) SignalR->>Hub: InvokeComponentMethod Hub->>Comp: Call method Comp->>Comp: Update state Comp->>Rust: Re-render Rust->>Hub: Verify patches Hub->>SignalR: ApplyCorrection (if needed) Note over User,Patcher: User Interaction (Cache Miss) User->>DOM: Click button DOM->>EventDel: Capture event EventDel->>Queue: Check for hint Queue-->>Queue: ๐Ÿ”ด CACHE MISS EventDel->>SignalR: Invoke method SignalR->>Hub: InvokeComponentMethod Hub->>Comp: Call method Comp->>Comp: Update state Comp->>Rust: Re-render Rust->>Rust: Compute patches Rust->>Hub: Send patches Hub->>SignalR: ApplyPatches SignalR->>Patcher: Apply to DOM Patcher->>DOM: Update (~45ms latency)

Predictive Rendering Pipeline

Flowchart showing how the prediction engine determines whether to send predictions, the confidence threshold, and the verification/correction flow.

flowchart TD START[Component State Change] --> PREDICT{Can Predict?} PREDICT -->|Yes| CONF{Confidence >= 0.7?} PREDICT -->|No| RENDER[Normal Render] CONF -->|Yes| SEND_PRED[Send Prediction Immediately] CONF -->|No| RENDER SEND_PRED --> CLIENT_CACHE[Client Caches Patches] CLIENT_CACHE --> APPLY_PRED[Apply Prediction Instantly] APPLY_PRED --> BG_RENDER[Background: Server Renders] RENDER --> BG_RENDER BG_RENDER --> RECON[Rust Reconciliation] RECON --> ACTUAL_PATCHES[Actual Patches] ACTUAL_PATCHES --> COMPARE{Prediction Match?} COMPARE -->|โœ… Match| NO_ACTION[No Action Needed] COMPARE -->|โŒ Mismatch| CORRECTION[Send Correction] CORRECTION --> CLIENT_FIX[Client Applies Fix] style SEND_PRED fill:#90EE90 style APPLY_PRED fill:#90EE90 style NO_ACTION fill:#90EE90 style CORRECTION fill:#FFB6C1 style CLIENT_FIX fill:#FFB6C1

State Synchronization NEW

Critical Update: The new auto-sync pattern ensures client state changes are immediately synchronized to the server, preventing stale data issues that could cause the Rust reconciler to overwrite client updates.

sequenceDiagram participant User participant Client as Client Hook (useState) participant SignalR as SignalR Manager participant Hub as MinimactHub participant Comp as MinimactComponent participant Rust as Rust Reconciler Note over User,Rust: NEW: Automatic State Sync User->>Client: setCount(5) Client->>Client: Update local state par Check Hint Queue Client->>Client: Check HintQueue alt Cache Hit Client->>Client: Apply cached patches (instant) else Cache Miss Client->>Client: No instant feedback end and Sync to Server Client->>SignalR: updateComponentState(componentId, "count", 5) SignalR->>Hub: UpdateComponentState Hub->>Comp: SetStateFromClient("count", 5) Comp->>Comp: Update internal state Comp->>Rust: TriggerRender() Rust->>Rust: Compute patches Rust->>Hub: Patches ready Hub->>SignalR: ApplyPatches (verification) SignalR->>Client: Patches applied end Note over User,Rust: Result: Server always has correct state!

Minimact Punch Architecture ๐Ÿน

useDomElementState integration showing how DOM observers feed into the reactive state system, enabling DOM-driven predictions.

graph TB subgraph "Client Runtime" HOOK[useDomElementState hook] STATE[DomElementState class] OBSERVERS[Browser Observers] SNAPSHOT[State Snapshot] end subgraph "Observers Layer" INTERSECT[IntersectionObserver] MUTATION[MutationObserver] RESIZE[ResizeObserver] end subgraph "Reactive Properties" PROPS["Properties - isIntersecting - childrenCount - attributes - classList"] COLLECTION["Collection Methods - every - some - filter"] STATS["Statistics - vals.avg - vals.sum - vals.median"] end subgraph "Integration" CONTEXT[ComponentContext] HINTQUEUE[HintQueue] SIGNALR[SignalR Manager] PATCHER[DOM Patcher] end subgraph "Server Side" CSHARP[C# DomElementStateHook] HUB[MinimactHub] PREDICTOR[Prediction Engine] end HOOK --> STATE STATE --> OBSERVERS OBSERVERS --> INTERSECT OBSERVERS --> MUTATION OBSERVERS --> RESIZE INTERSECT --> SNAPSHOT MUTATION --> SNAPSHOT RESIZE --> SNAPSHOT SNAPSHOT --> PROPS SNAPSHOT --> COLLECTION SNAPSHOT --> STATS STATE --> CONTEXT CONTEXT --> HINTQUEUE CONTEXT --> SIGNALR CONTEXT --> PATCHER SIGNALR --> HUB HUB --> CSHARP CSHARP --> PREDICTOR PREDICTOR --> HINTQUEUE

Integration Patterns

Hook integration showing the symmetry between useState and useDomElementState, both following the same MES-compliant pattern.

flowchart LR subgraph "Component Context" STATE_MAP[state: Map] EFFECTS[effects: Array] REFS[refs: Map] DOM_STATES[domElementStates: Map] HINT_QUEUE[hintQueue: HintQueue] DOM_PATCHER[domPatcher: DOMPatcher] SIGNALR_MGR[signalR: SignalRManager] end subgraph "Hooks" USE_STATE[useState] USE_EFFECT[useEffect] USE_REF[useRef] USE_DOM[useDomElementState] end subgraph "Symmetry" PATTERN[Same Pattern:
1. Index tracking
2. Context integration
3. HintQueue check
4. Server sync
5. Cleanup] end USE_STATE --> STATE_MAP USE_EFFECT --> EFFECTS USE_REF --> REFS USE_DOM --> DOM_STATES USE_STATE --> HINT_QUEUE USE_DOM --> HINT_QUEUE USE_STATE --> SIGNALR_MGR USE_DOM --> SIGNALR_MGR STATE_MAP --> PATTERN DOM_STATES --> PATTERN style USE_DOM fill:#FFD700 style DOM_STATES fill:#FFD700 style PATTERN fill:#90EE90

Complete System Overview

End-to-end architecture showing all components from developer experience through build-time compilation, server runtime, Rust engine, SignalR layer, client runtime, and Minimact Punch extension.

graph TB subgraph "Developer Experience" DEV[Developer writes TSX] IDE[TypeScript IntelliSense] end subgraph "Build Time" BABEL[Babel Plugin] CODEGEN[Code Generator] CSHARP[C# Classes] end subgraph "Server Runtime" ASPNET[ASP.NET Core] COMPONENT[MinimactComponent] STATEMGR[State Manager] HOOKS_CS[C# Hook Implementations] end subgraph "Rust Engine" FFI[FFI Bridge] RECONCILER[Reconciliation Engine] PREDICTOR[Prediction Engine] VNODE[VNode Differ] end subgraph "SignalR Layer" HUB[MinimactHub] CONNECTION[SignalR Connection] end subgraph "Client Runtime" SIGNALR_CLIENT[SignalR Manager] HOOKS_TS[TypeScript Hooks] CONTEXT[Component Context] HINTQUEUE[Hint Queue] PATCHER[DOM Patcher] PLAYGROUND[Playground Bridge] end subgraph "minimact-punch Extension" DOM_STATE[DomElementState] OBSERVERS[DOM Observers] STATS[Statistical Engine] INTEGRATION[Integration Layer] end subgraph "Browser" DOM[DOM] EVENTS[Event System] WEB_APIS[Web APIs] end DEV --> BABEL IDE --> DEV BABEL --> CODEGEN CODEGEN --> CSHARP CSHARP --> COMPONENT COMPONENT --> STATEMGR COMPONENT --> HOOKS_CS STATEMGR --> FFI HOOKS_CS --> FFI FFI --> RECONCILER FFI --> PREDICTOR RECONCILER --> VNODE PREDICTOR --> VNODE VNODE --> HUB COMPONENT --> HUB HUB --> CONNECTION CONNECTION --> SIGNALR_CLIENT SIGNALR_CLIENT --> HOOKS_TS SIGNALR_CLIENT --> HINTQUEUE HOOKS_TS --> CONTEXT CONTEXT --> PATCHER CONTEXT --> PLAYGROUND HINTQUEUE --> PATCHER PATCHER --> DOM INTEGRATION --> HOOKS_TS INTEGRATION --> CONTEXT DOM_STATE --> OBSERVERS OBSERVERS --> WEB_APIS DOM_STATE --> STATS STATS --> INTEGRATION DOM --> EVENTS EVENTS --> SIGNALR_CLIENT WEB_APIS --> DOM style DOM_STATE fill:#FFD700 style INTEGRATION fill:#FFD700 style OBSERVERS fill:#FFD700 style STATS fill:#FFD700

Performance Characteristics

Latency comparison showing the performance benefits of cache hits in both traditional Minimact and Minimact Punch scenarios.

Traditional SSR

~52ms total latency (network round-trip + processing)

Minimact Cache Hit

~2ms total latency (instant patch application)

Minimact Cache Miss

~52ms total latency (falls back to server render)

Minimact Punch Hit

~2ms total latency (DOM observer + instant patch)

Component Lifecycle & Initial Load

Initial Page Load Flow

How does the initial page load work? This diagram shows the progression from SSR โ†’ HTML โ†’ SignalR connection upgrade, demonstrating how the page works without JavaScript and is progressively enhanced with JavaScript.

sequenceDiagram participant Browser participant Server as ASP.NET Core participant Rust as Rust Engine participant Component participant SignalR as SignalR Hub participant Client as Client Runtime Note over Browser,Client: 1. Initial SSR (No JavaScript Yet) Browser->>Server: HTTP GET /page Server->>Component: Create instance Component->>Component: OnInitializedAsync() Component->>Rust: Render() โ†’ VNode Rust->>Rust: Generate HTML Rust->>Server: HTML string Server->>Browser: Return HTML page Browser->>Browser: Display HTML immediately Note over Browser,Client: 2. Progressive Enhancement (JavaScript Loads) Browser->>Browser: Parse & execute ~5KB client.js Browser->>Client: Initialize Minimact client Client->>SignalR: Establish WebSocket connection Note over Browser,Client: 3. Component Registration SignalR->>Server: Connection established Server->>SignalR: Assign ConnectionId Client->>Client: Query DOM for [data-component-id] Client->>SignalR: RegisterComponent(componentId) SignalR->>Server: Store mapping: ConnectionId โ†’ ComponentId Server->>Component: Attach connection to instance Note over Browser,Client: 4. Ready State Component->>Rust: Generate initial predictions Rust->>SignalR: QueueHint messages SignalR->>Client: Cache predictions Client->>Client: System ready - instant interactions enabled Note over Browser,Client: Result: Page works WITHOUT JS, enhanced WITH JS

Component ID Tracking

Components are identified and tracked between server and client using GUIDs embedded in data-component-id attributes.

graph LR subgraph "Server-Side Rendering" COMP[Component Instance] ID[Generate GUID] HTML[Rendered HTML] end subgraph "HTML Output" ATTR[data-component-id attribute] end subgraph "Client-Side Discovery" DOM[DOM Query] MAP[ComponentId โ†’ Element Map] end subgraph "Server Registry" REGISTRY[Component Registry] CONN[ConnectionId โ†’ Component Map] end COMP --> ID ID --> ATTR ATTR --> HTML HTML --> DOM DOM --> MAP MAP --> REGISTRY REGISTRY --> CONN style ATTR fill:#FFD700 style MAP fill:#90EE90

Prediction Engine Deep Dive

Learning & Pattern Detection

The prediction engine learns patterns through frequency analysis, sequence detection, and conditional pattern recognition. It assigns confidence scores and only sends predictions with โ‰ฅ70% confidence.

flowchart TD START[User Interaction] --> RECORD[Record to History] RECORD --> PATTERN{Pattern Analysis} PATTERN -->|Frequency Analysis| FREQ[Track state change frequency] PATTERN -->|Sequence Detection| SEQ[Detect interaction sequences] PATTERN -->|Conditional Patterns| COND[Learn conditional branches] FREQ --> CONFIDENCE[Calculate Confidence Score] SEQ --> CONFIDENCE COND --> CONFIDENCE CONFIDENCE --> THRESHOLD{Confidence >= 0.7?} THRESHOLD -->|Yes| GENERATE[Generate Prediction] THRESHOLD -->|No| SKIP[Skip prediction] GENERATE --> PRECOMPUTE[Pre-compute patches] PRECOMPUTE --> QUEUE[Queue to client] QUEUE --> MEASURE[Measure accuracy on use] MEASURE --> FEEDBACK[Adjust confidence weights] FEEDBACK --> PATTERN SKIP --> END[End] style GENERATE fill:#90EE90 style QUEUE fill:#90EE90 style CONFIDENCE fill:#FFD700

Prediction Triggers

Three types of triggers: explicit usePredictHint, automatic pattern learning, and user behavior patterns (e.g., hover โ†’ click probability).

sequenceDiagram participant Dev as Developer participant Comp as Component participant Pred as Prediction Engine participant Rust as Rust Reconciler participant Queue as Hint Queue Note over Dev,Queue: Trigger 1: Explicit usePredictHint Dev->>Comp: usePredictHint('increment', {count: count+1}) Comp->>Pred: Register hint Pred->>Rust: Compute patches for predicted state Rust->>Pred: Return patches Pred->>Queue: QueueHint(hintId, patches, confidence: 1.0) Note over Dev,Queue: Trigger 2: Automatic Pattern Learning Comp->>Comp: setState(newValue) Comp->>Pred: Notify state change Pred->>Pred: Analyze historical patterns Pred->>Pred: Detect: "count always increments by 1" Pred->>Rust: Compute patches for likely next state Rust->>Pred: Return patches Pred->>Queue: QueueHint(hintId, patches, confidence: 0.85) Note over Dev,Queue: Trigger 3: User Behavior Patterns Comp->>Pred: Track: User hovered button for 500ms Pred->>Pred: Pattern: Hover โ†’ Click (78% probability) Pred->>Rust: Pre-compute click result Rust->>Pred: Return patches Pred->>Queue: QueueHint(hintId, patches, confidence: 0.78) Note over Dev,Queue: Accuracy Feedback Loop Queue->>Queue: User clicked โ†’ Check cache Queue->>Pred: Report: Hit/Miss + actual state Pred->>Pred: Update pattern weights

Babel Plugin Transformation

TSX to C# Example

Concrete before/after example showing how TypeScript/JSX transforms into C# with VNode trees.

Input (Counter.tsx):

import { useState } from 'minimact';

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

    return (
        <div>
            <p>Count: {count}</p>
            <button onClick={() => setCount(count + 1)}>
                Increment
            </button>
        </div>
    );
}

Output (Counter.cs):

using Minimact.AspNetCore.Core;
using Minimact.AspNetCore.VNodes;

namespace MyApp.Components
{
    public partial class Counter : MinimactComponent
    {
        [State]
        private int count = 0;

        protected override VNode Render()
        {
            return new VElement("div",
                new VElement("p", $"Count: {count}"),
                new VElement("button",
                    new VAttribute("onClick", nameof(Increment)),
                    "Increment"
                )
            );
        }

        private void Increment()
        {
            count++;
            SetState(nameof(count), count);
        }
    }
}

Transformation Pipeline

flowchart TD START[Counter.tsx] --> PARSE[Babel Parse AST] PARSE --> DETECT[Detect Hooks] DETECT --> HOOK_STATE{Hook Type?} HOOK_STATE -->|useState| GEN_STATE[Generate State field] HOOK_STATE -->|useEffect| GEN_EFFECT[Generate lifecycle method] HOOK_STATE -->|useRef| GEN_REF[Generate private field] GEN_STATE --> TRACK_DEPS[Track dependencies] GEN_EFFECT --> TRACK_DEPS GEN_REF --> TRACK_DEPS TRACK_DEPS --> JSX[Parse JSX] JSX --> BUILD_VNODE[Build VNode tree] BUILD_VNODE --> EVENTS{Event Handlers?} EVENTS -->|Yes| GEN_METHODS[Generate C# methods] EVENTS -->|No| CONTINUE GEN_METHODS --> CONTINUE[Continue] CONTINUE --> TYPE_MAP[Map TS types to C# types] TYPE_MAP --> OUTPUT[Generate Counter.cs] style GEN_STATE fill:#90EE90 style BUILD_VNODE fill:#FFD700 style OUTPUT fill:#3b82f6

๐ŸŽจ Template Patch System NEW

Build-Time Template Generation

The Template Patch System revolutionizes predictive rendering by generating parameterized patch templates at build time through Babel AST analysis. This provides 100% coverage of all possible state values with zero learning phase.

flowchart TD TSX[Counter.tsx] --> BABEL[Babel Plugin] BABEL --> AST[Parse JSX AST] AST --> ANALYZE[Analyze JSX Expressions] ANALYZE --> DETECT{Dynamic Content?} DETECT -->|Static| STATIC[Static Template
No bindings] DETECT -->|Dynamic| DYNAMIC[Dynamic Template
Extract bindings] DYNAMIC --> SLOTS[Identify Slot Positions
'Count: {0}'] SLOTS --> BINDINGS[Record State Bindings
bindings: ['count']] BINDINGS --> COND{Conditional?} COND -->|Yes| COND_TEMPLATE[Conditional Template
true: 'โœ“', false: 'โ—‹'] COND -->|No| SIMPLE_TEMPLATE[Simple Template
template: '{0}'] STATIC --> TEMPLATE_JSON SIMPLE_TEMPLATE --> TEMPLATE_JSON COND_TEMPLATE --> TEMPLATE_JSON[Counter.templates.json] TEMPLATE_JSON --> CSHARP[Counter.cs with
[LoopTemplate] attributes] style BABEL fill:#3b82f6 style TEMPLATE_JSON fill:#10b981 style CSHARP fill:#8b5cf6

Template Types & Examples

1. Static Template (No bindings)

<h1>Welcome to Minimact</h1>

// Template:
{
  "type": "static",
  "template": "Welcome to Minimact",
  "bindings": []
}

2. Dynamic Template with Slots

<p>Count: {count}</p>

// Template:
{
  "type": "dynamic",
  "template": "Count: {0}",
  "bindings": ["count"],
  "slots": [{ "index": 0, "binding": "count" }]
}

3. Conditional Template

<span>{todo.done ? 'โœ“' : 'โ—‹'}</span>

// Template:
{
  "type": "conditional",
  "template": "{0}",
  "bindings": ["item.done"],
  "conditionalTemplates": {
    "true": "โœ“",
    "false": "โ—‹"
  }
}

4. Loop Template (Most Powerful)

{todos.map(todo => <li>{todo.text}</li>)}

// C# Attribute:
[LoopTemplate(
    itemsBinding: "todos",
    template: "<li>{0}</li>",
    bindings: ["item.text"]
)]

Runtime: Template Filling Flow

At runtime, when state changes, the client fills template slots with actual values for instant updates. No server round-trip needed!

sequenceDiagram participant User participant Client participant Templates as Template Cache participant DOM participant SignalR participant Server Note over User,Server: Initial Page Load Server->>Server: Render() โ†’ VNode tree Server->>Server: Extract templates from
[LoopTemplate] attributes Server->>Templates: Send all templates
+ initial state Templates->>Templates: Cache templates by
componentId + nodePath Note over User,Server: User Interaction (Instant Update) User->>Client: Click "Increment" Client->>Client: useState: setCount(count + 1) Client->>Templates: getTemplate(componentId, nodePath) Templates-->>Client: { template: "Count: {0}", bindings: ["count"] } Client->>Client: Fill slots:
"Count: {0}" โ†’ "Count: 5" Client->>DOM: Update text node Note right of DOM: โœจ 0ms! Instant update Client->>SignalR: updateComponentState("count", 5) SignalR->>Server: Sync state Server->>Server: SetStateFromClient("count", 5) Note right of Server: Server state in sync!
Prevents stale data Note over User,Server: Complex State Change (Server Render) User->>Client: Add new todo item Client->>SignalR: invokeMethod("addTodo", ...) SignalR->>Server: Execute addTodo() Server->>Server: todos.Add(newTodo) Server->>Server: Render() โ†’ New VNode Server->>Server: Rust reconciler diffs Server->>Client: Send patches Client->>DOM: Apply patches Note right of DOM: Server handles
complex logic

Template vs Hint Queue Comparison

graph TB subgraph "OLD: Hint Queue System" A1[User Action] --> B1[Server pre-computes
specific predictions] B1 --> C1[Cache patches for
count=0โ†’1, count=1โ†’2, etc.] C1 --> D1[Limited coverage
N predicted values] D1 --> E1[Learning phase required] E1 --> F1[Cache misses possible] end subgraph "NEW: Template Patch System" A2[Build Time] --> B2[Babel extracts templates
from JSX AST] B2 --> C2[Single parameterized template
'Count: {0}'] C2 --> D2[100% coverage
ALL possible values] D2 --> E2[Zero learning phase] E2 --> F2[No cache misses ever] end style A1 fill:#fca5a5 style F1 fill:#fca5a5 style A2 fill:#86efac style F2 fill:#86efac

๐Ÿ”Œ Plugin System Architecture NEW

Overview

Minimact's Plugin System enables 100% server-side plugins distributed as NuGet packages. Plugins have zero client bundle overhead and leverage the Template Patch System for instant client updates.

flowchart TD subgraph "Plugin Development" A[Create C# Class] --> B[Implement IMinimactPlugin] B --> C[Add [MinimactPlugin] attribute] C --> D[Define state interface/class] D --> E[Implement Render method] E --> F[Add embedded assets
CSS, JS, images] F --> G[Package as NuGet] end subgraph "Plugin Distribution" G --> H[Publish to NuGet.org] H --> I[Developer: dotnet add package] end subgraph "Plugin Discovery" I --> J[App starts] J --> K[PluginManager.AutoDiscover] K --> L[Scan assemblies for
[MinimactPlugin]] L --> M[Register plugins] M --> N[Load embedded assets] end subgraph "Runtime Usage" N --> O[<Plugin name='Clock' state={...} />] O --> P[Babel transforms to
new PluginNode] P --> Q[Server renders plugin] Q --> R[Client applies templates] end style G fill:#3b82f6 style H fill:#10b981 style M fill:#8b5cf6 style R fill:#f59e0b

Plugin Rendering Flow

From JSX to rendered output, showing how plugins integrate seamlessly with Minimact's architecture.

sequenceDiagram participant Dev as Developer participant Babel as Babel Plugin participant Server as ASP.NET Server participant PluginMgr as PluginManager participant Plugin as Clock Plugin participant Rust as Rust Reconciler participant Client as Browser Note over Dev,Client: Build Time Dev->>Babel: <Plugin name="Clock" state={time} /> Babel->>Babel: Detect Plugin JSX tag Babel->>Babel: Transform to C# code:
new PluginNode("Clock", stateObj) Babel->>Server: Generate Component.cs Note over Dev,Client: Runtime - Initial Render Client->>Server: Request page Server->>Server: Component.Render() Server->>Server: VNode tree includes
PluginNode("Clock", {...}) Server->>PluginMgr: RenderPlugin("Clock", state) PluginMgr->>PluginMgr: Validate state schema PluginMgr->>Plugin: Plugin.Render(state) Plugin-->>PluginMgr: VNode tree
(div > h2 + p) PluginMgr-->>Server: VNode tree Server->>Rust: Reconcile(oldVNode, newVNode) Rust-->>Server: DOM patches Server->>Client: Send patches + templates Client->>Client: Apply patches Client->>Client: Cache plugin templates Note over Dev,Client: State Update Client->>Client: time changes (1:23 โ†’ 1:24) Client->>Client: Template filling:
"{0}:{1} {2}" with [1,24,"PM"] Client->>Client: Update DOM instantly Note right of Client: 0ms update!
No server needed Client->>Server: updateComponentState("time", ...) Server->>Server: Keep state in sync

Plugin Asset Serving

Plugins can include CSS, JavaScript, images, and fonts as embedded resources, served automatically with versioning and caching.

flowchart TD A[Plugin has embedded assets] --> B[PluginAssetMiddleware] B --> C{Request matches
/plugin-assets/...?} C -->|No| D[Next middleware] C -->|Yes| E[Parse URL] E --> F{Version specified?} F -->|Yes| G[Get plugin by
name + version] F -->|No| H[Get latest version] G --> I{Plugin found?} H --> I I -->|No| J[404 Not Found] I -->|Yes| K[Find embedded resource] K --> L{Resource found?} L -->|No| J L -->|Yes| M[Set Content-Type] M --> N[Set Cache headers
max-age=86400] N --> O[Set ETag] O --> P[Stream resource bytes] style B fill:#3b82f6 style K fill:#10b981 style P fill:#8b5cf6

Plugin Example: Clock Widget

Plugin Implementation (ClockPlugin.cs):

[MinimactPlugin("Clock", "1.0.0")]
public class ClockPlugin : MinimactPlugin<ClockState>
{
    public override string Name => "Clock";
    public override string Version => "1.0.0";

    [LoopTemplate(
        template: "<div class='clock'><h2>{0}:{1}</h2><p>{2}</p></div>",
        bindings: ["hours", "minutes", "period"]
    )]
    public override VNode Render(ClockState state)
    {
        return new VElement("div",
            new VAttribute("class", "clock"),
            new VElement("h2", $"{state.Hours}:{state.Minutes:D2}"),
            new VElement("p", state.Period)
        );
    }

    public override IEnumerable<PluginAsset> GetAssets()
    {
        yield return new PluginAsset(
            "clock-widget.css",
            PluginAssetType.Stylesheet
        );
    }
}

public class ClockState
{
    public int Hours { get; set; }
    public int Minutes { get; set; }
    public string Period { get; set; } // "AM" or "PM"
}

Usage in Component (Dashboard.tsx):

export function Dashboard() {
    const [time, setTime] = useState({ hours: 1, minutes: 23, period: 'PM' });

    return (
        <div>
            <h1>Dashboard</h1>
            <Plugin name="Clock" state={time} />
        </div>
    );
}

Plugin Discovery & Registration

PluginManager automatically discovers plugins at startup or supports explicit registration for fine-grained control.

flowchart TD START[App Startup] --> CONFIG{Configuration?} CONFIG -->|Auto-Discovery| AUTO[PluginManager.AutoDiscover] CONFIG -->|Explicit| EXPLICIT[options.RegisterPlugin<T>] AUTO --> SCAN[Scan all loaded assemblies] SCAN --> FIND[Find types with
[MinimactPlugin] attribute] FIND --> INSTANTIATE[ActivatorUtilities.CreateInstance] EXPLICIT --> INSTANTIATE INSTANTIATE --> INIT[plugin.Initialize] INIT --> VALIDATE[Validate metadata] VALIDATE --> SCHEMA[Generate JSON Schema
from state type] SCHEMA --> ASSETS[Discover embedded assets] ASSETS --> REGISTER[Add to plugin registry] REGISTER --> READY[Plugin ready] READY --> USAGE[<Plugin name="..." />] style AUTO fill:#3b82f6 style EXPLICIT fill:#8b5cf6 style READY fill:#10b981

Multi-Version Plugin Support

Multiple versions of the same plugin can coexist, with semver-based compatibility checking.

graph TB subgraph "Plugin Registry" A[Clock@1.0.0] --> R[Registry] B[Clock@1.2.0] --> R C[Clock@2.0.0] --> R end subgraph "Component Requests" D[<Plugin name='Clock' />] --> E{GetLatestVersion} F[<Plugin name='Clock' version='1.x' />] --> G{GetLatestCompatible} H[<Plugin name='Clock' version='1.2.0' />] --> I{GetExactVersion} end E --> C G --> B I --> B C --> J[Render with Clock@2.0.0] B --> K[Render with Clock@1.2.0] style R fill:#3b82f6 style C fill:#10b981 style B fill:#10b981

Security & Authorization Model

Method Invocation Security

Multi-layer security ensures only authenticated, authorized users can invoke component methods with validated parameters.

sequenceDiagram participant Client participant SignalR as SignalR Hub participant Auth as Authorization participant Registry as Component Registry participant Comp as Component Note over Client,Comp: Secure Method Invocation Flow Client->>SignalR: InvokeComponentMethod(componentId, "UpdateProfile", args) SignalR->>Auth: ValidateConnection() Auth->>Auth: Check User.Identity Auth->>Auth: Verify ConnectionId is authenticated alt Not Authenticated Auth->>Client: 401 Unauthorized end SignalR->>Registry: GetComponent(componentId) alt Component Not Found Registry->>Client: Error: Component not found end Registry->>Registry: Verify component belongs to this connection alt Wrong Connection Registry->>Client: Error: Unauthorized access end SignalR->>Comp: Check [Authorize] attribute on method alt Has [Authorize(Roles="Admin")] Comp->>Auth: Check User.IsInRole("Admin") Auth-->>Comp: False Comp->>Client: Error: Forbidden end Comp->>Comp: Validate method parameters alt Invalid Parameters Comp->>Client: Error: Validation failed end Comp->>Comp: Invoke method via reflection Comp->>Comp: Update state Comp->>Client: Success

State Validation Flow

All client state updates go through type checking, range validation, sanitization, and custom validators before being applied.

flowchart TD START[Client sends UpdateComponentState] --> AUTH{User Authenticated?} AUTH -->|No| REJECT1[Reject: 401 Unauthorized] AUTH -->|Yes| OWNER{Owns Component?} OWNER -->|No| REJECT2[Reject: 403 Forbidden] OWNER -->|Yes| VALIDATE[Validate State Value] VALIDATE --> TYPE{Type Valid?} TYPE -->|No| REJECT3[Reject: Invalid type] TYPE -->|Yes| RANGE{Range Valid?} RANGE -->|No| REJECT4[Reject: Out of range] RANGE -->|Yes| SANITIZE[Sanitize Input] SANITIZE --> CUSTOM{Custom Validator?} CUSTOM -->|Yes| RUN_VALIDATOR[Run validation logic] CUSTOM -->|No| APPLY RUN_VALIDATOR --> VALID{Valid?} VALID -->|No| REJECT5[Reject: Custom validation failed] VALID -->|Yes| APPLY[Apply state change] APPLY --> LOG[Log change for audit] LOG --> SUCCESS[Success] style REJECT1 fill:#FFB6C1 style REJECT2 fill:#FFB6C1 style REJECT3 fill:#FFB6C1 style REJECT4 fill:#FFB6C1 style REJECT5 fill:#FFB6C1 style SUCCESS fill:#90EE90

Attack Prevention Examples

Demonstrating how the security layers block malicious state updates, unauthorized component access, and protected method invocation attempts.

sequenceDiagram participant Attacker as Malicious Client participant SignalR participant Validator participant Component Note over Attacker,Component: Attack Attempt: Send Invalid State Attacker->>SignalR: UpdateComponentState("count", 999999999) SignalR->>Validator: Validate state change Validator->>Validator: Check type: int โœ“ Validator->>Validator: Check range: > max allowed (1000) Validator->>Attacker: โŒ Error: Value exceeds maximum (1000) Note over Attacker,Component: Attack Attempt: Access Other User's Component Attacker->>SignalR: InvokeComponentMethod("other-user-component", "DeleteAccount") SignalR->>SignalR: Verify component ownership SignalR->>SignalR: ComponentId belongs to different ConnectionId SignalR->>Attacker: โŒ Error: Unauthorized access to component Note over Attacker,Component: Attack Attempt: Call Protected Method Attacker->>SignalR: InvokeComponentMethod("admin-panel", "DeleteAllUsers") SignalR->>Component: Check [Authorize(Roles="Admin")] Component->>Component: User.IsInRole("Admin") = false Component->>Attacker: โŒ Error: Forbidden - Admin role required Note over Attacker,Component: Result: All attacks blocked by security layers

Project Setup & Scaffolding NEW

Generated Project Structure

When you create a new Minimact project, this is the directory structure you get. Understanding where files go and what they do is crucial for development.

graph TB subgraph "Project Root" ROOT[my-app/] end subgraph "Source Code" SRC[src/] COMP[components/] PAGES[pages/] TEMPLATES[templates/] SERVICES[services/] end subgraph "Component Files" TSX["Counter.tsx Developer writes"] CS_GEN["Counter.cs Generated - do not edit"] CS_BEHIND["Counter.codebehind.cs Optional - business logic"] end subgraph "Configuration" BABEL["babel.config.js Minimact plugin"] TSCONFIG["tsconfig.json TypeScript config"] CSPROJ["MyApp.csproj C# project file"] PROGRAM["Program.cs ASP.NET setup"] end subgraph "Client Assets" WWWROOT[wwwroot/] CLIENT_JS["minimact-client.js ~5KB runtime"] STATIC[static assets] end ROOT --> SRC ROOT --> WWWROOT ROOT --> BABEL ROOT --> TSCONFIG ROOT --> CSPROJ ROOT --> PROGRAM SRC --> COMP SRC --> PAGES SRC --> TEMPLATES SRC --> SERVICES COMP --> TSX COMP --> CS_GEN COMP --> CS_BEHIND WWWROOT --> CLIENT_JS WWWROOT --> STATIC style TSX fill:#3b82f6 style CS_GEN fill:#f59e0b style CS_BEHIND fill:#10b981

Development Loop NEW

Inner Development Loop

The file-save-to-browser-update cycle happens automatically. File watchers detect changes, trigger Babel transformation, compile C#, and update the browserโ€”all in ~2-3 seconds.

sequenceDiagram participant Dev as Developer participant IDE as VS Code/Rider participant Watch as File Watcher participant Babel as Babel Plugin participant DotNet as .NET Compiler participant Server as Dev Server participant Browser Note over Dev,Browser: Developer Iteration Cycle Dev->>IDE: Edit Counter.tsx IDE->>IDE: Save file IDE->>Watch: File change detected Watch->>Babel: Transform Counter.tsx Babel->>Babel: Parse TSX AST Babel->>Babel: Generate C# code Babel->>CS_File: Write Counter.cs Note over Watch,Server: Automatic Build Watch->>DotNet: Trigger incremental build DotNet->>DotNet: Compile Counter.cs alt Compilation Error DotNet->>IDE: Show error in Problems panel IDE->>Dev: Display error else Success DotNet->>Server: Hot reload (if supported) alt Hot Reload Available Server->>Browser: Inject update (no refresh) else No Hot Reload Dev->>Browser: Manual refresh F5 end Browser->>Browser: Re-render component end Note over Dev,Browser: Changes visible in ~2-3 seconds

Hot Reload System NEW

Template-Based Hot Reload

Minimact uses a template-based hot reload system that extracts text node templates at build time and caches them on both server and client. When you edit a TSX file, only the changed templates are sent to the browser, achieving 3-5ms hot reload latency with 98% less memory than prediction-based approaches.

โšก 3-5ms Latency

Instant visual feedback on file save

๐Ÿ’พ 2KB per Component

98% memory reduction vs predictions

๐ŸŽฏ 100% Coverage

All state values, not just common ones

๐Ÿ”„ Auto State Updates

Templates automatically re-render on state change

Complete System Flow

This diagram shows the entire lifecycle: build-time template extraction, runtime initialization, hot reload updates, and automatic state change integration.

sequenceDiagram participant Dev as Developer participant Babel as Babel Plugin participant FS as File System participant Server as C# Server participant SignalR as SignalR Hub participant Client as Browser Client participant TemplateState as Template State Manager participant DOM as DOM Note over Dev,DOM: BUILD TIME - Template Extraction Dev->>Babel: Write/Edit Counter.tsx
<h1>Count: {count}</h1> Babel->>Babel: Parse JSX AST Babel->>Babel: Extract text node template
template: "Count: {0}"
bindings: ["count"] Babel->>FS: Generate Counter.g.cs Babel->>FS: Generate Counter.templates.json Note right of FS: {
"templates": {
"h1[0].text[0]": {
"template": "Count: {0}",
"bindings": ["count"],
"slots": [7]
}
}
} Note over Dev,DOM: RUNTIME - Component Initialization Client->>SignalR: RegisterComponent("Counter") SignalR->>Server: Load component Server->>FS: Read Counter.templates.json FS-->>Server: Return template map Server->>SignalR: Send template-map message SignalR->>Client: HotReload:TemplateMap Client->>TemplateState: loadTemplateMap(componentId, templates) TemplateState->>TemplateState: Cache templates in memory
(~2KB per component) Note right of TemplateState: Templates ready for
instant hot reload! Note over Dev,DOM: HOT RELOAD - Developer Edit Dev->>FS: Edit Counter.tsx
Change: "Count: {count}"
โ†’ "Counter: {count}" FS->>Babel: File change detected Babel->>Babel: Re-parse JSX Babel->>Babel: Extract new template
template: "Counter: {0}"
bindings: ["count"] Babel->>FS: Update Counter.templates.json FS->>Server: FileSystemWatcher event Server->>Server: TemplateHotReloadManager
Load new template map Server->>Server: Detect template change
OLD: "Count: {0}"
NEW: "Counter: {0}" Server->>Server: Get current state
count = 5 Server->>Server: Create template patch
{
template: "Counter: {0}",
params: [5],
bindings: ["count"]
} Server->>SignalR: Send template patch SignalR->>Client: HotReload:TemplatePatch Client->>TemplateState: applyTemplatePatch(patch) TemplateState->>TemplateState: Render: "Counter: {0}"
.replace("{0}", 5)
= "Counter: 5" TemplateState->>DOM: Update text node DOM->>DOM: Flash visual feedback Note right of DOM: ๐Ÿš€ INSTANT UPDATE!
3-5ms total latency Note over Dev,DOM: STATE CHANGE - User Interaction DOM->>Client: User clicks increment Client->>Client: useState: setCount(6) Client->>Client: Update local state Client->>TemplateState: updateState("count", 6) Client->>TemplateState: getTemplatesBoundTo("count") TemplateState-->>Client: [template for "h1[0].text[0]"] Client->>TemplateState: render(componentId, nodePath) TemplateState->>TemplateState: "Counter: {0}"
.replace("{0}", 6)
= "Counter: 6" TemplateState-->>Client: "Counter: 6" Client->>DOM: findElementByPath([0, 0]) Client->>DOM: textNode.textContent = "Counter: 6" Note right of DOM: โœจ Template auto-updates
with new state! Client->>SignalR: updateComponentState("count", 6) SignalR->>Server: Sync state to prevent stale data Server->>Server: component.SetStateFromClient("count", 6) Note right of Server: Server state in sync!
Next render will be correct

Template Extraction (Build Time)

During the Babel transformation, templates are extracted from JSX text nodes and saved to .templates.json files alongside the generated C# code.

flowchart TD A[Developer writes JSX] --> B{Babel Plugin} B --> C[Parse JSX AST] C --> D{For each JSX element} D --> E{Has text children?} E -->|Yes| F{Has expressions?} F -->|Yes| G[Extract dynamic template] F -->|No| H[Extract static template] E -->|No| D G --> I[Identify bindings
e.g., count] I --> J[Calculate slots
e.g., position 7] J --> K[Build template object] H --> K K --> L[Add to template map] L --> M{More elements?} M -->|Yes| D M -->|No| N[Generate .templates.json] N --> O[Generate .g.cs] style G fill:#4CAF50 style H fill:#2196F3 style N fill:#FF9800

Template Loading (Runtime Init)

When a component first registers, the server reads the .templates.json file and sends the template map to the client, which caches it in memory (~2KB per component).

flowchart TD A[Component registers] --> B[Server loads .templates.json] B --> C{File exists?} C -->|Yes| D[Parse JSON] C -->|No| E[Skip template features] D --> F[Cache in TemplateHotReloadManager] F --> G[Send template-map via SignalR] G --> H[Client receives message] H --> I[TemplateStateManager.loadTemplateMap] I --> J{For each template} J --> K[Store template with key
componentId:nodePath] K --> L[Build binding index
state โ†’ templates map] L --> M{More templates?} M -->|Yes| J M -->|No| N[Templates ready!] N --> O[Memory: ~2KB] N --> P[Coverage: 100%] N --> Q[Ready for hot reload] style D fill:#4CAF50 style I fill:#2196F3 style N fill:#FF9800

Hot Reload Update (Template Patch)

When you save a TSX file, the FileSystemWatcher detects the change, Babel regenerates the templates, and the server sends only the changed templates to the browser with the current state values filled in.

flowchart TD A[Developer edits TSX] --> B[FileSystemWatcher detects] B --> C[Babel re-runs] C --> D[New .templates.json generated] D --> E[Server loads new map] E --> F{Compare with cached map} F --> G{Template changed?} G -->|Yes| H[Get current component state] G -->|No| I[Skip - no update needed] H --> J["Fill template with params
template: Counter: {0}
params: [5]
= Counter: 5"] J --> K[Create TemplatePatch object] K --> L[Send via SignalR] L --> M[Client receives patch] M --> N[Render template with params] N --> O[Find DOM node by path] O --> P{Node found?} P -->|Yes| Q[Update textContent] P -->|No| R[Log warning] Q --> S[Flash visual feedback] S --> T[Update cached template] T --> U[Complete! 3-5ms total] style H fill:#4CAF50 style N fill:#2196F3 style U fill:#FF9800

State Change Integration

When useState triggers a state change, the template system automatically finds all templates bound to that state variable and re-renders them.

flowchart TD A[User triggers state change] --> B[setState called] B --> C[Update local state
context.state.set] C --> D[Check HintQueue] D --> E{Hint match?} E -->|Yes| F[Apply cached patches] E -->|No| G[Log cache miss] F --> H[Update template state
templateState.updateState] G --> H H --> I[Get templates bound to state
getTemplatesBoundTo] I --> J{Templates found?} J -->|Yes| K{For each template} J -->|No| L[Skip template update] K --> M[Render template
template.replace placeholders] M --> N[Find DOM node by path] N --> O{Node type?} O -->|Text| P[Update textContent] O -->|Element| Q{Has attribute?} Q -->|Yes| R[Update attribute] Q -->|No| S[Update textContent] P --> T{More templates?} R --> T S --> T T -->|Yes| K T -->|No| U[Sync to server
updateComponentState] U --> V[Server updates state
SetStateFromClient] V --> W[State synchronized!] style H fill:#4CAF50 style M fill:#2196F3 style U fill:#FF9800 style W fill:#9C27B0

Memory & Performance Comparison

Template-based hot reload uses 98% less memory than prediction-based caching while achieving 100% coverage of all possible state values.

โŒ Prediction-Based

  • Memory: ~100KB per component
  • Coverage: 85% (1000+ cached variations)
  • Scalability: Poor (linear growth)
  • Latency: 3-5ms (cache hit)

โœ… Template-Based

  • Memory: ~2KB per component
  • Coverage: 100% (parameterized)
  • Scalability: Excellent (constant size)
  • Latency: 3-5ms (same!)

Code-Behind Pattern NEW

When to Use Code-Behind

The code-behind pattern separates UI logic (TSX) from business logic (C#). Use .codebehind.cs for database queries, API calls, and complex server-side operations.

Counter.tsx (UI Logic)

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

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={increment}>+</button>
    </div>
  );
}

Counter.cs (Generated)

// โš ๏ธ DO NOT EDIT - Auto-generated
public partial class Counter {
  [State] private int count = 0;

  protected override VNode Render() {
    var data = UseServerData();
    return new VElement(...);
  }

  private void increment() {
    count++;
    SetState("count", count);
  }
}

Counter.codebehind.cs (Business Logic)

public partial class Counter {
  private readonly AppDbContext _db;

  public Counter(AppDbContext db) {
    _db = db;
  }

  private async Task<UserData> UseServerData() {
    return await _db.Users
      .Where(u => u.Id == UserId)
      .Include(u => u.Orders)
      .FirstOrDefaultAsync();
  }
}

Debugging Tools NEW

Debugging Across Layers

Minimact provides debugging tools for every layer: IDE breakpoints for C# server code, browser DevTools for client code, and the Playground Bridge for visual inspection.

๐Ÿ’ป IDE Debugging

Set C# breakpoints, watch variables, inspect call stacks in VS Code or Rider

๐ŸŒ Browser DevTools

Console logging, SignalR traffic inspection, DOM element inspection

๐ŸŽฏ Playground Bridge

Visual hint queue viewer, patch inspector, performance metrics

๐Ÿ“Š Error Handling

TypeScript errors in IDE, C# errors in Problems panel, runtime errors in console

Integration Points NEW

Adding Database (EF Core)

Integrating Entity Framework Core is straightforward. Install packages, create DbContext, register in DI, and use in .codebehind.cs files.

flowchart TD START[Need database access] --> INSTALL[Install EF Core packages] INSTALL --> CONTEXT[Create DbContext] CONTEXT --> MODELS[Define entity models] MODELS --> REGISTER[Register in Program.cs] REGISTER --> CONFIG["services.AddDbContext<AppDbContext>(...)"] CONFIG --> MIGRATE[Create migrations] MIGRATE --> USE[Use in component] USE --> INJECT[Inject via constructor] INJECT --> CODEBEHIND[Write queries in .codebehind.cs] CODEBEHIND --> EXAMPLE["private async Task<List<Todo>> LoadTodos() { return await _db.Todos .Where(t => t.UserId == UserId) .ToListAsync(); }"] style CONFIG fill:#3b82f6 style CODEBEHIND fill:#10b981

Full-Stack Integration

Minimact components can access the entire ASP.NET Core ecosystem through dependency injection in .codebehind.cs files.

๐Ÿ’พ Database

EF Core, Dapper, or any ORM

๐Ÿ” Authentication

ASP.NET Identity, JWT, OAuth

๐Ÿ”ง DI Services

Any registered service available

๐Ÿ“ก External APIs

HttpClient, gRPC, etc.

๐Ÿ’จ Caching

Redis, MemoryCache, etc.

๐Ÿ“ฌ Messaging

RabbitMQ, Azure Service Bus