docs(dev): update recent technical documentation

This commit is contained in:
Elian Doran
2025-11-03 22:16:15 +02:00
parent 4a47ff2ea0
commit d9071f2d8e
85 changed files with 1449 additions and 1790 deletions

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,15 @@
<p>Safe mode is triggered by setting the <code>TRILIUM_SAFE_MODE</code> environment
variable to a truthy value, usually <code>1</code>.</p>
<p>In each artifact there is a <code>trilium-safe-mode.sh</code> (or <code>.bat</code>)
script to enable it.</p>
<p>What it does:</p>
<ul>
<li data-list-item-id="e9c42a70a65d868a17df3413c17b7e6cf">Disables <code>customWidget</code> launcher types in <code>app/widgets/containers/launcher.js</code>.</li>
<li
data-list-item-id="ecd3fb5a4737b444e0c850eaea3877261">Disables the running of <code>mobileStartup</code> or <code>frontendStartup</code> scripts.</li>
<li
data-list-item-id="ea137da7a8e7ea33537b6ccf972a24728">Displays the root note instead of the previously saved session.</li>
<li
data-list-item-id="eae25286d35c9c22f543fddb8475d09aa">Disables the running of <code>backendStartup</code>, <code>hourly</code>, <code>daily</code> scripts
and checks for the hidden subtree.</li>
</ul>

View File

@@ -0,0 +1,64 @@
<p>Since TriliumNext 0.94.1, the desktop and server applications can be built
using <a href="https://nixos.org/">Nix</a>.</p>
<h2>System requirements</h2>
<p>Installation of Nix on Mac or Linux (<a href="https://nixos.org/download/">download page</a>).
About 3-4 gigabytes of additional storage space, for build artifacts.</p>
<h2>Run directly</h2>
<p>Using <a href="https://nix.dev/manual/nix/stable/command-ref/new-cli/nix3-run.html">nix run</a>,
the desktop app can be started as: <code>nix run github:TriliumNext/Trilium/v0.95.0</code>
</p>
<p>Running the server requires explicitly specifying the desired package: <code>nix run github:TriliumNext/Trilium/v0.95.0#server</code>
</p>
<p>Instead of a version (<code>v0.95.0</code> above), you can also specify
a commit hash (or a branch name). This makes it easy to test development
builds.</p>
<h2>Install on NixOS</h2>
<p>Add to your <code>flake.nix</code>:</p><pre><code class="language-text-x-trilium-auto">{
inputs = {
nixpkgs.url = # ...;
trilium-notes = {
url = "github:TriliumNext/Trilium/v0.95.0";
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs =
{
self,
# ...
trilium-notes,
...
}:
{
nixosConfigurations = {
"nixos" = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
./configuration.nix
];
specialArgs = {
inherit
trilium-notes
;
};
};
};
};
}
</code></pre>
<p>Add to your <code>configuration.nix</code>:</p><pre><code class="language-text-x-trilium-auto">{
# ...
trilium-notes,
...
}:
{
# ...
services.trilium-server.package = trilium-notes.packages.x86_64-linux.server;
environment.systemPackages = [
trilium-notes.packages.x86_64-linux.desktop
];
}</code></pre>
<p>The flake aims to be compatible with the latest NixOS stable and unstable.</p>

View File

@@ -0,0 +1 @@
<p>This is a clone of a note. Go to its <a href="../Desktop%20Installation/Nix%20flake.html">primary location</a>.</p>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,2 @@
# attributes
<table><thead><tr><th>Column Name</th><th>Data Type</th><th>Nullity</th><th>Default value</th><th>Description</th></tr></thead><tbody><tr><th><code>attributeId</code></th><td>Text</td><td>Non-null</td><td>&nbsp;</td><td>Unique Id of the attribute (e.g. <code>qhC1vzU4nwSE</code>), can also have a special unique ID for&nbsp;<a class="reference-link" href="#root/r11Bh3uxFGRj">Special notes</a>&nbsp;(e.g. <code>_lbToday_liconClass</code>).</td></tr><tr><th><code>noteId</code></th><td>Text</td><td>Non-null</td><td>&nbsp;</td><td>The ID of the <a href="notes.md">note</a> this atttribute belongs to</td></tr><tr><th><code>type</code></th><td>Text</td><td>Non-null</td><td>&nbsp;</td><td>The type of attribute (<code>label</code> or <code>relation</code>).</td></tr><tr><th><code>name</code></th><td>Text</td><td>Non-null</td><td>&nbsp;</td><td>The name/key of the attribute.</td></tr><tr><th><code>value</code></th><td>Text</td><td>Non-null</td><td><code>""</code></td><td><ul><li>For <code>label</code> attributes, a free-form value of the attribute.</li><li>For <code>relation</code> attributes, the ID of the <a href="notes.md">note</a> the relation is pointing to.</li></ul></td></tr><tr><th><code>position</code></th><td>Integer</td><td>Non-null</td><td>0</td><td>The position of the attribute compared to the other attributes. Some predefined attributes such as <code>originalFileName</code> have a value of 1000.</td></tr><tr><th><code>utcDateModified</code></th><td>Text</td><td>Non-null</td><td>&nbsp;</td><td>Modification date in UTC format (e.g. <code>2023-11-08 16:43:44.204Z</code>)</td></tr><tr><th><code>isDeleted</code></th><td>Integer</td><td>Non-null</td><td>&nbsp;</td><td><code>1</code> if the entity is <a href="../Deleted%20notes.md">deleted</a>, <code>0</code> otherwise.</td></tr><tr><th><code>deleteId</code></th><td>Text</td><td>Nullable</td><td><code>null</code></td><td>&nbsp;</td></tr><tr><th><code>isInheritable</code></th><td>Integer</td><td>Nullable</td><td>0</td><td>&nbsp;</td></tr></tbody></table>

View File

@@ -0,0 +1,2 @@
# blobs
<table><thead><tr><th>Column Name</th><th>Data Type</th><th>Nullity</th><th>Default value</th><th>Description</th></tr></thead><tbody><tr><th><code>blobId</code></th><td>Text</td><td>Non-null</td><td>&nbsp;</td><td><p>The unique ID of the blob (e.g. <code>XXbfAJXqWrYnSXcelLFA</code>).</p><aside class="admonition important"><p>The ID is actually a hash of the content, see <code>AbstractBeccaEntity#saveBlob</code>! It is a logic error to modify an existing blob.</p></aside></td></tr><tr><th><code>content</code></th><td>Text</td><td>Nullable</td><td><code>null</code></td><td><p>The content of the blob, can be either:</p><ul><li data-list-item-id="e1f1b8623c64f95f19751bbe494063d0f">text (for plain text notes or HTML notes).</li><li data-list-item-id="e5bbdee6fe5e5b12361fc74e339c9f1db">binary (for images and other types of attachments)</li></ul></td></tr><tr><th><code>dateModified</code></th><td>Text</td><td>Non-null</td><td>&nbsp;</td><td>Creation date with timezone offset (e.g. <code>2023-11-08 18:43:44.204+0200</code>)</td></tr><tr><th><code>utcDateModified</code></th><td>Text</td><td>Non-null</td><td>&nbsp;</td><td><p>Creation date in UTC format (e.g. <code>2023-11-08 16:43:44.204Z</code>).</p><p>Blobs cannot be modified, so this timestamp specifies when the blob was created.</p></td></tr></tbody></table>

View File

@@ -0,0 +1,22 @@
# Demo document
The demo document is an exported .zip that resides in `apps/server/src/assets/db/demo.zip`.
During on-boarding, if the user selects that they are a new user then the `demo.zip` is imported into the root note.
## Modifying the document
1. In the Git root, run `pnpm edit-docs:edit-demo`.
2. Wait for the desktop application to show up with the docs.
3. Simply make the needed modifications.
4. Wait for a few seconds for the change to be processed in the background.
5. Commit the change in Git.
## Testing the changes
1. Run:
```
rm -r data
pnpm server:start
```
2. And then do the on-boarding again.

View File

@@ -41,7 +41,7 @@ Go to `src/becca/entities/rows.ts` and add the new note type to `ALLOWED_NOTE_TY
## Final steps ## Final steps
* Update the <a class="reference-link" href="../Demo%20document.md">Demo document</a> to showcase the new note type. * Update the <a class="reference-link" href="../../Demo%20document.md">Demo document</a> to showcase the new note type.
## Troubleshooting ## Troubleshooting

View File

@@ -0,0 +1,43 @@
# Options
## Read an option
Add the import to the service (make sure the relative path is correct):
```javascript
import options from "../../services/options.js";
```
Them simply read the option:
```javascript
this.firstDayOfWeek = options.getInt("firstDayOfWeek");
```
## Adding new options
### Checkbox option
Refer to this example in `backup.tsx`:
```javascript
export function AutomaticBackup() {
const [ dailyBackupEnabled, setDailyBackupEnabled ] = useTriliumOptionBool("dailyBackupEnabled");
return (
<OptionsSection title={t("backup.automatic_backup")}>
<FormMultiGroup label={t("backup.automatic_backup_description")}>
<FormCheckbox
name="daily-backup-enabled"
label={t("backup.enable_daily_backup")}
currentValue={dailyBackupEnabled} onChange={setDailyBackupEnabled}
/>
</FormMultiGroup>
<FormText>{t("backup.backup_recommendation")}</FormText>
</OptionsSection>
)
}
```
> [!TIP]
> To trigger a UI refresh (e.g. `utils#reloadFrontendApp`), simply pass a `true` as the second argument to `useTriliumOption` methods.

View File

@@ -0,0 +1,18 @@
# Printing and exporting to PDF
Note printing is handled by `note_detail.js`, in the `printActiveNoteEvent` method. Exporting to PDF works similarly.
## How it works
Both printing and exporting as PDF use the same mechanism: a note is rendered individually in a separate webpage that is then sent to the browser or the Electron application either for printing or exporting as PDF.
The webpage that renders a single note can actually be accessed in a web browser. For example `http://localhost:8080/#root/WWRGzqHUfRln/RRZsE9Al8AIZ?ntxId=0o4fzk` becomes `http://localhost:8080/?print#root/WWRGzqHUfRln/RRZsE9Al8AIZ`.
Accessing the print note in a web browser allows for easy debugging to understand why a particular note doesn't render well. The mechanism for rendering is similar to the one used in <a class="reference-link" href="#root/0ESUbbAxVnoK">Note List</a>.
## Syntax highlighting
Syntax highlighting for code blocks is supported as well:
* It works by injecting a Highlight.js stylesheet into the print.
* The theme used is hard-coded (the _Visual Studio Light theme_, at the time of writing) in order not to have a dark background in print.
* <a class="reference-link" href="Syntax%20highlighting.md">Syntax highlighting</a> is handled by the content renderer.

View File

@@ -0,0 +1,6 @@
# Protected entities
The following entities can be made protected, via their `isProtected` flag:
* <a class="reference-link" href="Database%20structure/attachments.md">attachments</a>
* <a class="reference-link" href="Database%20structure/notes.md">notes</a>
* <a class="reference-link" href="Database%20structure/revisions.md">revisions</a>

View File

@@ -0,0 +1,4 @@
# Build information
* Provides context about when the build was made and the corresponding Git revision.
* The information is displayed to the client when going in the about dialog.
* The build information is hard-coded in `apps/server/src/services/build.ts`. This file is generated automatically via `chore:update-build-info` which itself is run automatically whenever making a build in the CI.

View File

@@ -0,0 +1,8 @@
# Docker
To build the server for Docker:
* Go to `apps/server` and run:
* `pnpm docker-build-debian` or
* `pnpm docker-build-alpine`.
* Similarly, to build the rootless versions: `pnpm docker-build-rootless-debian` or `pnpm docker-build-rootless-alpine`.
* To not only build but also run the Docker container, simply replace `docker-build` with `docker-start` (e.g. `pnpm docker-start-debian`).

View File

@@ -0,0 +1,10 @@
# Live reload (HMR)
Trilium uses Vite's HMR (hot module reloading) mechanism.
## Server live reload
If running the server using `pnpm server:start`, the server will watch for changes. For React components, they will be hot-reloaded without requiring a refresh. For other services, it will reload the page.
## Desktop live reload
`pnpm desktop:start` acts the same as `pnpm server:start` with hot-reloading for client-side changes. Changes on the desktop side require a complete re-run of the `pnpm desktop:start` command.

View File

@@ -1,4 +0,0 @@
# Build information
* Provides context about when the build was made and the corresponding Git revision.
* The information is displayed to the client when going in the about dialog.
* The build information is hard-coded in `src/services/build.ts`. This file is generated automatically via `npm run update-build-info` which itself is run automatically whenever making a build in the CI, or a [local delivery](../Old%20documentation/Build%20deliveries%20locally.md).

View File

@@ -1,2 +0,0 @@
# attributes
<table><thead><tr><th>Column Name</th><th>Data Type</th><th>Nullity</th><th>Default value</th><th>Description</th></tr></thead><tbody><tr><th><code>attributeId</code></th><td>Text</td><td>Non-null</td><td>&nbsp;</td><td>Unique Id of the attribute (e.g. <code>qhC1vzU4nwSE</code>), can also have a special unique ID for&nbsp;<a class="reference-link" href="../Special%20notes.md">Special notes</a>&nbsp;(e.g. <code>_lbToday_liconClass</code>).</td></tr><tr><th><code>noteId</code></th><td>Text</td><td>Non-null</td><td>&nbsp;</td><td>The ID of the <a href="notes.md">note</a> this atttribute belongs to</td></tr><tr><th><code>type</code></th><td>Text</td><td>Non-null</td><td>&nbsp;</td><td>The type of attribute (<code>label</code> or <code>relation</code>).</td></tr><tr><th><code>name</code></th><td>Text</td><td>Non-null</td><td>&nbsp;</td><td>The name/key of the attribute.</td></tr><tr><th><code>value</code></th><td>Text</td><td>Non-null</td><td><code>""</code></td><td><ul><li>For <code>label</code> attributes, a free-form value of the attribute.</li><li>For <code>relation</code> attributes, the ID of the <a href="notes.md">note</a> the relation is pointing to.</li></ul></td></tr><tr><th><code>position</code></th><td>Integer</td><td>Non-null</td><td>0</td><td>The position of the attribute compared to the other attributes. Some predefined attributes such as <code>originalFileName</code> have a value of 1000.</td></tr><tr><th><code>utcDateModified</code></th><td>Text</td><td>Non-null</td><td>&nbsp;</td><td>Modification date in UTC format (e.g. <code>2023-11-08 16:43:44.204Z</code>)</td></tr><tr><th><code>isDeleted</code></th><td>Integer</td><td>Non-null</td><td>&nbsp;</td><td><code>1</code> if the entity is <a href="../Deleted%20notes.md">deleted</a>, <code>0</code> otherwise.</td></tr><tr><th><code>deleteId</code></th><td>Text</td><td>Nullable</td><td><code>null</code></td><td>&nbsp;</td></tr><tr><th><code>isInheritable</code></th><td>Integer</td><td>Nullable</td><td>0</td><td>&nbsp;</td></tr></tbody></table>

View File

@@ -1,2 +0,0 @@
# blobs
<table><thead><tr><th>Column Name</th><th>Data Type</th><th>Nullity</th><th>Default value</th><th>Description</th></tr></thead><tbody><tr><th><code>blobId</code></th><td>Text</td><td>Non-null</td><td>&nbsp;</td><td>The unique ID of the blob (e.g. <code>XXbfAJXqWrYnSXcelLFA</code>).<p>Important: this ID is actually a hash of the content, see <code>AbstractBeccaEntity#saveBlob</code>! It is a logic error to modify an existing blob.</p></td></tr><tr><th><code>content</code></th><td>Text</td><td>Nullable</td><td><code>null</code></td><td><p>The content of the blob, can be either:</p><ul><li>text (for plain text notes or HTML notes).</li><li>binary (for images and other types of attachments)</li></ul></td></tr><tr><th><code>dateModified</code></th><td>Text</td><td>Non-null</td><td>&nbsp;</td><td>Creation date with timezone offset (e.g. <code>2023-11-08 18:43:44.204+0200</code>)</td></tr><tr><th><code>utcDateModified</code></th><td>Text</td><td>Non-null</td><td>&nbsp;</td><td>Creation date in UTC format (e.g. <code>2023-11-08 16:43:44.204Z</code>).<p>Blobs cannot be modified, so this timestamp specifies when the blob was created.</p></td></tr></tbody></table>

View File

@@ -1,19 +0,0 @@
# Demo document
The demo document is an exported .zip that resides in `db/demo.zip`.
During on-boarding, if the user selects that they are a new user then the `demo.zip` is imported into the root note.
## Modifying the document
On a dev server, remove all your existing notes in order to ensure a clean setup. Right click → Import to note and select the .zip file in `db/demo.zip`. Make sure to disable “Safe import”.
After making the necessary modifications, simply export the “Trilium Demo” note as “HTML in ZIP archive” and replace `db/demo.zip` with the newly exported one.
## Testing the changes
```
rm -r data
npm run start-server
```
And then do the on-boarding again.

View File

@@ -1,18 +0,0 @@
# Docker
To run a Docker build:
```
./bin/builder-docker.sh
```
To run the built Docker image:
```
sudo docker run -p 8081:8080 triliumnext/trilium:v0.90.6-beta
```
To enter a shell in the Docker container:
```
sudo docker run -it --entrypoint=/bin/sh zadam/trilium:0.63-latest
```

Binary file not shown.

Before

Width:  |  Height:  |  Size: 233 KiB

View File

@@ -1,8 +0,0 @@
# Icons on Mac
Looks great in Finder:
<figure class="image"><img src="Icons on Mac_image.png"></figure>
Looks great in Dock:
<figure class="image"><img src="1_Icons on Mac_image.png"></figure>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 233 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 250 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 251 KiB

View File

@@ -1,15 +0,0 @@
# Adaptive icon
| | |
| --- | --- |
| Before | <figure class="image"><img src="1_Adaptive icon_image.png"></figure> |
| After | <figure class="image"><img src="6_Adaptive icon_image.png"></figure> |
| With new scale | <figure class="image"><img src="4_Adaptive icon_image.png"></figure> |
## Scale
| | |
| --- | --- |
| 0.9 | <figure class="image"><img src="2_Adaptive icon_image.png"></figure> |
| 0.85 | <figure class="image"><img src="5_Adaptive icon_image.png"></figure> |
| 0.8 | <figure class="image"><img src="Adaptive icon_image.png"></figure> |
| 0.75 | <figure class="image"><img src="3_Adaptive icon_image.png"></figure> |

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.8 KiB

View File

@@ -1,50 +0,0 @@
# Slightly blurry icon on Mac
Slightly blurry in extended preview on Mac
<figure class="image"><img src="1_Slightly blurry icon on Ma.png"></figure>
In the screenshot, the icon is around 650px whereas the closest image we have is 512px, so that might explain the blur. Adding an `ic10` (`1024x1024`, aka `512x512@2x` to see what happens).
Before:
```
File: ../images/app-icons/mac/icon.icns
ic09: 62069 bytes, png: 512x512
```
After:
```
File: ../images/app-icons/mac/icon.icns
icp4: 1140 bytes, png: 16x16
icp5: 1868 bytes, png: 32x32
ic07: 9520 bytes, png: 128x128
ic09: 62069 bytes, png: 512x512
ic10: 180442 bytes, png: 512x512@2x
```
Even with a 1024x1024 icon, the image is still blurry.
Comparing the `.icns` file from the Electron build reveals that the `.icns` file has been tampered with:
<table><thead><tr><th>The <code>electron.icns</code> from the resulting build</th><th>The icon source</th></tr></thead><tbody><tr><td><pre><code class="language-text-plain">File: images/app-icons/mac/electron.icns
icp4: 1140 bytes, png: 16x16
icp5: 1868 bytes, png: 32x32
ic07: 9520 bytes, png: 128x128
ic09: 62069 bytes, png: 512x512
ic10: 180442 bytes, png: 512x512@2x</code></pre></td><td><pre><code class="language-text-plain">File: images/app-icons/mac/icon.icns
icp4: 1648 bytes, png: 16x16
icp5: 4364 bytes, png: 32x32
ic07: 26273 bytes, png: 128x128
ic09: 206192 bytes, png: 512x512
ic10: 716034 bytes, png: 512x512@2x</code></pre></td></tr></tbody></table>
The bluriness might come from the image itself: [https://stackoverflow.com/questions/54030521/convert-svg-to-png-with-sharp-edges](https://stackoverflow.com/questions/54030521/convert-svg-to-png-with-sharp-edges) 
Rendering with Inkscape (left) vs ImageMagick (right):
<figure class="image"><img src="2_Slightly blurry icon on Ma.png"></figure>
Now in macOS it's also rendering quite nicely:
<figure class="image"><img src="Slightly blurry icon on Ma.png"></figure>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 336 KiB

View File

@@ -1,27 +0,0 @@
# Removed icons
The following icons were removed:
## Main images
These are stored in `images`:
| Name | Resolution | Description |
| --- | --- | --- |
| `icon-black.png` | 36x36 | Does not appear to be used. |
| `icon-color.png` | 36x36 | Used only by some tests in `test-etapi`. |
| `icon-grey.png` | 36x36 | Does not appear to be used. |
| `icon.svg` | 210x297 | Does not appear to be used. |
## App icons
| Name | Resolution | Description |
| --- | --- | --- |
| `png/16x16-bw.png` | 16x16 | Do not appear to be used. |
| `png/16x16.png` | | |
| `png/24x24.png` | 24x24 | |
| `png/32x32.png` | 32x32 | |
| `png/48x48.png` | 48x48 | |
| `png/64x64.png` | 64x64 | |
| `png/96x96.png` | 96x96 | |
| `png/512x512.png` | 512x512 | Does not appear to be used. |
| `win/setup-banner.xcf` | | GIMP source for `win/setup-banner.gif`. Provided only for future editing. |

View File

@@ -1,20 +0,0 @@
# Live reload
## Server live reload
If running the server using `npm run start-server`, the server will watch for changes in `src/public` and trigger a frontend reload if that occurs.
## Electron live reload
Similarly, `npm run start-electron` supports live refresh  as well.
However, a core difference is that Electron watches `dist/src/public` instead of `src/public` since Electron runs on its own copy of the files.
To ameliorate that, a separate watch script has been implemented which automatically copies files from `src/public` to `dist/src/public` whenever a change is detected. To run it:
```
npm run
```
## Technical details
* This mechanism is managed at server level by watching for changes in`services/ws.ts`.

View File

@@ -1,30 +0,0 @@
# Note types
The note type is defined by the `type` column in <a class="reference-link" href="Database/notes.md">notes</a>.
Possible types:
<table class="ck-table-resized"><colgroup><col> <col> <col> <col> <col></colgroup><thead><tr><th>Note Type</th><th><code>type</code> value</th><th>Corresponding MIME type</th><th>Content of the note's blob</th><th>Relevant attributes</th></tr></thead><tbody><tr><th>Text</th><td><code>text</code></td><td>&nbsp;</td><td>The HTML of the note.</td><td>&nbsp;</td></tr><tr><th><a href="https://github.com/zadam/trilium/wiki/Relation-map">Relation Map&nbsp;</a></th><td><code>relationMap</code></td><td><code>application/json</code></td><td><p>A JSON describing the note:</p><pre><code class="language-text-plain">{
"notes": [
{
"noteId": "gFQDL11KEm9G",
"x": 142,
"y": 405
},
{
"noteId": "8GcjEKyrrCgl",
"x": 100.10406374385552,
"y": 757.0364424520196
}
],
"transform": {
"scale": 0.3,
"x": 480.29766098682165,
"y": 116.83892021963081
}
}</code></pre></td><td>None</td></tr><tr><th><a href="https://github.com/zadam/trilium/wiki/Scripts">Render Note</a></th><td><code>render</code></td><td><code>text/html</code> or blank.</td><td>An empty blob.</td><td><code>~renderNote</code> pointing to the HTML note to render.</td></tr><tr><th>Canvas</th><td><code>canvas</code></td><td><code>application/json</code></td><td><pre><code class="language-text-plain">{
"appState": {},
"elemenets": {},
"files": {},
"type": "excalidraw",
"version": 2
}</code></pre></td><td>None</td></tr><tr><th>Mermaid Diagram</th><td><code>mermaid</code></td><td><code>text/mermaid</code> or <code>text/plain</code></td><td>The plain text content of the Mermaid diagram.</td><td>None</td></tr><tr><th>Book</th><td><code>book</code></td><td><code>text/html</code> or blank.</td><td>An empty blob.</td><td><ul><li><code>#viewType</code> which can be either <code>grid</code> or <code>list</code>.</li><li><code>#expanded</code></li></ul><p>both options are shown to the user via the “Book Properties” ribbon widget.</p></td></tr><tr><th>Web View</th><td><code>webView</code></td><td>blank</td><td>An empty blob.</td><td><code>#webViewSrc</code> pointing to an URL to render.</td></tr><tr><th>Code</th><td><code>code</code></td><td>Depends on the language (e.g. <code>text/plain</code>, <code>text/x-markdown</code>, <code>text/x-c++src</code>).</td><td>The plain text content.</td><td>&nbsp;</td></tr></tbody></table>

View File

@@ -1,14 +0,0 @@
# Options
## Read an option
Add the import to the service (make sure the relative path is correct):
```javascript
import options from "../../services/options.js";
```
Them simply read the option:
```javascript
this.firstDayOfWeek = options.getInt("firstDayOfWeek");
```

View File

@@ -1,37 +0,0 @@
# Check box option
In the TPL:
```
<div class="options-section">
<h4>Background effects</h4>
<p>On the desktop application, it's possible to use a semi-transparent background tinted in the colors of the user's wallpaper to add a touch of color.</p>
<div class="col-6 side-checkbox">
<label class="form-check">
<input type="checkbox" class="background-effects form-check-input" />
Enable background effects (Windows 11 only)
</label>
</div>
</div>
```
In `doRender()`:
```
doRender() {
this.$backgroundEffects = this.$widget.find("input.background-effects");
this.$backgroundEffects.on("change", () => this.updateCheckboxOption("backgroundEffects", this.$backgroundEffects));
}
```
In `optionsLoaded(options)`:
```
async optionsLoaded(options) {
this.setCheckboxState(this.$backgroundEffects, options.backgroundEffects);
}
```

View File

@@ -1,36 +0,0 @@
# Displaying the option in settings
Go to `src/public/app/widgets/type_widgets/options` and select a corresponding category, such as `appearance` and edit one of the JS files.
For example, to create a select:
First, modify the template (`TPL`), to add the new widget:
```
<div class="col-6">
<label>First day of the week</label>
<select class="first-day-of-week-select form-control">
<option value="0">Sunday</option>
<option value="1">Monday</option>
</select>
</div>
```
Secondly, create a reference to the new element in `doRender()`:
```
this.$firstDayOfWeek = this.$widget.find(".first-day-of-week-select");
```
Then in `optionsLoaded` adjust the value to the one set in the database:
```
this.$firstDayOfWeek.val(options.firstDayOfWeek);
```
To actually update the option, add a listener in `doRender`:
```
this.$firstDayOfWeek.on("change", () => {
this.updateOption("firstDayOfWeek", this.$firstDayOfWeek.val());
});
```

View File

@@ -1,10 +0,0 @@
# Refresh widget with option change
To make a widget react to a change of a given option, simply add the following to the widget:
```javascript
async entitiesReloadedEvent({loadResults}) {
if (loadResults.getOptionNames().includes("firstDayOfWeek")) {
// Do something.
}
}
```

View File

@@ -1,12 +0,0 @@
# Trigger UI refresh
Call `utils.reloadFrontendApp`, but make sure to wait for the option to be saved first.
```
this.$backgroundEffects.on("change", async () => {
await this.updateCheckboxOption("backgroundEffects", this.$backgroundEffects);
utils.reloadFrontendApp("background effect change");
});
```

View File

@@ -1,15 +0,0 @@
# Printing
Note printing is handled by `note_detail.js`, in the `printActiveNoteEvent` method.
The application uses the [`print-this`](https://www.npmjs.com/package/print-this) library to isolate `.note-detail-printable:visible` and prepare it for printing.
Some scripts like KaTeX are manually injected in the footer, and the CSS to be used is manually defined. The most important one is `print.css`.
## Syntax highlighting
Syntax highlighting for code blocks is supported as well:
* It works by injecting a Highlight.js stylesheet into the print.
* The theme used is hard-coded (the _Visual Studio Light theme_, at the time of writing) in order not to have a dark background in print.
* The Highlight.js library is not needed since the `.note-detail-printable` which is rendered already has the `.hljs` classes added to it in order to achieve the syntax highlighting.
* The user's choice of whether to enable syntax highlighting is also respected.

View File

@@ -1,6 +0,0 @@
# Protected entities
The following entities can be made protected, via their `isProtected` flag:
* <a class="reference-link" href="Database/attachments.md">attachments</a>
* <a class="reference-link" href="Database/notes.md">notes</a>
* <a class="reference-link" href="Database/revisions.md">revisions</a>

View File

@@ -26,8 +26,11 @@ As a quick heads-up of some differences when compared to `npm`:
Run `pnpm i` at the top of the `Notes` repository to install the dependencies. Run `pnpm i` at the top of the `Notes` repository to install the dependencies.
> [!NOTE]
> Dependencies are kept up to date periodically in the project. Generally it's a good rule to do `pnpm i` after each `git pull` on the main branch.
## IDE ## IDE
Our recommended IDE for working on TriliumNext is Visual Studio Code (or VSCodium if you are looking for a fully open-source alternative). Our recommended IDE for working on Trilium is Visual Studio Code (or VSCodium if you are looking for a fully open-source alternative).
By default we include a number of suggested extensions which should appear when opening the repository in VS Code. Most of the extensions are for integrating various technologies we are using such as Playwright and Vitest for testing and NX for mono-repo management. By default we include a number of suggested extensions which should appear when opening the repository in VS Code. Most of the extensions are for integrating various technologies we are using such as Playwright and Vitest for testing or for <a class="reference-link" href="Architecture/Internationalisation%20%20Translat.md">Internationalisation / Translations</a>.

View File

@@ -1,5 +1,5 @@
# Project Structure # Project Structure
As the application grew in complexity, our build system was growing even more difficult to maintain and was spread across multiple repositories. As such we have decided to use a mono-repo approach, and to do so we chose to have NX manage our mono-repo. As the application grew in complexity, we decided to switch to a monorepo based on `pnpm`. Our initial monorepo implementation used NX, but we've switched to pure `pnpm` workspaces and our own build scripts.
## Project structure ## Project structure
@@ -12,45 +12,34 @@ The mono-repo is mainly structured in:
* `packages`, containing dependencies used by one or more `apps`. * `packages`, containing dependencies used by one or more `apps`.
* `commons`, containing shared code for all the apps. * `commons`, containing shared code for all the apps.
## Working with NX ## Working with the project
### Running tasks via the CLI
For example to run the server instance: For example to run the server instance:
``` ```
pnpm exec nx run server:serve pnpm server:start
``` ```
NX has built-in cache support which should make development much faster. Sometimes, it can get in the way; to skip the cache simply append `--skip-nx-cache` to the command you are running.
### Running tasks using Visual Studio Code
If you are using Visual Studio Code as your development tool for Trilium, consider using the NX Console. It allows running tasks/targets much easier via the dedicated tab. Right-click a target in the list for more options, such as bypassing the cache.
## Important tasks ## Important tasks
Each application has a number of tasks (called _targets_ by NX). Here's a non-exhaustive list of the tasks that are useful during development. Each application has a number of tasks. Here's a non-exhaustive list of the tasks that are useful during development.
To run any of the task use `pnpm exec nx run project:task`, or use the Visual Studio Code integration as described above. To run any of the tasks, use `pnpm project:task`:
* `client`: * `client`:
* The client is not meant to be run by itself, despite being described as an app. See the documentation on the server instead. * The client is not meant to be run by itself, despite being described as an app. See the documentation on the server instead.
* `server`: * `server`:
* To run the server in development mode, run `client:serve` (which will only serve the public assets), followed by `server:serve` (which will proxy the assets of the client as well). The dev port remains the same as always, `8080`. * To run the server in development mode, run `server:start`. The dev port is `8080`.
* To run the server in production mode (with its own copy of the assets), run `server:start-prod`. * To run the server in production mode (with its own copy of the assets), run `server:start-prod`.
* To build the server for Docker, run `docker-build` which will automatically build and tag the image if Docker is installed locally. * To build for Docker, see <a class="reference-link" href="Building/Docker.md">Docker</a>.
* Similarly, run `docker-start` to build and run the Docker image.
* `desktop`: * `desktop`:
* To run the desktop, run `desktop:serve`. * To run the desktop in development mode with watch, run `desktop:start`.
* Unlike the server, this one does not require the client since it will automatically get a production copy of it. The only downside is that modifications to the code will only take effect after restarting the task. * To run the desktop in production mode, run `desktop:start-prod`.
## Building packages ## Building packages
Generally, the building process of a project generates a `dist` folder containing everything needed for production. To trigger a build run `pnpm nx build project` where `project` is the name of a project from either `apps` or `packages`. Generally, the building process of a project generates a `dist` folder containing everything needed for production.
## Managing dependencies across the mono-repo ## Managing dependencies across the mono-repo
We are using [pnpm workspaces](https://pnpm.io/workspaces) to manage the project structure, further augmented by NX which is described in a different section. We are using [pnpm workspaces](https://pnpm.io/workspaces) to manage the project structure. The workspace configuration is in `pnpm-workspace.yaml` at project level but it generally should not be modified.
The workspace configuration is in `pnpm-workspace.yaml` at project level but it generally should not be modified.

View File

@@ -34,7 +34,7 @@ In the newly copied package, go to `package.json` and edit:
2. In `peerDependencies`, change `ckeditor5` to the same version as from the previous step. 2. In `peerDependencies`, change `ckeditor5` to the same version as from the previous step.
3. Similarly, update `vitest` dependencies to match the monorepo one. 3. Similarly, update `vitest` dependencies to match the monorepo one.
4. Remove the `prepare` entry from the `scripts` section. 4. Remove the `prepare` entry from the `scripts` section.
5. Change `build:dist` to simply `build` in order to integrate it with NX. 5. Change `build:dist` to simply `build`.
6. In `tsconfig.dist.json`, change `typings/types` to `../typings/types.d.ts` to be compatible with the latest TypeScript version. 6. In `tsconfig.dist.json`, change `typings/types` to `../typings/types.d.ts` to be compatible with the latest TypeScript version.
## Step 4. Install missing dependencies and build errors ## Step 4. Install missing dependencies and build errors

View File

@@ -1,6 +1,6 @@
# better-sqlite3 was compiled against a different Node.js version # better-sqlite3 was compiled against a different Node.js version
This generally can happen when running the development version of either the `desktop` or `server`, but it should not happen as often as it used to. The reason is that `better-sqlite3` is a native dependency and has different builds for either the system's Node.js (as used by the `server`), or Electron's one (as used by the `desktop`). This generally can happen when running the development version of either the `desktop` or `server`, but it should not happen as often as it used to. The reason is that `better-sqlite3` is a native dependency and has different builds for either the system's Node.js (as used by the `server`), or Electron's one (as used by the `desktop`).
To solve this, go to `apps/server` and run `pnpm rebuild`. For Electron this step is not necessary as it's already handled by the `rebuild-deps` NX target. To solve this, go to `apps/server` and run `pnpm rebuild`. For Electron (`desktop`) this step generally not necessary, however `pnpm postinstall` should solve it.
If you can reproduce this issue consistently, please open a bug report. If you can reproduce this issue consistently, please open a bug report.

View File

@@ -366,6 +366,41 @@
"format": "markdown", "format": "markdown",
"dataFileName": "System Requirements.md", "dataFileName": "System Requirements.md",
"attachments": [] "attachments": []
},
{
"isClone": false,
"noteId": "Un4wj2Mak2Ky",
"notePath": [
"pOsGYCXsbNQG",
"Otzi9La2YAUX",
"poXkQfguuA0U",
"Un4wj2Mak2Ky"
],
"title": "Nix flake",
"notePosition": 30,
"prefix": null,
"isExpanded": false,
"type": "text",
"mime": "text/html",
"attributes": [
{
"type": "label",
"name": "shareAlias",
"value": "nix-flake",
"isInheritable": false,
"position": 20
},
{
"type": "label",
"name": "iconClass",
"value": "bx bxl-tux",
"isInheritable": false,
"position": 30
}
],
"format": "markdown",
"dataFileName": "Nix flake.md",
"attachments": []
} }
] ]
}, },
@@ -1221,6 +1256,22 @@
"format": "markdown", "format": "markdown",
"dataFileName": "System Requirements.md", "dataFileName": "System Requirements.md",
"attachments": [] "attachments": []
},
{
"isClone": true,
"noteId": "Un4wj2Mak2Ky",
"notePath": [
"pOsGYCXsbNQG",
"Otzi9La2YAUX",
"WOcw2SLH6tbX",
"Un4wj2Mak2Ky"
],
"title": "Nix flake",
"prefix": null,
"dataFileName": "Nix flake.clone.md",
"type": "text",
"format": "markdown",
"isExpanded": false
} }
] ]
}, },
@@ -13996,6 +14047,40 @@
"attachments": [] "attachments": []
} }
] ]
},
{
"isClone": false,
"noteId": "64ZTlUPgEPtW",
"notePath": [
"pOsGYCXsbNQG",
"tC7s2alapj8V",
"64ZTlUPgEPtW"
],
"title": "Safe mode",
"notePosition": 250,
"prefix": null,
"isExpanded": false,
"type": "text",
"mime": "text/html",
"attributes": [
{
"type": "label",
"name": "shareAlias",
"value": "safe-mode",
"isInheritable": false,
"position": 20
},
{
"type": "label",
"name": "iconClass",
"value": "bx bxs-virus-block",
"isInheritable": false,
"position": 30
}
],
"format": "markdown",
"dataFileName": "Safe mode.md",
"attachments": []
} }
] ]
}, },

View File

@@ -0,0 +1,2 @@
# Nix flake
This is a clone of a note. Go to its [primary location](../Desktop%20Installation/Nix%20flake.md).