@fde-desktop/fde-core
v0.4.35
Published
Core library for building FDE Desktop environments
Readme
@fde-desktop/fde-core
Core library for building FDE Desktop environments. This package provides everything needed to create desktop-like applications in React:
- UI Components: Desktop, Window, Taskbar, Launcher, ContextMenu, etc.
- Core Apps: Files, Settings, Notepad, Image Viewer, PDF Viewer, etc.
- Stores: Zustand stores for desktop, settings, custom apps
- Hooks: 30+ hooks for app management, notifications, icons, file system, etc.
- Domain Entities: createWindow, createDesktopIcon, createLauncherFolder
- Infrastructure: IndexedDBFileSystem, DockerFileSystemAdapter, FdeApiAdapter
- Types & Utilities: Full TypeScript types and helper functions
Installation
npm install @fde-desktop/fde-core
# or
yarn add @fde-desktop/fde-core
# or
bun add @fde-desktop/fde-coreYou also need to import the package styles in your entry point:
import '@fde-desktop/fde-core/dist/index.css';This single import includes all required styles (Mantine, component styles, etc.).
Peer Dependencies
react^19.0.0react-dom^19.0.0
Quick Start
The simplest way is to use the FdeDesktop component:
import { FdeDesktop, type AppRegistryEntry } from '@fde-desktop/fde-core';
import '@fde-desktop/fde-core/dist/index.css';
// Define your custom apps (optional)
const myApps: Record<string, AppRegistryEntry> = {
'my-app': {
loader: () => import('./MyApp'),
appName: 'My App',
},
};
function App() {
return <FdeDesktop customApps={myApps} />;
}Core apps (Files, Settings, Notepad, etc.) are loaded automatically. Your custom apps are merged with the core registry.
FdeDesktop Props
<FdeDesktop
customApps={userApps} // Optional: your custom apps
defaultWallpaper={wallpaperUrl} // Optional: default wallpaper URL
initialApp="welcome" // Optional: app ID to open on start
mode="dark" // Optional: force 'light' | 'dark' theme
prefetchLoaders={[ // Optional: preload lazy apps
{ id: 'dos-emulator', loader: () => import('./DosEmulatorApp') },
]}
>
{/* Optional: extra desktop content */}
</FdeDesktop>Creating a Custom App
Step 1: Create the component
Every app receives WindowContentProps — a window entity and a notifyReady callback:
// MyApp.tsx
import { type FC, useEffect } from 'react';
import type { WindowContentProps } from '@fde-desktop/fde-core';
const MyApp: FC<WindowContentProps> = ({ window: win, notifyReady }) => {
const { filePath } = (win?.contentData ?? {}) as { filePath?: string };
useEffect(() => {
notifyReady?.({});
}, [win, notifyReady]);
return (
<div>
<h1>My App</h1>
{filePath && <p>Opening: {filePath}</p>}
</div>
);
};
export default MyApp;Step 2: Register the app
// App.tsx
import { FdeDesktop, type AppRegistryEntry } from '@fde-desktop/fde-core';
const myApps: Record<string, AppRegistryEntry> = {
'my-app': {
loader: () => import('./MyApp'),
appName: 'My App',
isLazy: true,
defaultWidth: 800,
defaultHeight: 600,
minWidth: 640,
minHeight: 480,
fcIcon: 'FcFolder',
},
};
function App() {
return <FdeDesktop customApps={myApps} />;
}Step 3: Open the app programmatically
import { useOpenApp } from '@fde-desktop/fde-core';
function MyButton() {
const openApp = useOpenApp();
return (
<button onClick={() => openApp('my-app', { contentData: { filePath: '/docs/readme.md' } })}>
Open My App
</button>
);
}Step 4: Add a menu bar (optional)
// MyAppMenuBar.tsx
import { type FC, memo } from 'react';
import { AppMenuBar } from '@fde-desktop/fde-core';
import type { MenuBarComponentProps, AppMenuElement } from '@fde-desktop/fde-core';
export const MyAppMenuBar: FC<MenuBarComponentProps> = memo(({ windowId, onExit }) => {
const elements: AppMenuElement[] = [
{
type: 'menu',
label: 'File',
items: [
{ type: 'item', label: 'Exit', icon: 'FcLeave', onClick: onExit },
],
},
];
return <AppMenuBar elements={elements} />;
});
MyAppMenuBar.displayName = 'MyAppMenuBar';Register it alongside the component:
const myApps: Record<string, AppRegistryEntry> = {
'my-app': {
loader: () => import('./MyApp'),
menuBarLoader: () => import('./MyAppMenuBar').then(m => ({ default: m.MyAppMenuBar })),
appName: 'My App',
isLazy: true,
},
};Exports
UI Components
import {
FdeDesktop,
Desktop,
DesktopIcon,
Window,
AppMenuBar,
DynamicMenuBarRenderer,
Taskbar,
Launcher,
TaskbarContextMenu,
LanguageSelector,
ContextMenu,
CreateItemContextMenu,
ThemeProvider,
useTheme,
DEFAULT_FDE_THEME,
FdeProvider,
useFdeContext,
AppReadyProvider,
useAppReady,
initRegistry,
getAppComponent,
getMenuBarComponent,
getMenuBarBuilder,
isLazyApp,
getAppName,
registerComponents,
} from '@fde-desktop/fde-core';Apps (Core Apps)
import {
FilesApp,
SettingsApp,
NotesApp,
ImageViewerApp,
PdfApp,
UploaderApp,
MenuEditApp,
DeviceInfoApp,
CalendarApp,
TerminalApp,
CodeServerApp,
CORE_APPS,
CORE_APP_IDS,
DEFAULT_WINDOW_DIMENSIONS,
// Menu bars
NotesMenuBar,
SettingsMenuBar,
PdfMenuBar,
ImageViewerMenuBar,
MenuEditMenuBar,
TerminalMenuBar,
} from '@fde-desktop/fde-core';Lazy-Loaded App Components
import {
FilesAppLazy,
NotesAppLazy,
ImageViewerAppLazy,
PdfAppLazy,
MenuEditAppLazy,
UploaderAppLazy,
SettingsAppLazy,
DeviceInfoAppLazy,
CalendarAppLazy,
CreateItemAppLazy,
} from '@fde-desktop/fde-core';Shared Components
import {
AppIcon,
VscIcon,
AppLoading,
AppEmptyState,
LanguageFlag,
CollapsibleSection,
FileIcon,
DirtyIndicator,
ColorPicker,
CreateItemApp,
DownloadProgress,
FilePickerApp,
FilePickerModal,
FolderPicker,
IconColorPicker,
SettingsSection,
ExternalLinkApp,
CustomAppLoader,
CustomAppLoadingScreen,
CustomAppNotSupported,
CustomAppOffline,
PortraitWarning,
} from '@fde-desktop/fde-core';Stores
import {
useDesktopStore,
useSettingsStore,
useCustomAppStore,
useAppTempMemoryStore,
useCloseModalStore,
fileSystem,
resetFileSystem,
resetWindowManager,
getPersistedThemeMode, // Read theme from localStorage before React mounts
} from '@fde-desktop/fde-core';
// Desktop state
const { windows, openWindow, closeWindow } = useDesktopStore();
// Settings
const { wallpaper, theme, language, setThemeMode } = useSettingsStore();
// Custom apps (Docker)
const { customApps, loadCustomApps } = useCustomAppStore();Hooks
import {
// App management
useOpenApp,
useAppName,
useFdeApi,
// UI
useClock,
useSystemTheme,
useAnimationDuration,
useAdaptiveDimensions,
useTaskbarHeight,
useTaskbarContextMenu,
useContextMenu,
useCollapsible,
useSearchFilter,
// Notifications
useNotifications,
// File system
useDownload,
useResolvedUrl,
// Icons
useFcIcon,
useFcIconElement,
useFiIcon,
useFiIconElement,
useVscIcon,
useVscIconElement,
// Drag & Drop
DragDropProvider,
useDroppableArea,
useDraggableItem,
useDragDropState,
// Window
useWindowButtonRegistry,
// Theme & Language
useApplyFont,
useFontDownload,
useLanguageSync,
// State
useIsDirty,
useCloseInterceptor,
// Device
useDeviceDetection,
// Updates
useAppUpdate,
// Custom apps
useCustomAppHMR,
useCustomAppLifecycle,
// Lifecycle
useFolderName,
} from '@fde-desktop/fde-core';Domain Entities
import {
createWindow,
createDesktopIcon,
createLauncherFolder,
createPredefinedLauncherFolder,
updateLauncherFolder,
createFolder,
createFile,
} from '@fde-desktop/fde-core';
const win = createWindow({
title: 'My Window',
appId: 'my-app',
x: 100,
y: 100,
width: 800,
height: 600,
});
const icon = createDesktopIcon({
appId: 'files',
x: 20,
y: 20,
name: 'Files',
fcIcon: 'FcFolder',
});Infrastructure
import {
IndexedDBFileSystem,
DockerFileSystemAdapter,
FdeApiAdapter,
initializeFdeApi,
getFdeApi,
WindowManagerAdapter,
DefaultThemeProvider,
toMantineTheme,
JsDosAdapter,
prefetchApps,
migrateStorage,
SUPPORTED_LANGUAGES,
DEFAULT_LANGUAGE,
} from '@fde-desktop/fde-core';Types & Interfaces
import type {
// App types
AppEntry,
AppRegistryEntry,
AppComponent,
WindowContentProps,
MenuBarBuilder,
MenuBarComponent,
MenuBarComponentProps,
// Window types
WindowEntity,
WindowInput,
WindowProps,
// File system types
FileSystemNode,
FileNode,
FolderNode,
IFileSystem,
// Desktop types
DesktopIconEntity,
DesktopIconInput,
DesktopState,
NotificationItem,
ClipboardState,
// Theme types
Theme,
ThemeMode,
FdeTheme,
CustomThemeColors,
IThemeProvider,
// Other
AppMenuElement,
MenuItem,
CreateFolderOptions,
FdeApi,
LauncherFolder,
LauncherFolderInput,
SupportedLanguage,
} from '@fde-desktop/fde-core';Utilities
import {
// UUID
generateUUID,
uuidv4,
// Runtime detection
getRuntime,
isDocker,
isBrowser,
isElectron,
isDev,
// Formatting
formatBytes,
getFileExtension,
getMimeTypeFromExtension,
getAppIdForMime,
// File system
sortNodes,
sortDesktopIcons,
buildBreadcrumbs,
// Version
isNewerVersion,
// Browser
clearBrowserData,
// DOM
waitForContainer,
// URL
getBaseUrl,
resolveUrl,
// Hash
hashBlob,
// Colors
getFourRandomColors,
} from '@fde-desktop/fde-core';Constants
import {
DEFAULT_WINDOW_DIMENSIONS,
ICON_COLUMN_WIDTH,
ICON_ROW_HEIGHT,
ICON_MARGIN,
TASKBAR_HEIGHT,
DEFAULT_VIEWPORT_WIDTH,
DEFAULT_VIEWPORT_HEIGHT,
BREAKPOINTS,
ANIMATION_DURATION,
AVAILABLE_FONTS,
FONT_STACKS,
GOOGLE_FONTS_HREF,
PRESET_COLORS,
PRESET_ICONS,
DEFAULT_LAUNCHER_FOLDERS,
CUSTOM_APPS_FOLDER_ID,
APP_IDS,
DEFAULT_FDE_THEME,
} from '@fde-desktop/fde-core';i18n
import { i18n } from '@fde-desktop/fde-core';
import { I18nextProvider } from 'react-i18next';
function App() {
return (
<I18nextProvider i18n={i18n}>
<FdeDesktop />
</I18nextProvider>
);
}Core Apps
| App ID | Name | Description |
| -------------- | ------------ | ----------------------- |
| files | Files | File browser |
| settings | Settings | System settings |
| notepad | Notepad | Text editor (TipTap v3) |
| image-viewer | Image Viewer | Image viewer |
| pdf | PDF Viewer | PDF viewer |
| uploader | Uploader | File uploader |
| device-info | Device Info | System information |
| calendar | Calendar | Calendar widget |
| menuedit | MenuEdit | Launcher folder editor |
| terminal | Terminal | Terminal emulator |
| code-server | VS Code | VS Code in browser |
Runtime Detection
import { getRuntime, isDocker, isBrowser, isElectron, isDev } from '@fde-desktop/fde-core';
const runtime = getRuntime(); // 'browser' | 'docker' | 'electron'
if (isDocker()) {
// Docker-specific code (API-based file system)
}
if (isBrowser()) {
// Browser-only code (IndexedDB file system)
}
if (isElectron()) {
// Electron desktop app code
}Docker Integration
For Docker-based deployments:
import { DockerFileSystemAdapter, FdeApiAdapter, initializeFdeApi } from '@fde-desktop/fde-core';
initializeFdeApi();
const dockerFs = new DockerFileSystemAdapter();
// Custom app hot-reload
useCustomAppHMR();Example App
The main repository's src/ directory contains a complete example application that demonstrates how to use this package. It includes:
- WelcomeApp: Personal portfolio/profile app
- LinkedinApp / GithubApp: External link apps
- DosEmulatorApp: DOS game emulator using js-dos
- Custom App Registry: Shows how to register custom apps
See the main repository for the complete example.
License
Apache-2.0
