# Monorepo Structure Trilium is organized as a TypeScript monorepo using NX, facilitating code sharing, consistent tooling, and efficient build processes. This document provides a comprehensive overview of the project structure, build system, and development workflow. ## Project Organization ``` TriliumNext/Trilium/ ├── apps/ # Runnable applications │ ├── client/ # Frontend web application │ ├── server/ # Node.js backend server │ ├── desktop/ # Electron desktop application │ ├── web-clipper/ # Browser extension │ ├── db-compare/ # Database comparison tool │ ├── dump-db/ # Database dump utility │ └── edit-docs/ # Documentation editor ├── packages/ # Shared libraries │ ├── commons/ # Shared interfaces and utilities │ ├── ckeditor5/ # Rich text editor │ ├── codemirror/ # Code editor │ ├── highlightjs/ # Syntax highlighting │ ├── ckeditor5-admonition/ # CKEditor plugin │ ├── ckeditor5-footnotes/ # CKEditor plugin │ ├── ckeditor5-math/ # CKEditor plugin │ └── ckeditor5-mermaid/ # CKEditor plugin ├── docs/ # Documentation ├── nx.json # NX workspace configuration ├── package.json # Root package configuration ├── pnpm-workspace.yaml # PNPM workspace configuration └── tsconfig.base.json # Base TypeScript configuration ``` ## Applications ### Client (`/apps/client`) The frontend application shared by both server and desktop versions. ``` apps/client/ ├── src/ │ ├── components/ # Core UI components │ ├── entities/ # Frontend entities (FNote, FBranch, etc.) │ ├── services/ # Business logic and API calls │ ├── widgets/ # UI widgets system │ │ ├── type_widgets/ # Note type specific widgets │ │ ├── dialogs/ # Dialog components │ │ └── panels/ # Panel widgets │ ├── public/ │ │ ├── fonts/ # Font assets │ │ ├── images/ # Image assets │ │ └── libraries/ # Third-party libraries │ └── desktop.ts # Desktop entry point ├── package.json ├── project.json # NX project configuration └── vite.config.ts # Vite build configuration ``` #### Key Files - `desktop.ts` - Main application initialization - `services/froca.ts` - Frontend cache implementation - `widgets/basic_widget.ts` - Base widget class - `services/server.ts` - API communication layer ### Server (`/apps/server`) The Node.js backend providing API, database, and business logic. ``` apps/server/ ├── src/ │ ├── becca/ # Backend cache system │ │ ├── entities/ # Core entities (BNote, BBranch, etc.) │ │ └── becca.ts # Cache interface │ ├── routes/ # Express routes │ │ ├── api/ # Internal API endpoints │ │ └── pages/ # HTML page routes │ ├── etapi/ # External API │ ├── services/ # Business services │ ├── share/ # Note sharing functionality │ │ └── shaca/ # Share cache │ ├── migrations/ # Database migrations │ ├── assets/ │ │ ├── db/ # Database schema │ │ └── doc_notes/ # Documentation notes │ └── main.ts # Server entry point ├── package.json ├── project.json └── webpack.config.js # Webpack configuration ``` #### Key Services - `services/sql.ts` - Database access layer - `services/sync.ts` - Synchronization logic - `services/ws.ts` - WebSocket server - `services/protected_session.ts` - Encryption handling ### Desktop (`/apps/desktop`) Electron wrapper for the desktop application. ``` apps/desktop/ ├── src/ │ ├── main.ts # Electron main process │ ├── preload.ts # Preload script │ ├── services/ # Desktop-specific services │ └── utils/ # Desktop utilities ├── resources/ # Desktop resources (icons, etc.) ├── package.json └── electron-builder.yml # Electron Builder configuration ``` ### Web Clipper (`/apps/web-clipper`) Browser extension for saving web content to Trilium. ``` apps/web-clipper/ ├── src/ │ ├── background.js # Background script │ ├── content.js # Content script │ ├── popup/ # Extension popup │ └── options/ # Extension options ├── manifest.json # Extension manifest └── package.json ``` ## Packages ### Commons (`/packages/commons`) Shared TypeScript interfaces and utilities used across applications. ```typescript // packages/commons/src/types.ts export interface NoteRow { noteId: string; title: string; type: string; mime: string; isProtected: boolean; dateCreated: string; dateModified: string; } export interface BranchRow { branchId: string; noteId: string; parentNoteId: string; notePosition: number; prefix: string; isExpanded: boolean; } ``` ### CKEditor5 (`/packages/ckeditor5`) Custom CKEditor5 build with Trilium-specific plugins. ``` packages/ckeditor5/ ├── src/ │ ├── ckeditor.ts # Editor configuration │ ├── plugins.ts # Plugin registration │ └── trilium/ # Custom plugins ├── theme/ # Editor themes └── package.json ``` #### Custom Plugins - **Admonition**: Note boxes with icons - **Footnotes**: Reference footnotes - **Math**: LaTeX equation rendering - **Mermaid**: Diagram integration ### CodeMirror (`/packages/codemirror`) Code editor customizations for the code note type. ```typescript // packages/codemirror/src/index.ts export function createCodeMirror(element: HTMLElement, options: CodeMirrorOptions) { return CodeMirror(element, { ...defaultOptions, ...options, // Trilium-specific customizations }); } ``` ## Build System ### NX Configuration **`nx.json`** ```json { "tasksRunnerOptions": { "default": { "runner": "nx/tasks-runners/default", "options": { "cacheableOperations": ["build", "test", "lint"], "parallel": 3 } } }, "targetDefaults": { "build": { "dependsOn": ["^build"], "cache": true }, "test": { "cache": true } } } ``` ### Project Configuration Each application and package has a `project.json` defining its targets: ```json { "name": "server", "targets": { "build": { "executor": "@nx/webpack:webpack", "options": { "outputPath": "dist/apps/server", "main": "apps/server/src/main.ts", "tsConfig": "apps/server/tsconfig.app.json" } }, "serve": { "executor": "@nx/node:node", "options": { "buildTarget": "server:build" } }, "test": { "executor": "@nx/jest:jest", "options": { "jestConfig": "apps/server/jest.config.ts" } } } } ``` ### Build Commands ```bash # Build specific project pnpm nx build server pnpm nx build client # Build all projects pnpm nx run-many --target=build --all # Build with dependencies pnpm nx build server --with-deps # Production build pnpm nx build server --configuration=production ``` ## Development Workflow ### Initial Setup ```bash # Install dependencies pnpm install # Enable corepack for pnpm corepack enable # Build all packages pnpm nx run-many --target=build --all ``` ### Development Commands ```bash # Start development server pnpm run server:start # or pnpm nx run server:serve # Start desktop app pnpm nx run desktop:serve # Run client dev server pnpm nx run client:serve # Watch mode for packages pnpm nx run commons:build --watch ``` ### Testing ```bash # Run all tests pnpm test:all # Run tests for specific project pnpm nx test server pnpm nx test client # Run tests in watch mode pnpm nx test server --watch # Generate coverage pnpm nx test server --coverage ``` ### Linting and Type Checking ```bash # Lint specific project pnpm nx lint server # Type check pnpm nx run server:typecheck # Lint all projects pnpm nx run-many --target=lint --all # Fix lint issues pnpm nx lint server --fix ``` ## Dependency Management ### Package Dependencies Dependencies are managed at both root and project levels: ```json // Root package.json - shared dev dependencies { "devDependencies": { "@nx/workspace": "^17.0.0", "typescript": "^5.0.0", "eslint": "^8.0.0" } } // Project package.json - project-specific dependencies { "dependencies": { "express": "^4.18.0", "better-sqlite3": "^9.0.0" } } ``` ### Adding Dependencies ```bash # Add to root pnpm add -D typescript # Add to specific project pnpm add express --filter server # Add to multiple projects pnpm add lodash --filter server --filter client ``` ### Workspace References Internal packages are referenced using workspace protocol: ```json { "dependencies": { "@triliumnext/commons": "workspace:*" } } ``` ## TypeScript Configuration ### Base Configuration **`tsconfig.base.json`** ```json { "compilerOptions": { "rootDir": ".", "sourceMap": true, "declaration": false, "moduleResolution": "node", "emitDecoratorMetadata": true, "experimentalDecorators": true, "importHelpers": true, "target": "ES2022", "module": "ESNext", "lib": ["ES2022", "dom"], "skipLibCheck": true, "skipDefaultLibCheck": true, "baseUrl": ".", "paths": { "@triliumnext/commons": ["packages/commons/src/index.ts"] } } } ``` ### Project-Specific Configuration ```json // apps/server/tsconfig.json { "extends": "../../tsconfig.base.json", "compilerOptions": { "module": "commonjs", "types": ["node"] }, "include": ["src/**/*"], "exclude": ["**/*.spec.ts"] } ``` ## Build Optimization ### NX Cloud ```bash # Enable NX Cloud for distributed caching pnpm nx connect-to-nx-cloud ``` ### Affected Commands ```bash # Build only affected projects pnpm nx affected:build --base=main # Test only affected projects pnpm nx affected:test --base=main # Lint only affected projects pnpm nx affected:lint --base=main ``` ### Build Caching NX caches build outputs to speed up subsequent builds: ```bash # Clear cache pnpm nx reset # Run with cache disabled pnpm nx build server --skip-nx-cache # See cache statistics pnpm nx report ``` ## Production Builds ### Building for Production ```bash # Build server for production pnpm nx build server --configuration=production # Build client with optimization pnpm nx build client --configuration=production # Build desktop app pnpm nx build desktop --configuration=production pnpm electron:build # Creates distributables ``` ### Docker Build ```dockerfile # Multi-stage build FROM node:20-alpine AS builder WORKDIR /app COPY package*.json pnpm-lock.yaml ./ RUN corepack enable && pnpm install --frozen-lockfile COPY . . RUN pnpm nx build server --configuration=production FROM node:20-alpine WORKDIR /app COPY --from=builder /app/dist/apps/server ./ COPY --from=builder /app/node_modules ./node_modules CMD ["node", "main.js"] ``` ## Continuous Integration ### GitHub Actions Example ```yaml name: CI on: [push, pull_request] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: pnpm/action-setup@v2 with: version: 8 - uses: actions/setup-node@v3 with: node-version: 20 cache: 'pnpm' - run: pnpm install --frozen-lockfile - run: pnpm nx affected:lint --base=origin/main - run: pnpm nx affected:test --base=origin/main - run: pnpm nx affected:build --base=origin/main ``` ## Troubleshooting ### Common Issues 1. **Build Cache Issues** ```bash # Clear NX cache pnpm nx reset # Clear node_modules and reinstall rm -rf node_modules pnpm install ``` 2. **Dependency Version Conflicts** ```bash # Check for duplicate packages pnpm list --depth=0 # Update all dependencies pnpm update --recursive ``` 3. **TypeScript Path Resolution** ```bash # Verify TypeScript paths pnpm nx run server:typecheck --traceResolution ``` ### Debug Commands ```bash # Show project graph pnpm nx graph # Show project dependencies pnpm nx print-affected --type=app --select=projects # Verbose output pnpm nx build server --verbose # Profile build performance pnpm nx build server --profile ``` ## Best Practices ### Project Structure 1. **Keep packages focused**: Each package should have a single, clear purpose 2. **Minimize circular dependencies**: Use dependency graph to identify issues 3. **Share common code**: Extract shared logic to packages/commons ### Development 1. **Use NX generators**: Generate consistent code structure 2. **Leverage caching**: Don't skip-nx-cache unless debugging 3. **Run affected commands**: Save time by only building/testing changed code ### Testing 1. **Colocate tests**: Keep test files next to source files 2. **Use workspace scripts**: Define common scripts in root package.json 3. **Parallel execution**: Use `--parallel` flag for faster execution ## Related Documentation - [Environment Setup](../Environment%20Setup.md) - Development environment setup - [Project Structure](../Project%20Structure.md) - Detailed project structure - [Build Information](../Development%20and%20architecture/Build%20information.md) - Build details