14 KiB
Vendored
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 initializationservices/froca.ts- Frontend cache implementationwidgets/basic_widget.ts- Base widget classservices/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 layerservices/sync.ts- Synchronization logicservices/ws.ts- WebSocket serverservices/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.
// 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.
// 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
{
"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:
{
"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
# 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
# Install dependencies
pnpm install
# Enable corepack for pnpm
corepack enable
# Build all packages
pnpm nx run-many --target=build --all
Development Commands
# 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
# 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
# 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:
// 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
# 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:
{
"dependencies": {
"@triliumnext/commons": "workspace:*"
}
}
TypeScript Configuration
Base Configuration
tsconfig.base.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
// apps/server/tsconfig.json
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"module": "commonjs",
"types": ["node"]
},
"include": ["src/**/*"],
"exclude": ["**/*.spec.ts"]
}
Build Optimization
NX Cloud
# Enable NX Cloud for distributed caching
pnpm nx connect-to-nx-cloud
Affected Commands
# 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:
# 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
# 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
# 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
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
-
Build Cache Issues
# Clear NX cache pnpm nx reset # Clear node_modules and reinstall rm -rf node_modules pnpm install -
Dependency Version Conflicts
# Check for duplicate packages pnpm list --depth=0 # Update all dependencies pnpm update --recursive -
TypeScript Path Resolution
# Verify TypeScript paths pnpm nx run server:typecheck --traceResolution
Debug Commands
# 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
- Keep packages focused: Each package should have a single, clear purpose
- Minimize circular dependencies: Use dependency graph to identify issues
- Share common code: Extract shared logic to packages/commons
Development
- Use NX generators: Generate consistent code structure
- Leverage caching: Don't skip-nx-cache unless debugging
- Run affected commands: Save time by only building/testing changed code
Testing
- Colocate tests: Keep test files next to source files
- Use workspace scripts: Define common scripts in root package.json
- Parallel execution: Use
--parallelflag for faster execution
Related Documentation
- Environment Setup - Development environment setup
- Project Structure - Detailed project structure
- Build Information - Build details