TypeFlow is a professional E2E Type-Safety Architecture DDD-based template for building lightweight desktop applications using .NET 8 and TypeScript, React (Vite), Wolverine and Photino, eliminating network overhead (No HTTP/SignalR) in favor of direct IPC communication and the No-Ceremony Messaging pattern.
This template was created to eliminate the most common cause of errors in hybrid apps, the "I thought the backend was sending this field as a number, but it came back as string/null", and to improve the developer experience by providing them a ready-made template for developing and building apps.
| Problem with standard hybrid applications | Solution in TypeFlow |
|---|---|
Model Mismatch: Changing the type in C# (e.g. int to string) causes runtime errors on the front end, which are only detected by the user. |
Build-time Synchronization: Automatic generation of TS interfaces from C# records via TypeGen. Frontend compilation error immediately after a change in the backend. |
| Network Overhead: Unnecessary setup of a local HTTP server, TCP/IP stack overhead, problems with occupied ports and CORS. | Native IPC Communication: Direct interprocess communication (Photino). Elimination of the network layer in favor of native data transfer speeds. |
| Boilerplate Fatigue: Each new feature requires writing controllers, routes, mappings, and fetchers. | No-Ceremony Messaging: Using the Mediator (Wolverine) pattern. You add a contract, and the handler is automatically found. No unnecessary "pipe" code. |
| Data Corruption: The frontend "trusts" the TS types, but the backend sends incomplete or invalid JSON, which breaks the UI state. | Zod Runtime Guard: Every message arriving at the front end is validated against the Zod schema. The application rejects invalid data before processing it. |
| Vendor Lock-in: Strong coupling of business logic with a specific windowing framework (e.g. Electron only). | Agnostic Dispatcher Architecture: Business logic is isolated (DDD). You can swap Photino for Electron or Tauri in a day without touching Domain. |
| Silent Handler Failures: Forgetting to implement a handler for a new request, which only becomes apparent during manual testing. | Enforced Unit Testing: Automated tests verify that each contract has an assigned handler and that the DI container is complete before the application starts. |
We use native IPC (Inter-Process Communication) provided by Photino, which eliminates the HTTP protocol overhead and the need to manage local ports.
Domain— Contracts: C# records defining requests and responses.Application— Business Logic: Wolverine Handlers (Pure Functions).Infrastructure– Implementations: This place is for implementing functions such as File Access, Databases, and External APIs.Bridge— Type Generator: Automatic type synchronization C# -> TypeScript.Presentation— Host: Photino (WebView2, WebKit, WebKitGTK) + Universal DispatcherFrontend— UI: React + Vite + TypeScript.Tests– Unit Tests:
sequenceDiagram
participant UI as React (Frontend)
participant Bridge as Photino Bridge (C#)
participant Bus as Wolverine (Mediator)
participant App as Application Handler
Note over UI, App: Fast IPC Channel (No HTTP/TCP)
UI->>Bridge: window.external.sendMessage(JSON)
rect rgb(240, 240, 240)
Bridge->>Bus: Dispatch(Request)
Bus->>App: Execute Handle()
App-->>Bus: Return Response
end
Bus-->>Bridge: Process Completion
Bridge-->>UI: Invoke JS Callback (Result)
Note right of UI: Type-Safe Response Received
graph TD
subgraph Standard_Approach ["Traditional Hybrid (HTTP/Local Server)"]
direction TB
UI1[React Frontend] -->|1. Fetch API| Net[Network Stack / Loopback]
Net -->|2. TCP/IP Handshake| FW[Local Firewall / OS Ports]
FW -->|3. HTTP Request| Srv[Kestrel / Express Server]
Srv -->|4. Middleware / Routing| Logic1[Business Logic]
Logic1 -->|5. JSON Serialization| Srv
Srv -->|6. HTTP Response| UI1
style Standard_Approach fill:#fff1f1,stroke:#d32f2f
end
subgraph TypeFlow_Approach ["TypeFlow (Native IPC)"]
direction TB
UI2[React Frontend] -->|1. Native Message| Bridge[Photino Bridge]
Bridge -->|2. In-Memory Dispatch| Bus[Wolverine / Mediator]
Bus -->|3. Direct Execution| Logic2[Business Logic]
Logic2 -->|4. Direct Return| UI2
style TypeFlow_Approach fill:#f1faff,stroke:#0288d1
end
For the template to work and build, you must have: - .NET 8 SDK - Node.js & pnpm - WebView2/WebKit/WebKitGTK Runtime
- Definition: Add Request record in Domain.
- Synchronization: Run Bridge to have types in React.
- Implementation: Add a static Handle method in Application.
- Call: Use BridgeClient.call('Request', { ... }) in React.
This template is designed to detect errors during the compilation and build phase, rather than during runtime. The system is based on four pillars:
- Wolverine: Generates code that connects messages to handlers during build. Unit tests in the Tests project ensure that:
- Each query (Request/Respond) has an assigned Handler.
- The DI (Dependency Injection) container is complete and no dependencies have been missed.
- TypeGen (C# ↔ TypeScript): We use TypeGen to automatically generate TypeScript interfaces from C# records in Domain.
- Guarantee: Changing a field name in the backend immediately causes a React compile error, eliminating typos and model mismatches.
- Zod (Schema Validation): We use Zod as a validation layer at the entrance to the Frontend.
- Runtime Guard: Even if the TS types match, Zod checks the actual shape of the incoming JSON. If data is corrupted or incomplete, the application responds immediately, protecting the UI state from unforeseen errors.
- Full-Stack Traceability: By combining these tools, the workflow is completely secure.
C# Record → TypeGen → Zod Schema → React Component
Each part of this chain is verified automatically.
This project is released under the MIT License. You are free to use, modify, and distribute it commercially, provided you retain the author's attribution.
Adam Plejznerowski
LinkedIn: https://www.linkedin.com/in/adam-plejznerowski-64598636a/