Co-authored-by: Artur <145776561+arturict@users.noreply.github.com> Co-authored-by: arturict <arturict@users.noreply.github.com> Co-authored-by: Thomas <thomas@ajnart.fr> Co-authored-by: Afonso Jorge Ramos <afonsojorgeramos@gmail.com> Co-authored-by: Danura30082 <danura30082+github@gmail.com> Co-authored-by: Kushie <122986913+kushiemoon-dev@users.noreply.github.com> Co-authored-by: ajnart <thomas@ajnart.fr> Co-authored-by: ajnart <thomas@ajnart.dev> Co-authored-by: chenjun <chenjun@foxmail.com> Co-authored-by: Wikibear <wikibear@users.noreply.github.com> Co-authored-by: Bergasha <bergasha@gmail.com> Co-authored-by: leafyelin <43306196+leafyelin@users.noreply.github.com> Co-authored-by: Lucas Araujo <lucas.lra@gmail.com> Co-authored-by: GreenMonito <86085570+GreenMonito@users.noreply.github.com> Co-authored-by: Nerdy-Technician <roffo@nerdy-technician.social> Co-authored-by: Jun <34545896+jcstrong@users.noreply.github.com> Co-authored-by: Edmond Abraham <54119952+gitedmond@users.noreply.github.com> Co-authored-by: thrawnx <tight.bulb9384@fastmail.com> Co-authored-by: Chris <58918656+nordada@users.noreply.github.com> Co-authored-by: yi111 <153097222+Yi-111-a@users.noreply.github.com> Co-authored-by: Yanis <naamaneyanis@gmail.com> Co-authored-by: Wikibear <me@sej.de> Co-authored-by: alessiottavo <93441886+alessiottavo@users.noreply.github.com>
6.9 KiB
Homarr architecture
Contents
Applications and runtimes
| Path | Role |
|---|---|
apps/nextjs |
Main Next.js application and HTTP APIs on port 3000 |
apps/docs |
Next.js and Fumadocs documentation site on port 3003 |
apps/tasks |
Cron-job initialization and scheduling runtime; it does not expose the old port-3002 API |
apps/websocket |
tRPC WebSocket subscriptions on port 3001 |
apps/workshop |
Go/PocketBase Workshop service and provider integration |
pnpm dev runs only @homarr/nextjs. Use pnpm --filter @homarr/tasks dev, pnpm --filter @homarr/websocket dev, or pnpm dev:docs when a task needs those runtimes.
In production, apps/nextjs/src/instrumentation-node.ts starts the tasks and WebSocket runtimes inside the Node process. Nginx listens on port 7575, proxies /websockets to port 3001, and sends other traffic to port 3000. Redis can run internally or externally.
Package map
Foundation and domain
core: environment validation, database and Redis factories, logging, infrastructure.definitions: domain enums, integration definitions, widget kinds, permissions.common: shared utilities with environment-specific entrypoints. Search it before adding helpers.validation: shared Zod schemas.server-settings: typed server-setting keys and access.
Data, identity, and transport
db: Drizzle schemas, queries, migrations, and three database drivers.auth: Auth.js/NextAuth configuration, sessions, providers, and API keys.api: tRPC routers, contexts, MCP metadata extraction, OpenAPI, and client/server entrypoints.redis: Redis clients, pub/sub channels, and caches.cron-jobs-core,cron-jobs,cron-job-status: scheduling primitives, job implementations, and status transport.
Backends and external systems
integrations: typed clients for external applications.request-handler: shared server request flows.docker,ping,image-proxy,icons,analytics: bounded infrastructure capabilities.custom-widgets: Custom JSX v2 schema, validation, runtime, and security contracts.workshop: TypeScript Workshop client, backend contracts, and schemas used by Homarr.
UI and composed features
ui: shared Mantine components, theme, and hooks. Search here before creating a primitive.form,forms-collection: Zod-backed form setup and reusable forms.modals,modals-collection: modal primitives and feature modals.boards: board state, edit mode, and cache coordination.settings,spotlight,notifications,onboarding: cross-feature UI flows.widgets: widget definitions, dynamic component loaders, and shared widget UI.translation: next-intl configuration and locale catalogs.cli: Node operations CLI.tools/homarr-devis the separate Go developer CLI.
Dependency direction
Prefer these directions; verify the exact dependency in package manifests before changing a boundary.
- Put infrastructure in
coreand stable domain names indefinitions. - Put reusable, dependency-light helpers in
common; use its public environment-specific entrypoints. - Build persistence in
db, identity inauth, transport inredis, and external clients inintegrations. - Compose server behavior in
api,cron-jobs, and request-handler packages. - Build primitives in
ui,form, andmodals; compose product surfaces in widgets and collection packages. - Keep app entrypoints in
apps/*thin. Avoid moving reusable behavior intoapps/nextjswhen a package already owns it.
Core patterns
tRPC and MCP
packages/api/src/root.ts lazily composes the application router. Server components use @homarr/api/server; client components use @homarr/api/client. MCP extraction requires the eager router in packages/api/src/mcp.ts, so MCP-enabled subrouters must be imported and registered there directly. Use the mcp-integration skill for exposure and security rules.
Databases
Drizzle schemas live in packages/db/schema/. DB_DRIVER selects better-sqlite3 or node-postgres; MySQL and MariaDB are no longer runtime drivers in v2. Existing MySQL installations must use the documented converter before upgrading. Migrations live under packages/db/migrations/sqlite/ and packages/db/migrations/postgresql/.
Widgets
packages/widgets/src/registry.ts owns the explicit widget-module and component-loader registries. packages/widgets/src/manifest.ts caches those loaders and exposes definitions, components, and combined resources. Widget modules use createWidgetDefinition and typed option builders. Data commonly comes from tRPC queries or Redis-backed cron results. Use existing shared widget components before creating local variants.
Integrations
packages/definitions/src/integration.ts owns integrationDefs and IntegrationKind. packages/integrations/src/base/creator.ts owns createIntegrationAsync; concrete integrations implement the shared base contract. Keep credentials and permission checks on server-owned paths.
Cron jobs
Jobs live in packages/cron-jobs/src/jobs/ and use createCronJob. apps/tasks initializes and starts the job group. Job results and status can flow through Redis and tRPC; the retired port-3002 management-API model is no longer part of the architecture.
Routing and localization
User routes live below apps/nextjs/src/app/[locale]/; the locale segment does not add a URL prefix. Route groups organize home and board surfaces. Administrative routes live under manage, Custom Widget configuration has a token route, and Workshop has a management surface.
Custom Widgets and Workshop
packages/custom-widgets owns the Custom JSX v2 contract. packages/workshop is the Homarr-side client/contract package; apps/workshop is the separate Go/PocketBase service. Use the homarr-custom-widget skill for authoring and security constraints.
Commands and conventions
- Read current scripts from the root or package
package.json; avoid caching commands that do not exist. - Use
pnpm devfor Next.js,pnpm dev:docsfor docs, andpnpm dev:cli -- <args>for the Go developer CLI. - Use
pnpm docker:dev:upfor the Redis development dependency. - Follow the Testing section in
AGENTS.mdfor test creation and validation scope. - Use
~/*only inside the Next.js app. Use public@homarr/*entrypoints across package boundaries. - Keep Mantine application styles separate from the Tailwind-based docs app.