@burdenoff/fe-libs
v2026.919.1
Published
Burdenoff frontend primitives and domain libraries
Readme
@burdenoff/fe-libs
Frontend primitives and domain libraries for all Burdenoff products.
Architecture
This is a Layer 1 package - a monolithic package with subpath exports for all primitives.
Package Structure
@burdenoff/fe-libs/
├── /workflow - Workflow primitives (Node, Canvas, Edge)
├── /tag - Tag components
├── /form - Form components
├── /button - Button primitives
└── /shared - Shared utilities (cn, types)Usage
import { Button } from '@burdenoff/fe-libs/button';
import { WorkflowNode, WorkflowCanvas } from '@burdenoff/fe-libs/workflow';
import { cn } from '@burdenoff/fe-libs/shared';Development
# Install dependencies
bun install
# Build library
bun run build
# Type check
bun run type:check
# Run all checks
bun run sanityComponents
Workflow Primitives
- WorkflowNode - Renders a workflow node with status indicators
- WorkflowCanvas - Canvas component for workflow builder with grid background
Button
- Button - Versatile button component with variants (default, destructive, outline, secondary, ghost, link)
Shared
- cn - Utility for merging Tailwind classes
shell-native (app shells only)
@burdenoff/fe-libs/shell-native is the shell-side native runtime: Capacitor
(iOS/Android), Electron desktop and PWA wiring in one entry point. App shells
import it; microfrontends never do — MFEs talk to the shell through
window.__burdenoffNativeBridge (@burdenoff/fe-libs/shared/native).
Boot it once in main.tsx, before React mounts:
import { bootNativeShell, registerDeepLinkNavigator } from '@burdenoff/fe-libs/shell-native';
const shell = bootNativeShell({
product: 'vibecontrols',
appName: 'VibeControls',
// Optional plugins are loaded ONLY through these loaders, so web-only shells
// never bundle them.
plugins: {
updater: () => import('@capgo/capacitor-updater'),
pushNotifications: () => import('@capacitor/push-notifications'),
},
push: { enabled: true, onToken: (token) => void registerDevice(token) },
runtimeHooks: { syncPendingOperations: refetchAll, saveState: flushDrafts },
});
// Inside the router:
registerDeepLinkNavigator((path) => navigate(path));
// After the first meaningful paint:
void shell.markAppReady();Boot order (each step is individually try/caught — boot never throws): preview →
OTA notifyAppReady → auth-redirect intercept → external URL opener → native
bridge + platform classes → device info → status-bar theme listener → keyboard →
Android back button → deep links → network → app-state hooks → push listeners →
splash safety timer (native) → PWA service worker (web) → desktop shell boot.
Contracts the shells and MFEs can rely on:
- Window globals —
__burdenoffNativeBridge,__burdenoffDeviceInfo,__burdenoffOpenExternal(url),__burdenoffPushToken,__burdenoffPwaInstallPrompt. - Body classes —
platform-ios | platform-android | platform-web,platform-native,platform-preview,keyboard-open.<html>carriesdata-platformand (in preview)data-native-preview. - CSS var —
--keyboard-height(0px when closed). - Window events —
burdenoff:appReady,burdenoff:appStateChange,burdenoff:networkStatusChange,burdenoff:keyboardWillShow|DidShow|WillHide|DidHide,burdenoff:pushToken,burdenoff:pwaUpdateReady,burdenoff:pwaInstalled,burdenoff:pwaInstallAvailable. The shell listens forburdenoff:statusBarTheme.
Native preview flag
?__nativePreview=ios|android|pwa|desktop renders the installed-app chrome in a
plain browser (persisted in sessionStorage, cleared with off). It is
presentation only — real plugin calls stay gated on
Capacitor.isPluginAvailable, and the flag is ignored inside a real native app.
Build-time config generators
defineCapacitorConfig(nativeConfig), defineWebManifest(nativeConfig) and
renderServiceWorker(nativeConfig, version) are pure functions (no
@capacitor/* imports) that emit each product's capacitor.config.ts,
public/manifest.json and public/sw.js from its native.config.json
(NativeConfig).
Tech Stack
- React 19
- TypeScript 5.9+
- TailwindCSS v4
- Radix UI (for accessible primitives)
- Vite 7 (for building)
