# eQuantic.UI Build Flow > 🌐 This page in: English Β· **[PortuguΓͺs](BuildFlow-pt-BR)** This document describes the eQuantic.UI build flow, demonstrating how the framework maintains **zero external dependencies** for the consumer. ## Visual Flow ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ DEVELOPMENT (source tree) β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ reconciler.ts, component.ts, etc. β”‚ β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ npm run build β”‚ (only during development) β”‚ (eQuantic.UI.Runtime) β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β–Ό dist/index.js (compiled runtime) β”‚ β”‚ boot.ts ──────importsβ”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ dotnet build β”‚ β”‚ (eQuantic.UI.Server) β”‚ β”‚ β”‚ β”‚ ResolveBunForServer target: β”‚ β”‚ β”œβ”€ Looks for Bun in: β”‚ β”‚ β”‚ Runtime.Osx64/tools/bun/ β”‚ β”‚ β”‚ Runtime.Win64/tools/bun/ β”‚ β”‚ β”‚ Runtime.Linux64/tools/bun/ β”‚ β”‚ β”œβ”€ Extracts from .zip if needed β”‚ β”‚ └─ chmod +x (Unix) β”‚ β”‚ β”‚ β”‚ BundleRuntime target: β”‚ β”‚ └─ "$(_BunPath)" build boot.ts β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β–Ό wwwroot/runtime.js (embedded in Server.dll) β”‚ β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ dotnet pack β”‚ β”‚ (eQuantic.UI.Server) β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β–Ό artifacts/packages/eQuantic.UI.Server.0.1.1.nupkg β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ CONSUMER (client project) β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ MyApp.csproj β”œβ”€ Sdk="eQuantic.UI.Sdk/0.1.1" └─ PackageReference: eQuantic.UI.Server, eQuantic.UI.Runtime β”‚ β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ dotnet restore β”‚ β”‚ β”‚ β”‚ NuGet installs packages: β”‚ β”‚ β”œβ”€ eQuantic.UI.Sdk β”‚ β”‚ β”œβ”€ eQuantic.UI.Server β”‚ β”‚ β”œβ”€ eQuantic.UI.Runtime β”‚ β”‚ β”‚ └─ (meta-package) β”‚ β”‚ └─ eQuantic.UI.Runtime.Osx64 β”‚ ◄── Bun embedded here! β”‚ └─ tools/bun/bun-darwin.zip β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ > **Which Bun?** `src/eQuantic.UI.Runtime/bun-toolchain.json` holds the version and a SHA-256 per > platform, checked on every test run. The digests prove the committed bytes are the ones the > release published; the version is verified by extracting the host's binary and running it, because > a manifest nobody compares against the thing it describes drifts from it. > > All six platform packages (`Osx64`, `OsxArm64`, `Win64`, `WinArm64`, `Linux64`, `LinuxArm64`) carry > the same build; a different Bun per architecture is how you get a bundle that only fails on one > person's machine. > > Updating it: replace the `.zip` files, run the tests once with `EQ_UPDATE_BUN_MANIFEST=1`, and read > the diff. A version that moved with digests that did not is a mistake, and so is the reverse. β”‚ β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ dotnet build β”‚ β”‚ β”‚ β”‚ SDK.targets executes: β”‚ β”‚ β”‚ β”‚ 1. ResolveBunZipPath β”‚ β”‚ └─ $(PkgeQuantic_UI_Runtime_ β”‚ β”‚ Osx64)/tools/bun/*.zip β”‚ β”‚ β”‚ β”‚ 2. EnsureBunExtracted β”‚ β”‚ β”œβ”€ Unzip if needed β”‚ β”‚ └─ chmod +x (Unix) β”‚ β”‚ β”‚ β”‚ 3. ResolveBunPath β”‚ β”‚ └─ Defines $(BunPath) β”‚ β”‚ β”‚ β”‚ 4. InstallBunPackages β”‚ β”‚ β”œβ”€ β†’ bun add β”‚ β”‚ └─ Symlink node_modules β”‚ β”‚ β”‚ β”‚ 5. CompileEQuanticUI β”‚ β”‚ └─ dotnet eqc.dll ... --bun β”‚ β”‚ "$(BunPath)" β”‚ β”‚ β”‚ β”‚ 6. CopyEQuanticRuntime β”‚ ◄── Runtime.js deployment β”‚ └─ Copy from Runtime package β”‚ β”‚ to wwwroot/_equantic/ β”‚ β”‚ β”‚ β”‚ └─ "$(BunPath)" x β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β–Ό wwwroot/_equantic/ β”œβ”€ runtime.js (from Runtime package) └─ *.js (compiled components) β”‚ β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ dotnet run β”‚ β”‚ β”‚ β”‚ Server serves: β”‚ β”‚ β”œβ”€ runtime.js (from Server.dll) β”‚ β”‚ └─ *.js (from wwwroot/_equantic)β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β–Ό Browser loads application ``` ## Bun Source by Component | Component | Bun Source | | -------------------------- | --------------------------------------------------------- | | **Server** (package build) | `eQuantic.UI.Runtime.{OS}/tools/bun/` (source tree) | | **SDK** (consumer) | `$(PkgeQuantic_UI_Runtime_{OS})/tools/bun/` (NuGet cache) | ## Consumer Requirements The consumer only needs: - .NET SDK 10.0 - `dotnet restore` + `dotnet build` **No Node.js, npm, or global Bun installation required.** ## Key Files | File | Responsibility | | --------------------- | ---------------------------------------------------------------- | | `Sdk/Sdk.targets` | Resolves Bun, installs `` items, compiles components | | `Server.csproj` | Resolves Bun from source tree, bundles runtime.js | | `Runtime.{OS}.csproj` | Packages Bun executable for each platform | ## MSBuild Targets (Execution Order) ### In SDK (consumer) 1. **ResolveBunZipPath** - Finds the Bun .zip in NuGet cache 2. **EnsureBunExtracted** - Extracts the executable if needed 3. **ResolveBunPath** - Defines `$(BunPath)` for later use 4. **InstallBunPackages** - Installs `` items via `bun add` (see [BunPackage](BunPackage)) 5. **CompileEQuanticUI** - Transpiles C# β†’ TypeScript β†’ JavaScript 6. **CopyEQuanticRuntime** - Copies runtime.js from Runtime package to wwwroot/\_equantic/ ### In Server (development) 1. **ResolveBunForServer** - Finds Bun in source tree 2. **BundleRuntime** - Compiles boot.ts β†’ runtime.js ## Package Architecture & Self-Containment eQuantic.UI follows a **self-contained package architecture** where each package manages its own artifacts. The SDK acts as an orchestrator, referencing other packages via NuGet's `$(Pkg*)` properties. ### Architecture Principles **Before (Problematic):** ``` SDK Package ❌ β”œβ”€ Embedded runtime.js (copied from Runtime) └─ Embedded *.cs files (copied from Components) ``` Problems: tight coupling, version conflicts, artifact duplication **After (Correct):** ``` Runtime Package βœ… └─ tools/runtime/runtime.js (self-contained) Components Package βœ… └─ tools/source/*.cs (self-contained) SDK Package βœ… └─ References other packages via $(PkgeQuantic_UI_*) ``` Benefits: decoupling, correct versioning, no duplication ### Runtime.js Deployment **1. Packaging (Development)** During `dotnet pack` of **eQuantic.UI.Runtime**: ```xml ``` The Runtime package embeds its own compiled JavaScript artifact. **2. Deployment (Consumer Build)** During `dotnet build`, the SDK's **CopyEQuanticRuntime** target executes: ```xml <_RuntimeSourcePath Condition="'$(PkgeQuantic_UI_Runtime)' != ''"> $(PkgeQuantic_UI_Runtime)/tools/runtime/runtime.js <_RuntimeSourcePath Condition="'$(_RuntimeSourcePath)' == ''"> $(MSBuildThisFileDirectory)../../eQuantic.UI.Runtime/dist/index.js <_RuntimeDestPath>$(MSBuildProjectDirectory)/$(EQuanticOutputPath)runtime.js ``` ### Components Source Deployment **1. Packaging (Development)** During `dotnet pack` of **eQuantic.UI.Components**: ```xml ``` The Components package embeds its own C# source files for compiler type resolution. **2. Compilation (Consumer Build)** During `dotnet build`, the SDK's **CompileEQuanticUI** target executes: ```xml <_StandardComponentsDir Condition="'$(PkgeQuantic_UI_Components)' != ''"> $(PkgeQuantic_UI_Components)/tools/source <_StandardComponentsDir Condition="'$(_StandardComponentsDir)' == ''"> $(MSBuildThisFileDirectory)../../eQuantic.UI.Components ``` ### Key Architectural Benefits - **Decoupling**: SDK doesn't embed artifacts from other packages - **Correct Versioning**: Consumer can use Runtime 0.1.3 + SDK 0.1.2 independently - **No Duplication**: Each artifact exists only in its source package - **Flexibility**: Packages evolve independently without tight coupling - **Clear Interface**: SDK references packages via well-defined NuGet properties (`$(Pkg*)`) - **Development Fallback**: Source tree paths work for framework development ### Runtime Single Bundle Strategy The Runtime uses **Vite's `inlineDynamicImports: true`** configuration to create a single bundle: ```typescript // eQuantic.UI.Runtime/vite.config.ts export default defineConfig({ build: { rollupOptions: { output: { inlineDynamicImports: true, // ← Creates single bundle }, }, }, }); ``` **Why Single Bundle?** - **Simplified Deployment**: Only one file to copy (runtime.js) - **No Chunk Management**: Avoids issues with separate logger-_.js, error-overlay-_.js chunks - **Reliable Distribution**: Guaranteed that all runtime features (logger, error overlay) are included - **Small Size**: ~49KB minified with all features included Without this, Vite would create separate chunks for dynamic imports, and the SDK would need to copy multiple files with hash-based names.