Platform Differences
Mythetech.Framework supports both Desktop and WebAssembly platforms. This guide covers the key differences.
Feature Availability
| Feature | Desktop | WebAssembly |
|---|---|---|
| UI Components | ✅ | ✅ |
| MessageBus | ✅ | ✅ |
| Plugins (Dynamic Load) | ✅ | ❌ |
| Plugins (Static Reference) | ✅ | ✅ |
| MCP Tools | ✅ | ✅ |
| MCP stdio Transport | ✅ | ❌ |
| Persistent Storage | LiteDB | localStorage |
| File Dialogs | Native | WASM File API |
| Link Opening | Native | Browser |
Plugin Loading
Desktop
Plugins can be loaded dynamically at runtime:
// Load from directory
await app.Services.UsePluginsAsync("plugins");This scans the directory, loads assemblies, and discovers plugins automatically.
WebAssembly
Dynamic assembly loading isn't supported in WASM. Plugins must be referenced at compile time:
// Add project reference in .csproj
<ProjectReference Include="..\MyPlugin\MyPlugin.csproj" />
// Load the referenced assembly
await app.Services.UsePluginAsync(typeof(MyPlugin.Manifest).Assembly);Storage
Desktop (LiteDB)
- File-based NoSQL database
- Stored in application data directory
- Supports complex object graphs
- No size limits (filesystem limited)
- Transactions supported
// Works with complex types
await storage.SetAsync("user", new User
{
Profile = new Profile { /* nested data */ }
});WebAssembly (localStorage)
- Browser localStorage API
- Serialized as JSON
- ~5MB typical limit
- No transactions
- Cleared with browser data
// Same API, different implementation
await storage.SetAsync("user", simpleUserData);WARNING
Keep WebAssembly storage data simple and small due to localStorage limitations.
File Operations
Desktop
Full access to native file dialogs:
// Open file dialog
var file = await fileService.OpenFileAsync(new OpenFileOptions
{
Title = "Select a file",
Filters = [new("Text Files", "*.txt")]
});
// Save file dialog
await fileSaveService.SaveFileAsync("output.txt", data);WebAssembly
Uses browser File System Access API:
// Same interface, browser implementation
var file = await fileService.OpenFileAsync(options);
// Download-style save
await fileSaveService.SaveFileAsync("output.txt", data);TIP
The WASM implementation uses KristofferStrube.Blazor.FileSystemAccess for File System Access API integration.
Link Opening
Desktop
Opens in system default browser:
linkOpenService.OpenUrl("https://example.com");
// Opens in Chrome, Firefox, Edge, etc.WebAssembly
Opens in browser context:
linkOpenService.OpenUrl("https://example.com");
// Opens in new tab (same browser)MCP
Desktop
Full MCP support with stdio transport:
builder.Services.AddMcp(options =>
{
options.ServerName = "MyApp";
options.ServerVersion = "1.0.0";
});
// Start MCP server
await messageBus.PublishAsync(new EnableMcpServerMessage());WebAssembly
Tools can be registered but stdio transport isn't available:
// Tools can be registered
builder.Services.AddMcpTools();
// But no transport available (HTTP transport planned)Detecting Platform
// Check runtime platform
if (OperatingSystem.IsBrowser())
{
// WebAssembly-specific code
}
else
{
// Desktop-specific code
}Or use the Framework's platform service:
[Inject]
private IPlatformService Platform { get; set; }
if (Platform.IsDesktop)
{
// Desktop features
}Best Practices
- Check for null services — Platform-specific services may be null
- Use abstractions — Prefer
ILinkOpenServiceover direct APIs - Test on both platforms — Behavior can differ subtly
- Size storage carefully — WASM has limited localStorage
- Plan for missing features — Gracefully degrade when features aren't available
// Example: Graceful degradation
if (fileSaveService != null)
{
await fileSaveService.SaveFileAsync(filename, data);
}
else
{
// Fallback: show data in dialog for copy/paste
await dialogService.ShowMessageBox("Export", dataAsString);
}