Monorepo Context Architecture
Monorepo Svelte 5 Context Boundary Architecture
Section titled “Monorepo Svelte 5 Context Boundary Architecture”This document summarizes the root cause of the “missing AppHeader context” issue we encountered, and outlines best practices for our build setup and component design moving forward in the vyasa-ui and vyasa-apps ecosystem.
The Root Cause: Svelte 5 svelte-package Context Loss
Section titled “The Root Cause: Svelte 5 svelte-package Context Loss”The core issue was a combination of how Svelte 5 currently handles the Context API across package boundaries, and how Vite resolves the Svelte runtime in a monorepo workspace.
- Vite Runtime Duplication: When running
bun run devinvyasa-apps/apps/platform, Vite initially spun up two separate instances of the Svelte runtime—one for theplatformapp code, and one for the pre-packaged@project-vyasa/vyasa-uicode innode_modules. - Context Map Isolation: Because the runtimes were duplicated,
setContext('theme')in theplatformapp’s component tree saved the context to one map, whilegetContext('theme')inside the compiledAppHeader.sveltelooked for the context in a different, isolated map. This causedthemeCtxto silently evaluate toundefined. - Snippet Scoping: In Svelte 5, snippets capture context from their declaration site (in this case,
PlatformShell), but when executing inside a component from a different package (AppShell), the context boundary could not be traversed correctly due to the runtime duplication.
Build Setup Changes
Section titled “Build Setup Changes”To prevent this class of bugs permanently, the following build configuration rule must be enforced across all Svelte applications in the monorepo.
1. Unified Svelte Runtime via Vite Deduplication
Section titled “1. Unified Svelte Runtime via Vite Deduplication”Any Vite application (e.g. vyasa-apps/apps/platform) that consumes a local workspace Svelte package MUST explicitly instruct Vite to deduplicate Svelte. This forces Vite to use a single runtime tree across all workspace boundaries.
Requirement in vite.config.ts:
export default defineConfig({ resolve: { dedupe: ['svelte'] // Critical for Context API across workspace packages }, optimizeDeps: { exclude: ['@project-vyasa/vyasa-ui'] }});Component Design Changes
Section titled “Component Design Changes”While Vite deduplication solves the runtime split, components published via svelte-package should be designed to be resilient to context loss.
1. Explicit Prop Fallbacks for Context (Dependency Injection)
Section titled “1. Explicit Prop Fallbacks for Context (Dependency Injection)”When building core layout components in vyasa-ui that rely on Context API (like AppHeader, ActivityBar, etc.), always allow the consumer to pass the context explicitly via a prop as an “escape hatch”.
Example Implementation (already applied to AppHeader):
<script lang="ts"> interface Props { // ... themeContext?: any; // Escape hatch for cross-package context loss } let { themeContext }: Props = $props();
// Priority: Explicit Prop > Fallback Context const defaultThemeCtx = getContext<any>('theme'); const themeCtx = $derived(themeContext || defaultThemeCtx);</script>2. Extensible Snippet Slots
Section titled “2. Extensible Snippet Slots”Avoid hardcoding the right or left sides of foundational layout components if they contain business logic. Exposing named snippets allows consuming apps to inject custom buttons without needing to fork the component.
Example (already applied to AppHeader):
<script lang="ts"> interface Props { // ... headerRight?: import('svelte').Snippet; }</script>
<div class="header-right"> {@render headerRight?.()} <!-- Allows platform app to inject custom actions --></div>Summary
Section titled “Summary”The architecture is now extremely robust.
vyasa-apps/apps/platformuses Vite deduplication and explicit prop injection (themeContext={themeContext}) to ensure theAppHeaderrenders perfectly.vyasa-ui’sAppHeaderis now safely encapsulated and resilient to monorepo dev-server edge cases.- All custom theme buttons were successfully removed from
ViewerAppBar.svelte, restoring clean separation of concerns.