# blobs

blobId: BV960M5pex2TXr6hOHEi
dateModified: 2025-03-09 12:18:55.626+0200
utcDateModified: 2025-03-09 10:18:55.756Z
content:
  <div class="content">
         

        <div class="ck-content">
          <p><a href="https://github.com/lokalise/i18n-ally"><code>i18n-ally</code></a> is
            a VS Code extension that aids in internationalization.</p>
          <p>It is currently integrated in the project and offers features such as:</p>
          <ul>
            <li>Highlight, autocomplete translations.</li>
            <li>Display translations inline.</li>
            <li>Extract messages into translation.</li>
          </ul>
          <h3>Extracting messages into translation</h3>
          <ol>
            <li>Open any .js file and select an untranslated string inside a template
              (<code>TPL</code>).</li>
            <li>Press Ctrl+P and look for “i18n Ally: Extract text into i18n messages”</li>
            <li>Select the first template.</li>
            <li>Select the path of translation, taking into consideration the&nbsp;
              <a
              class="reference-link" href="#root/jmdNDjhIzbIx">Guidelines</a>&nbsp;(e.g. <code>jump_to_note.search-for-note-by-its-name</code>).</li>
          </ol>
        </div>
      </div>


blobId: ev5eDgV5MSEjRTwoGmLk
dateModified: 2025-03-09 12:18:55.626+0200
utcDateModified: 2025-03-09 10:18:55.759Z
content:
  <div class="content">
         

        <div class="ck-content">
          <ul>
            <li>Server-side translations are managed by the same library as the client,
              i18next.</li>
            <li>The translation files reside in the <code>/translations</code> directory,
              following the same convention as the client (<code>translations/{{lng}}/{{ns}}.json</code>),
              where the namespace is <code>server.json</code>. So for the Spanish translations
              we have <code>translations/es/server.json</code>.</li>
            <li>Loading of translations is managed by <a href="https://github.com/i18next/i18next-fs-backend">i18next-fs-backend</a> which
              loads the translations directly from the file system (unlike HTTP requests
              like the client), at the path mentioned previously (relative to <code>package.json</code>).</li>
          </ul>
          <h2>How to translate a string</h2>
          <p>Unlike the client which uses a dedicated client service, the i18next library
            on the server is used directly, as such:</p><pre><code class="language-application-javascript-env-frontend">import { t } from "i18next";

  const translatedString = t("message.id");</code></pre>
          <h2>What should be translated</h2>
          <ul>
            <li>Avoid translating server-side logs, as those are supposed to be for debugging
              and as such there is no benefit in translating them.</li>
            <li>Translate any user-facing message that comes from the server, such as
              error messages shown in the Electron application, or information such as
              keyboard shortcuts, note titles, etc.</li>
          </ul>
        </div>
      </div>


blobId: 4mS2juYTP6u8jvG5GnB3
dateModified: 2025-03-09 12:18:55.626+0200
utcDateModified: 2025-03-09 10:18:55.761Z
content:
  <div class="content">
         

        <div class="ck-content">
          <h2>Server live reload</h2>
          <p>If running the server using <code>npm run start-server</code>, the server
            will watch for changes in <code>src/public</code> and trigger a frontend
            reload if that occurs.</p>
          <h2>Electron live reload</h2>
          <p>Similarly, <code>npm run start-electron</code> supports live refresh &nbsp;as
            well.</p>
          <p>However, a core difference is that Electron watches <code>dist/src/public</code> instead
            of <code>src/public</code> since Electron runs on its own copy of the files.</p>
          <p>To ameliorate that, a separate watch script has been implemented which
            automatically copies files from <code>src/public</code> to <code>dist/src/public</code> whenever
            a change is detected. To run it:</p><pre><code class="language-text-plain">npm run </code></pre>
          <h2>Technical details</h2>
          <ul>
            <li>This mechanism is managed at server level by watching for changes in<code>services/ws.ts</code>.</li>
          </ul>
        </div>
      </div>


blobId: 8XKJ0OwpnCbjNXKIDLaP
dateModified: 2025-03-09 12:18:55.626+0200
utcDateModified: 2025-03-09 10:18:55.763Z
content:
  <div class="content">
         

        <div class="ck-content">
          <h2>Server-side</h2>
          <ul>
            <li>There are three themes embedded in the application:
              <ul>
                <li><code>light</code>, located in <code>src\public\stylesheets\theme-light.css</code>
                </li>
                <li><code>dark</code>, located in <code>src\public\stylesheets\theme-dark.css</code>
                </li>
                <li><code>next</code>, located in <code>src\public\stylesheets\theme-next.css</code>.</li>
              </ul>
            </li>
            <li>The default theme is set only once, when the database is created and is
              managed by <code>options_init#initNotSyncedOptions</code>.
              <ul>
                <li>In the original implementation: On Electron, the choice between <code>light</code> and <code>dark</code> is
                  done based on the OS preference. Otherwise, the theme is always <code>dark</code>.</li>
                <li>Now, we always choose <code>next</code> as the default theme.</li>
              </ul>
            </li>
            <li>The theme is served via <code>src\routes\index.ts</code>, in the <code>getThemeCssUrl</code> method.</li>
          </ul>
          <h2>Client-side</h2>
          <ul>
            <li>The predefined themes are hard-coded in the client in <code>src\public\app\widgets\type_widgets\options\appearance\theme.js</code>.</li>
            <li>The user-defined themes are obtained via a call to the server: <code>options/user-themes</code>.</li>
            <li>The theme retrieval is done via a request.</li>
          </ul>
        </div>
      </div>


blobId: X49BYQmVGMry9Vms4n4b
dateModified: 2025-03-09 12:18:55.626+0200
utcDateModified: 2025-03-09 10:18:55.767Z
content:
  <div class="content">
         

        <div class="ck-content">
          <p>Entity hashing is done in <code>content_hash#getEntityHashes</code>.</p>
          <ul>
            <li>It works by looking at the <code>entity_changes</code> table and going through
              each of the entity names/types:
              <ul>
                <li><code>blobs</code>
                </li>
                <li><code>attributes</code>
                </li>
                <li><code>revisions</code>
                </li>
                <li><code>attachments</code>
                </li>
                <li><code>notes</code>
                </li>
                <li><code>branches</code>
                </li>
                <li><code>etapi_tokens</code>
                </li>
                <li><code>options</code>
                </li>
              </ul>
            </li>
            <li>For some reason <code>note_reordering</code> entities are ignored specifically.</li>
            <li>All the rows in <code>entity_changes</code> are then ordered alphabetically,
              based on their <code>entityId</code>.</li>
            <li>Every entity row is then grouped by <code>entityName</code> and then by
              sector. The sector is defined as the first character of the <code>id</code>.</li>
            <li>The hash is altered to add the <code>isErased</code> value as well since
              the hash of deleted entries is not updated.</li>
            <li>For each sector, the hash is calculated using <code>utils.hash</code>,
              using SHA1 encoded as Base64.</li>
          </ul>
        </div>
      </div>


blobId: 1BedfcvvJ4ZoaZ8lGNzG
dateModified: 2025-03-09 12:18:55.626+0200
utcDateModified: 2025-03-09 10:18:55.770Z
content:
  <div class="content">
         

        <div class="ck-content">
          <ul>
            <li>Provides context about when the build was made and the corresponding Git
              revision.</li>
            <li>The information is displayed to the client when going in the about dialog.</li>
            <li>The build information is hard-coded in <code>src/services/build.ts</code>.
              This file is generated automatically via <code>npm run update-build-info</code> which
              itself is run automatically whenever making a build in the CI, or a <a href="#root/5jt68zVszBwg">local delivery</a>.</li>
          </ul>
        </div>
      </div>


blobId: BhwuNrgG8nIkowIr2dFl
dateModified: 2025-03-09 12:18:55.626+0200
utcDateModified: 2025-03-09 10:18:55.775Z
content:
  <div class="content">
         

        <div class="ck-content">
          <figure class="table" style="width:100%;">
            <table class="ck-table-resized">
              <colgroup>
                <col style="width:21.13%;">
                  <col style="width:8.03%;">
                    <col style="width:7.85%;">
                      <col style="width:9.86%;">
                        <col style="width:53.13%;">
              </colgroup>
              <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>attachmentId</code>
                  </th>
                  <td>Text</td>
                  <td>Non-null</td>
                  <td>&nbsp;</td>
                  <td>Unique ID (e.g. <code>qhC1vzU4nwSE</code>)</td>
                </tr>
                <tr>
                  <th><code>ownerId</code>
                  </th>
                  <td>Text</td>
                  <td>Non-null</td>
                  <td>&nbsp;</td>
                  <td>The unique ID of a row in&nbsp;<a class="reference-link" href="#root/IGBPgB2RHETG">notes</a>.</td>
                </tr>
                <tr>
                  <th><code>role</code>
                  </th>
                  <td>Text</td>
                  <td>Non-null</td>
                  <td>&nbsp;</td>
                  <td>The role of the attachment: <code>image</code> for images that are attached
                    to a note.</td>
                </tr>
                <tr>
                  <th><code>mime</code>
                  </th>
                  <td>Text</td>
                  <td>Non-null</td>
                  <td>&nbsp;</td>
                  <td>The MIME type of the attachment (e.g. <code>image/png</code>)</td>
                </tr>
                <tr>
                  <th><code>title</code>
                  </th>
                  <td>Text</td>
                  <td>Non-null</td>
                  <td>&nbsp;</td>
                  <td>The title of the attachment.</td>
                </tr>
                <tr>
                  <th><code>isProtected</code>
                  </th>
                  <td>Integer</td>
                  <td>Non-null</td>
                  <td>0</td>
                  <td><code>1</code> if the entity is <a href="#root/Dg4uPB2H4fOz">protected</a>, <code>0</code> otherwise.</td>
                </tr>
                <tr>
                  <th><code>position</code>
                  </th>
                  <td>Integer</td>
                  <td>Non-null</td>
                  <td>0</td>
                  <td>Not sure where the position is relevant for attachments (saw it with values
                    of 10 and 0).</td>
                </tr>
                <tr>
                  <th><code>blobId</code>
                  </th>
                  <td>Text</td>
                  <td>Nullable</td>
                  <td><code>null</code>
                  </td>
                  <td>The corresponding <code>blobId</code> from the&nbsp;<a class="reference-link"
                    href="#root/ju37hnZip2p5">blobs</a>&nbsp;table.</td>
                </tr>
                <tr>
                  <th><code>dateModified</code>
                  </th>
                  <td>Text</td>
                  <td>Non-null</td>
                  <td>&nbsp;</td>
                  <td>Localized modification date (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>Modification date in UTC format (e.g. <code>2023-11-08 16:43:44.204Z</code>)</td>
                </tr>
                <tr>
                  <th><code>utcDateScheduledForErasure</code>
                  </th>
                  <td>Text</td>
                  <td>Nullable</td>
                  <td><code>null</code>
                  </td>
                  <td>&nbsp;</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="#root/6HX57T5uKCPC">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>
              </tbody>
            </table>
          </figure>
        </div>
      </div>


blobId: KyplH3HACPrqRNhEJsrQ
dateModified: 2025-03-09 12:18:55.626+0200
utcDateModified: 2025-03-09 10:18:55.777Z
content:
  <div class="content">
         

        <div class="ck-content">
          <figure class="table">
            <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/NnChTzAIFTCX">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="#root/IGBPgB2RHETG">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="#root/IGBPgB2RHETG">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="#root/6HX57T5uKCPC">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>
          </figure>
        </div>
      </div>


blobId: Tjnhbw8oqquPMwhbjgV9
dateModified: 2025-03-09 12:18:55.626+0200
utcDateModified: 2025-03-09 10:18:55.780Z
content:
  <div class="content">
         

        <div class="ck-content">
          <figure class="table">
            <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>).</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>Localized modification date (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>Modification date in UTC format (e.g. <code>2023-11-08 16:43:44.204Z</code>)</td>
                </tr>
              </tbody>
            </table>
          </figure>
        </div>
      </div>


blobId: o0npGwTkKNWPM8Bs47q8
dateModified: 2025-03-09 12:18:55.626+0200
utcDateModified: 2025-03-09 10:18:55.782Z
content:
  <div class="content">
         

        <div class="ck-content">
          <figure class="table">
            <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>branchId</code>
                  </th>
                  <td>Text</td>
                  <td>Non-null</td>
                  <td>&nbsp;</td>
                  <td>The ID of the branch, in the form of <code>a_b</code> where <code>a</code> is
                    the <code>parentNoteId</code> and <code>b</code> is the <code>noteId</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="#root/IGBPgB2RHETG">note</a>.</td>
                </tr>
                <tr>
                  <th><code>parentNoteId</code>
                  </th>
                  <td>Text</td>
                  <td>Non-null</td>
                  <td>&nbsp;</td>
                  <td>The ID of the parent <a href="#root/IGBPgB2RHETG">note</a> the note belongs to.</td>
                </tr>
                <tr>
                  <th><code>notePosition</code>
                  </th>
                  <td>Integer</td>
                  <td>Non-null</td>
                  <td>&nbsp;</td>
                  <td>The position of the branch within the same level of hierarchy, the value
                    is usually a multiple of 10.</td>
                </tr>
                <tr>
                  <th><code>prefix</code>
                  </th>
                  <td>Text</td>
                  <td>Nullable</td>
                  <td>&nbsp;</td>
                  <td>The <a href="#root/XYuZNL1Z3eao">branch prefix</a> if any, or <code>NULL</code> otherwise.</td>
                </tr>
                <tr>
                  <th><code>isExpanded</code>
                  </th>
                  <td>Integer</td>
                  <td>Non-null</td>
                  <td>0</td>
                  <td>Whether the branch should appear expanded (its children shown) to the
                    user.</td>
                </tr>
                <tr>
                  <th><code>isDeleted</code>
                  </th>
                  <td>Integer</td>
                  <td>Non-null</td>
                  <td>0</td>
                  <td><code>1</code> if the entity is <a href="#root/6HX57T5uKCPC">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>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>
              </tbody>
            </table>
          </figure>
        </div>
      </div>


blobId: oyk3tZy9idvVMHsIEt98
dateModified: 2025-03-09 12:18:55.626+0200
utcDateModified: 2025-03-09 10:18:55.786Z
content:
  <div class="content">
         

        <div class="ck-content">
          <figure class="table">
            <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>id</code>
                  </th>
                  <td>Integer</td>
                  <td>Nullable</td>
                  <td>&nbsp;</td>
                  <td>A sequential numeric index of the entity change.</td>
                </tr>
                <tr>
                  <th><code>entityName</code>
                  </th>
                  <td>Text</td>
                  <td>Nullable</td>
                  <td>&nbsp;</td>
                  <td>The type of entity being changed (<code>attributes</code>, <code>branches</code>, <code>note_reordering</code>,
                    etc.)</td>
                </tr>
                <tr>
                  <th><code>entityId</code>
                  </th>
                  <td>Text</td>
                  <td>Nullable</td>
                  <td>&nbsp;</td>
                  <td>The ID of the entity being changed.</td>
                </tr>
                <tr>
                  <th><code>hash</code>
                  </th>
                  <td>Text</td>
                  <td>Nullable</td>
                  <td>&nbsp;</td>
                  <td>TODO: Describe how the hash is calculated</td>
                </tr>
                <tr>
                  <th><code>isErased</code>
                  </th>
                  <td>Integer</td>
                  <td>Nullable</td>
                  <td>&nbsp;</td>
                  <td>TODO: What does this do?</td>
                </tr>
                <tr>
                  <th><code>changeId</code>
                  </th>
                  <td>Text</td>
                  <td>Nullable</td>
                  <td>&nbsp;</td>
                  <td>TODO: What does this do?</td>
                </tr>
                <tr>
                  <th><code>componentId</code>
                  </th>
                  <td>Text</td>
                  <td>Nullable</td>
                  <td>&nbsp;</td>
                  <td>TODO: What does this do?</td>
                </tr>
                <tr>
                  <th><code>instanceId</code>
                  </th>
                  <td>Text</td>
                  <td>Nullable</td>
                  <td>&nbsp;</td>
                  <td>TODO: What does this do?</td>
                </tr>
                <tr>
                  <th><code>isSynced</code>
                  </th>
                  <td>Integer</td>
                  <td>Nullable</td>
                  <td>&nbsp;</td>
                  <td>TODO: What does this do?</td>
                </tr>
                <tr>
                  <th><code>utcDateChanged</code>
                  </th>
                  <td>Text</td>
                  <td>Nullable</td>
                  <td>&nbsp;</td>
                  <td>Date of the entity change in UTC format (e.g. <code>2023-11-08 16:43:44.204Z</code>)</td>
                </tr>
              </tbody>
            </table>
          </figure>
        </div>
      </div>


blobId: GJxcIAoDiOt1tDAMobD8
dateModified: 2025-03-09 12:18:55.626+0200
utcDateModified: 2025-03-09 10:18:55.789Z
content:
  <div class="content">
         

        <div class="ck-content">
          <figure class="table">
            <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>etapiTokenId</code>
                  </th>
                  <td>Text</td>
                  <td>Non-null</td>
                  <td>&nbsp;</td>
                  <td>A unique ID of the token (e.g. <code>aHmLr5BywvfJ</code>).</td>
                </tr>
                <tr>
                  <th><code>name</code>
                  </th>
                  <td>Text</td>
                  <td>Non-null</td>
                  <td>&nbsp;</td>
                  <td>The name of the token, as is set by the user.</td>
                </tr>
                <tr>
                  <th><code>tokenHash</code>
                  </th>
                  <td>Text</td>
                  <td>Non-null</td>
                  <td>&nbsp;</td>
                  <td>The token itself.</td>
                </tr>
                <tr>
                  <th><code>utcDateCreated</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>)</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>0</td>
                  <td><code>1</code> if the entity is <a href="#root/6HX57T5uKCPC">deleted</a>, <code>0</code> otherwise.</td>
                </tr>
              </tbody>
            </table>
          </figure>
        </div>
      </div>


blobId: Tii526VieHKeyTwoqtsH
dateModified: 2025-03-09 12:18:55.626+0200
utcDateModified: 2025-03-09 10:18:55.793Z
content:
  <div class="content">
         

        <div class="ck-content">
          <figure class="table">
            <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>noteId</code>
                  </th>
                  <td>Text</td>
                  <td>Non-null</td>
                  <td>&nbsp;</td>
                  <td>The unique ID of the note (e.g. <code>2LJrKqIhr0Pe</code>).</td>
                </tr>
                <tr>
                  <th><code>title</code>
                  </th>
                  <td>Text</td>
                  <td>Non-null</td>
                  <td><code>"note"</code>
                  </td>
                  <td>The title of the note, as defined by the user.</td>
                </tr>
                <tr>
                  <th><code>isProtected</code>
                  </th>
                  <td>Integer</td>
                  <td>Non-null</td>
                  <td>0</td>
                  <td><code>1</code> if the entity is <a href="#root/Dg4uPB2H4fOz">protected</a>, <code>0</code> otherwise.</td>
                </tr>
                <tr>
                  <th><code>type</code>
                  </th>
                  <td>Text</td>
                  <td>Non-null</td>
                  <td><code>"text"</code>
                  </td>
                  <td>The type of note (i.e. <code>text</code>, <code>file</code>, <code>code</code>, <code>relationMap</code>, <code>mermaid</code>, <code>canvas</code>).</td>
                </tr>
                <tr>
                  <th><code>mime</code>
                  </th>
                  <td>Text</td>
                  <td>Non-null</td>
                  <td><code>"text/html"</code>
                  </td>
                  <td>The MIME type of the note (e.g. <code>text/html</code>).. Note that it
                    can be an empty string in some circumstances, but not null.</td>
                </tr>
                <tr>
                  <th><code>isDeleted</code>
                  </th>
                  <td>Integer</td>
                  <td>Nullable</td>
                  <td>0</td>
                  <td><code>1</code> if the entity is <a href="#root/6HX57T5uKCPC">deleted</a>, <code>0</code> otherwise.</td>
                </tr>
                <tr>
                  <th><code>deleteId</code>
                  </th>
                  <td>Text</td>
                  <td>Non-null</td>
                  <td><code>null</code>
                  </td>
                  <td>&nbsp;</td>
                </tr>
                <tr>
                  <th><code>dateCreated</code>
                  </th>
                  <td>Text</td>
                  <td>Non-null</td>
                  <td>&nbsp;</td>
                  <td>Localized creation date (e.g. <code>2023-11-08 18:43:44.204+0200</code>)</td>
                </tr>
                <tr>
                  <th><code>dateModified</code>
                  </th>
                  <td>Text</td>
                  <td>Non-null</td>
                  <td>&nbsp;</td>
                  <td>Localized modification date (e.g. <code>2023-11-08 18:43:44.204+0200</code>)</td>
                </tr>
                <tr>
                  <th><code>utcDateCreated</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>)</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>blobId</code>
                  </th>
                  <td>Text</td>
                  <td>Nullable</td>
                  <td><code>null</code>
                  </td>
                  <td>The corresponding ID from&nbsp;<a class="reference-link" href="#root/ju37hnZip2p5">blobs</a>.
                    Although it can theoretically be <code>NULL</code>, haven't found any such
                    note yet.</td>
                </tr>
              </tbody>
            </table>
          </figure>
        </div>
      </div>


blobId: cS0DQAI7YN8DfN9jkpEi
dateModified: 2025-03-09 12:18:55.626+0200
utcDateModified: 2025-03-09 10:18:55.797Z
content:
  <div class="content">
         

        <div class="ck-content">
          <figure class="table">
            <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>name</code>
                  </th>
                  <td>Text</td>
                  <td>Non-null</td>
                  <td>&nbsp;</td>
                  <td>The name of option (e.g. <code>maxContentWidth</code>)</td>
                </tr>
                <tr>
                  <th><code>value</code>
                  </th>
                  <td>Text</td>
                  <td>Non-null</td>
                  <td>&nbsp;</td>
                  <td>The value of the option.</td>
                </tr>
                <tr>
                  <th><code>isSynced</code>
                  </th>
                  <td>Integer</td>
                  <td>Non-null</td>
                  <td>0</td>
                  <td><code>0</code> if the option is not synchronized and thus can differ between
                    clients, <code>1</code> if the option is synchronized.</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>
              </tbody>
            </table>
          </figure>
        </div>
      </div>


blobId: nLEN5DgUqMs4eHWiVWAl
dateModified: 2025-03-09 12:18:55.626+0200
utcDateModified: 2025-03-09 10:18:55.800Z
content:
  <div class="content">
         

        <div class="ck-content">
          <figure class="table">
            <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>noteId</code>
                  </th>
                  <td>Text</td>
                  <td>Non-null</td>
                  <td>&nbsp;</td>
                  <td>Unique ID of the note (e.g. <code>yRRTLlqTbGoZ</code>).</td>
                </tr>
                <tr>
                  <th><code>notePath</code>
                  </th>
                  <td>Text</td>
                  <td>Non-null</td>
                  <td>&nbsp;</td>
                  <td>The path (IDs) to the <a href="#root/IGBPgB2RHETG">note</a> from root to the note
                    itself, separated by slashes.</td>
                </tr>
                <tr>
                  <th><code>utcDateCreated</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>)</td>
                </tr>
              </tbody>
            </table>
          </figure>
        </div>
      </div>


blobId: PGDnJXQKiljnasvTsTNF
dateModified: 2025-03-09 12:18:55.626+0200
utcDateModified: 2025-03-09 10:18:55.805Z
content:
  <div class="content">
         

        <div class="ck-content">
          <figure class="table">
            <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>revisionId</code>
                  </th>
                  <td>TextText</td>
                  <td>Non-null</td>
                  <td>&nbsp;</td>
                  <td>Unique ID of the revision (e.g. <code>0GjgUqnEudI8</code>).</td>
                </tr>
                <tr>
                  <th><code>noteId</code>
                  </th>
                  <td>Text</td>
                  <td>Non-null</td>
                  <td>&nbsp;</td>
                  <td>ID of the <a href="#root/IGBPgB2RHETG">note</a> this revision belongs to.</td>
                </tr>
                <tr>
                  <th><code>type</code>
                  </th>
                  <td>Text</td>
                  <td>Non-null</td>
                  <td><code>""</code>
                  </td>
                  <td>The type of note (i.e. <code>text</code>, <code>file</code>, <code>code</code>, <code>relationMap</code>, <code>mermaid</code>, <code>canvas</code>).</td>
                </tr>
                <tr>
                  <th><code>mime</code>
                  </th>
                  <td>Text</td>
                  <td>Non-null</td>
                  <td><code>""</code>
                  </td>
                  <td>The MIME type of the note (e.g. <code>text/html</code>).</td>
                </tr>
                <tr>
                  <th><code>title</code>
                  </th>
                  <td>Text</td>
                  <td>Non-null</td>
                  <td>&nbsp;</td>
                  <td>The title of the note, as defined by the user.</td>
                </tr>
                <tr>
                  <th><code>isProtected</code>
                  </th>
                  <td>Integer</td>
                  <td>Non-null</td>
                  <td>0</td>
                  <td><code>1</code> if the entity is <a href="#root/Dg4uPB2H4fOz">protected</a>, <code>0</code> otherwise.</td>
                </tr>
                <tr>
                  <th><code>blobId</code>
                  </th>
                  <td>Text</td>
                  <td>Nullable</td>
                  <td><code>null</code>
                  </td>
                  <td>The corresponding ID from&nbsp;<a class="reference-link" href="#root/ju37hnZip2p5">blobs</a>.
                    Although it can theoretically be <code>NULL</code>, haven't found any such
                    note yet.</td>
                </tr>
                <tr>
                  <th><code>utcDateLastEdited</code>
                  </th>
                  <td>Text</td>
                  <td>Non-null</td>
                  <td>&nbsp;</td>
                  <td><strong>Not sure how it differs from modification date.</strong>
                  </td>
                </tr>
                <tr>
                  <th><code>utcDateCreated</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>)</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>dateLastEdited</code>
                  </th>
                  <td>Text</td>
                  <td>Non-null</td>
                  <td>&nbsp;</td>
                  <td><strong>Not sure how it differs from modification date.</strong>
                  </td>
                </tr>
                <tr>
                  <th><code>dateCreated</code>
                  </th>
                  <td>Text</td>
                  <td>Non-null</td>
                  <td>&nbsp;</td>
                  <td>Localized creatino date (e.g. <code>2023-08-12 15:10:04.045+0300</code>)</td>
                </tr>
              </tbody>
            </table>
          </figure>
        </div>
      </div>


blobId: UHg7IN1jYJ1tsVYLN7E6
dateModified: 2025-03-09 12:18:55.626+0200
utcDateModified: 2025-03-09 10:18:55.809Z
content:
  <div class="content">
         

        <div class="ck-content">
          <p>The following entities can be made protected, via their <code>isProtected</code> flag:</p>
          <ul>
            <li><a class="reference-link" href="#root/duw4MXvDJMWD">attachments</a>
            </li>
            <li><a class="reference-link" href="#root/IGBPgB2RHETG">notes</a>
            </li>
            <li><a class="reference-link" href="#root/JxUVp60zWDIy">revisions</a>
            </li>
          </ul>
        </div>
      </div>


blobId: 3UjpwGAL4cFgaHHGsKZm
dateModified: 2025-03-09 12:18:55.626+0200
utcDateModified: 2025-03-09 10:18:55.857Z
content:
  <div class="content">
         

        <div class="ck-content">
          <p>The note type is defined by the <code>type</code> column in&nbsp;<a class="reference-link"
            href="#root/IGBPgB2RHETG">notes</a>.</p>
          <p>Possible types:</p>
          <figure class="table" style="width:100%;">
            <table class="ck-table-resized">
              <colgroup>
                <col style="width:9.01%;">
                  <col style="width:10.33%;">
                    <col style="width:29.72%;">
                      <col style="width:23.85%;">
                        <col style="width:27.09%;">
              </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>
          </figure>
        </div>
      </div>


blobId: WL2UZ5GiP71F0mWXENJ3
dateModified: 2025-03-09 12:18:55.626+0200
utcDateModified: 2025-03-09 10:18:55.861Z
content:
  <div class="content">
         

        <div class="ck-content">
          <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>Disables <code>customWidget</code> launcher types in <code>app/widgets/containers/launcher.js</code>.</li>
            <li>Disables the running of <code>mobileStartup</code> or <code>frontendStartup</code> scripts.</li>
            <li>Displays the root note instead of the previously saved session.</li>
            <li>Disables the running of <code>backendStartup</code>, <code>hourly</code>, <code>daily</code> scripts
              and checks for the hidden subtree.</li>
          </ul>
        </div>
      </div>


blobId: MBG0scetLqUeXnqM1IEJ
dateModified: 2025-03-09 12:18:55.626+0200
utcDateModified: 2025-03-09 10:18:55.868Z
content:
  <div class="content">
         

        <div class="ck-content">
          <p>Icons are stored in <code>images</code> and in <code>images/app-icons</code>.</p>
          <h2>Favicon</h2>
          <p>The favicon is served dynamically via <code>serve-favicon</code>, using
            the icon in <code>images/app-icons/win/icon.ico</code>.</p>
          <h2>Declarative generation of icons</h2>
          <p>All the icons are now built off of the SVGs in the <code>images</code> directory
            using the <code>bin/create-icons.sh</code> script.</p>
          <h2>Main images</h2>
          <p>These are stored in <code>images</code>:</p>
          <figure class="table">
            <table>
              <thead>
                <tr>
                  <th>Name</th>
                  <th>Resolution</th>
                  <th>Description</th>
                </tr>
              </thead>
              <tbody>
                <tr>
                  <td><code>icon-black.svg</code>
                  </td>
                  <td>53x40</td>
                  <td>Used by the global menu button when not hovered.</td>
                </tr>
                <tr>
                  <td><code>icon-color.svg</code>
                  </td>
                  <td>53x40</td>
                  <td>Used by the global menu when hovered.</td>
                </tr>
                <tr>
                  <td><code>icon-grey.svg</code>
                  </td>
                  <td>53x40</td>
                  <td>Used by the dark theme, in place of <code>icon-black.svg</code>.</td>
                </tr>
              </tbody>
            </table>
          </figure>
          <h2>App icons</h2>
          <figure class="table">
            <table>
              <thead>
                <tr>
                  <th>Name</th>
                  <th>Resolution</th>
                  <th>Description</th>
                </tr>
              </thead>
              <tbody>
                <tr>
                  <td><code>ios/apple-touch-icon.png</code>
                  </td>
                  <td>180x180</td>
                  <td>Used as <code>apple-touch-icon</code>, but only in <code>login.ejs</code> and <code>set_password.ejs</code> for
                    some reason.</td>
                </tr>
                <tr>
                  <td><code>mac/icon.icns</code>
                  </td>
                  <td>512x512</td>
                  <td>Provided as <code>--icon</code> to <code>electron-packager</code> for <code>mac-arm64</code> and <code>mac-x64</code> 
                    <a
                    href="#root/5jt68zVszBwg">builds</a>.</td>
                </tr>
                <tr>
                  <td><code>png/128x128.png</code>
                  </td>
                  <td>128x128</td>
                  <td>Used in <code>linux-x64</code>  <a href="#root/5jt68zVszBwg">build</a>,
                    to provide an <code>icon.png</code>.</td>
                </tr>
                <tr>
                  <td><code>png/256x256-dev.png</code>
                  </td>
                  <td rowspan="2">256x256</td>
                  <td>Used by the Electron window icon, if in dev mode.</td>
                </tr>
                <tr>
                  <td><code>png/256x256.png</code>
                  </td>
                  <td>Used by the Electron window icon, if not in dev mode.</td>
                </tr>
                <tr>
                  <td><code>win/icon.ico</code>
                  </td>
                  <td>
                    <ul>
                      <li>ICO 16x16</li>
                      <li>ICO 32x32</li>
                      <li>ICO 48x48</li>
                      <li>ICO 64x64</li>
                      <li>ICO 128x128</li>
                      <li>PNG 256x256</li>
                    </ul>
                  </td>
                  <td>
                    <ul>
                      <li>Used by the <code>win-x64</code>  <a href="#root/5jt68zVszBwg">build</a>.</li>
                      <li>Used by Squirrel Windows installer for: setup icon, app icon, control
                        panel icon</li>
                      <li>Used as the favicon.</li>
                    </ul>
                  </td>
                </tr>
                <tr>
                  <td><code>win/setup-banner.gif</code>
                  </td>
                  <td>640x480</td>
                  <td>Used by the Squirrel Windows installer during the installation process.
                    Has only one frame.</td>
                </tr>
              </tbody>
            </table>
          </figure>
          <h2>Additional locations where the branding is used</h2>
          <ul>
            <li>In the client, more specifically in <code>src/public/app/widgets/buttons/global_menu.js</code>,
              where the SVG content of the icon is directly embedded to allow styling
              via CSS.</li>
            <li>In the&nbsp;<a class="reference-link" href="#root/N864ORbFlbUC">Demo document</a>,
              as an attachment.</li>
            <li>In the&nbsp;<a class="reference-link" href="#root/OeKBfN6JbMIq/MF99QFRe1gVy/xkj1bqW7zJwQ/t6mT72MfEzb2">CKEditor</a>&nbsp;build,
              look for <code>packages/ckeditor5-build-balloon-block/src/icons/trilium.svg</code>.
              Make sure not to have any <code>fill</code> overrides in the SVG as the wrong
              color will be used.</li>
          </ul>
        </div>
      </div>


blobId: C9iQPs8vzEk2Z1v6WHLn
dateModified: 2025-03-09 12:18:55.626+0200
utcDateModified: 2025-03-09 10:18:55.872Z
content:
  <div class="content">
         

        <div class="ck-content">
          <p>The following icons were removed:</p>
          <h2>Main images</h2>
          <p>These are stored in <code>images</code>:</p>
          <figure class="table">
            <table>
              <thead>
                <tr>
                  <th>Name</th>
                  <th>Resolution</th>
                  <th>Description</th>
                </tr>
              </thead>
              <tbody>
                <tr>
                  <td><code>icon-black.png</code>
                  </td>
                  <td>36x36</td>
                  <td>Does not appear to be used.</td>
                </tr>
                <tr>
                  <td><code>icon-color.png</code>
                  </td>
                  <td>36x36</td>
                  <td>Used only by some tests in <code>test-etapi</code>.</td>
                </tr>
                <tr>
                  <td><code>icon-grey.png</code>
                  </td>
                  <td>36x36</td>
                  <td>Does not appear to be used.</td>
                </tr>
                <tr>
                  <td><code>icon.svg</code>
                  </td>
                  <td>210x297</td>
                  <td>Does not appear to be used.</td>
                </tr>
              </tbody>
            </table>
          </figure>
          <h2>App icons</h2>
          <figure class="table">
            <table>
              <thead>
                <tr>
                  <th>Name</th>
                  <th>Resolution</th>
                  <th>Description</th>
                </tr>
              </thead>
              <tbody>
                <tr>
                  <td><code>png/16x16-bw.png</code>
                  </td>
                  <td rowspan="2">16x16</td>
                  <td rowspan="7">Do not appear to be used.</td>
                </tr>
                <tr>
                  <td><code>png/16x16.png</code>
                  </td>
                </tr>
                <tr>
                  <td><code>png/24x24.png</code>
                  </td>
                  <td>24x24</td>
                </tr>
                <tr>
                  <td><code>png/32x32.png</code>
                  </td>
                  <td>32x32</td>
                </tr>
                <tr>
                  <td><code>png/48x48.png</code>
                  </td>
                  <td>48x48</td>
                </tr>
                <tr>
                  <td><code>png/64x64.png</code>
                  </td>
                  <td>64x64</td>
                </tr>
                <tr>
                  <td><code>png/96x96.png</code>
                  </td>
                  <td>96x96</td>
                </tr>
                <tr>
                  <td><code>png/512x512.png</code>
                  </td>
                  <td>512x512</td>
                  <td>Does not appear to be used.</td>
                </tr>
                <tr>
                  <td style="border-top:1px solid rgb(222, 226, 230);padding:0.75rem;"><code>win/setup-banner.xcf</code>
                  </td>
                  <td style="border-top:1px solid rgb(222, 226, 230);padding:0.75rem;">&nbsp;</td>
                  <td style="border-top:1px solid rgb(222, 226, 230);padding:0.75rem;">GIMP source for <code>win/setup-banner.gif</code>. Provided only for future
                    editing.</td>
                </tr>
              </tbody>
            </table>
          </figure>
        </div>
      </div>


blobId: yqK7SIMAEeqpYrilpfLE
dateModified: 2025-03-09 12:18:55.626+0200
utcDateModified: 2025-03-09 10:18:55.876Z
content:
  <div class="content">
         

        <div class="ck-content">
          <p>&nbsp;</p>
          <p>Looks great in Finder:</p>
          <figure class="image">
            <img style="aspect-ratio:1972/728;" src="api/attachments/MGiHilLmJkM2/image/1_Icons on Mac_image.png" width="1972"
            height="728">
          </figure>
          <p>Looks great in Dock:</p>
          <figure class="image">
            <img style="aspect-ratio:1960/302;" src="api/attachments/maB5f1sqlw34/image/Icons on Mac_image.png" width="1960"
            height="302">
          </figure>
        </div>
      </div>


blobId: Ph8xoMBnGLElAwQCF0PS
dateModified: 2025-03-09 12:18:55.626+0200
utcDateModified: 2025-03-09 10:18:55.910Z
content:
  <div class="content">
         

        <div class="ck-content">
          <p>Slightly blurry in extended preview on Mac</p>
          <figure class="image">
            <img style="aspect-ratio:2406/1598;" src="api/attachments/LTIkbHYLuHyh/image/1_Slightly blurry icon on Ma.png"
            width="2406" height="1598">
          </figure>
          <p>In the screenshot, the icon is around 650px whereas the closest image
            we have is 512px, so that might explain the blur. Adding an <code>ic10</code> (<code>1024x1024</code>,
            aka <code>512x512@2x</code> to see what happens).</p>
          <p>Before:</p><pre><code class="language-text-plain">File: ../images/app-icons/mac/icon.icns
    ic09: 62069 bytes, png: 512x512</code></pre>
          <p>After:</p><pre><code class="language-text-plain">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</code></pre>
          <p>Even with a 1024x1024 icon, the image is still blurry.</p>
          <p>Comparing the <code>.icns</code> file from the Electron build reveals that
            the <code>.icns</code> file has been tampered with:</p>
          <figure class="table">
            <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>
          </figure>
          <p>The bluriness might come from the image itself: <a href="https://stackoverflow.com/questions/54030521/convert-svg-to-png-with-sharp-edges">https://stackoverflow.com/questions/54030521/convert-svg-to-png-with-sharp-edges</a>&nbsp;</p>
          <p>Rendering with Inkscape (left) vs ImageMagick (right):</p>
          <figure class="image">
            <img style="aspect-ratio:1234/528;" src="api/attachments/25AjJTitMObV/image/2_Slightly blurry icon on Ma.png"
            width="1234" height="528">
          </figure>
          <p>Now in macOS it's also rendering quite nicely:</p>
          <figure class="image">
            <img style="aspect-ratio:2470/1630;" src="api/attachments/8TF8ANOmH33X/image/Slightly blurry icon on Ma.png"
            width="2470" height="1630">
          </figure>
        </div>
      </div>


blobId: gtXKDriS7B3aHwUTOTWD
dateModified: 2025-03-09 12:18:55.626+0200
utcDateModified: 2025-03-09 10:18:56.001Z
content:
  <div class="content">
         

        <div class="ck-content">
          <figure class="table" style="width:100%;">
            <table class="ck-table-resized">
              <colgroup>
                <col style="width:11.22%;">
                  <col style="width:88.78%;">
              </colgroup>
              <tbody>
                <tr>
                  <th>Before</th>
                  <td>
                    <figure class="image">
                      <img style="aspect-ratio:1960/302;" src="api/attachments/27VbmHQe8jNt/image/2_Adaptive icon_image.png" width="1960"
                      height="302">
                    </figure>
                  </td>
                </tr>
                <tr>
                  <th>After</th>
                  <td>
                    <figure class="image">
                      <img style="aspect-ratio:2116/302;" src="api/attachments/xzFpYwjN8R14/image/6_Adaptive icon_image.png" width="2116"
                      height="302">
                    </figure>
                  </td>
                </tr>
                <tr>
                  <th>With new scale</th>
                  <td>
                    <figure class="image">
                      <img style="aspect-ratio:2116/302;" src="api/attachments/cH4zqfKx4oLh/image/5_Adaptive icon_image.png" width="2116"
                      height="302">
                    </figure>
                  </td>
                </tr>
              </tbody>
            </table>
          </figure>
          <h2>Scale</h2>
          <figure class="table" style="width:300px;">
            <table>
              <tbody>
                <tr>
                  <th>0.9</th>
                  <td style="background-color:hsl(0, 0%, 90%);">
                    <figure class="image">
                      <img style="aspect-ratio:128/128;" src="api/attachments/MMEDNXcfP7S7/image/Adaptive icon_image.png" width="128"
                      height="128">
                    </figure>
                  </td>
                </tr>
                <tr>
                  <th>0.85</th>
                  <td style="background-color:hsl(0, 0%, 90%);">
                    <figure class="image">
                      <img style="aspect-ratio:128/128;" src="api/attachments/zvMwg8B8Nkf5/image/1_Adaptive icon_image.png" width="128"
                      height="128">
                    </figure>
                  </td>
                </tr>
                <tr>
                  <th>0.8</th>
                  <td style="background-color:hsl(0, 0%, 90%);">
                    <figure class="image">
                      <img style="aspect-ratio:128/128;" src="api/attachments/5UwXDdE8lRdr/image/3_Adaptive icon_image.png" width="128"
                      height="128">
                    </figure>
                  </td>
                </tr>
                <tr>
                  <th>0.75</th>
                  <td style="background-color:hsl(0, 0%, 90%);">
                    <figure class="image">
                      <img style="aspect-ratio:128/128;" src="api/attachments/5aWSWVuL19A4/image/4_Adaptive icon_image.png" width="128"
                      height="128">
                    </figure>
                  </td>
                </tr>
              </tbody>
            </table>
          </figure>
        </div>
      </div>


blobId: LzeAcsVZRdoX5XUBG4ye
dateModified: 2025-03-09 12:18:55.626+0200
utcDateModified: 2025-03-09 10:18:56.135Z
content:
  <div class="content">
         

        <div class="ck-content">
          <p>The demo document is an exported .zip that resides in <code>db/demo.zip</code>.</p>
          <p>During on-boarding, if the user selects that they are a new user then
            the <code>demo.zip</code> is imported into the root note.</p>
          <h2>Modifying the document</h2>
          <p>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 <code>db/demo.zip</code>.
            Make sure to disable “Safe import”.</p>
          <p>After making the necessary modifications, simply export the “Trilium Demo”
            note as “HTML in ZIP archive” and replace <code>db/demo.zip</code> with the
            newly exported one.</p>
          <h2>Testing the changes</h2><pre><code class="language-text-plain">rm -r data
  npm run start-server</code></pre>
          <p>And then do the on-boarding again.</p>
        </div>
      </div>


blobId: XJRuTZ3gSBfSrFC9oTkc
dateModified: 2025-03-09 12:18:55.626+0200
utcDateModified: 2025-03-09 10:18:56.139Z
content:
  <div class="content">
         

        <div class="ck-content">
          <p>To run a Docker build:</p><pre><code class="language-text-plain">./bin/builder-docker.sh</code></pre>
          <p>To run the built Docker image:</p><pre><code class="language-text-plain">sudo docker run -p 8081:8080 triliumnext/notes:v0.90.6-beta</code></pre>
          <p>To enter a shell in the Docker container:</p><pre><code class="language-text-plain">sudo docker run -it --entrypoint=/bin/sh zadam/trilium:0.63-latest</code></pre>
        </div>
      </div>


blobId: 4KRm4SbmtmOBNZPRGyhW
dateModified: 2025-03-09 12:18:55.626+0200
utcDateModified: 2025-03-09 10:18:56.143Z
content:
  <div class="content">
         

        <div class="ck-content">
          <h2>Read an option</h2>
          <p>Add the import to the service (make sure the relative path is correct):</p><pre><code class="language-application-javascript-env-frontend">import options from "../../services/options.js";</code></pre>
          <p>Them simply read the option:</p><pre><code class="language-application-javascript-env-frontend">this.firstDayOfWeek = options.getInt("firstDayOfWeek");</code></pre>
        </div>
      </div>


blobId: N7bYvoAnkSVSVl5JniY4
dateModified: 2025-03-09 12:18:55.626+0200
utcDateModified: 2025-03-09 10:18:56.147Z
content:
  <div class="content">
         

        <div class="ck-content">
          <p>In the TPL:</p><pre><code class="language-text-html">&lt;div class="options-section"&gt;
      &lt;h4&gt;Background effects&lt;/h4&gt;

      &lt;p&gt;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.&lt;/p&gt;

      &lt;div class="col-6 side-checkbox"&gt;
          &lt;label class="form-check"&gt;
              &lt;input type="checkbox" class="background-effects form-check-input" /&gt;
              Enable background effects (Windows 11 only)
          &lt;/label&gt;
      &lt;/div&gt;
  &lt;/div&gt;</code></pre>
          <p>In <code>doRender()</code>:</p><pre><code class="language-text-x-trilium-auto">doRender() {
  	this.$backgroundEffects = this.$widget.find("input.background-effects");

  	this.$backgroundEffects.on("change", () =&gt; this.updateCheckboxOption("backgroundEffects", this.$backgroundEffects));
  }</code></pre>
          <p>In <code>optionsLoaded(options)</code>:</p><pre><code class="language-text-x-trilium-auto">async optionsLoaded(options) {

      this.setCheckboxState(this.$backgroundEffects, options.backgroundEffects);

  }</code></pre>
        </div>
      </div>


blobId: VrpY4wGH5xyMTkI8TpXL
dateModified: 2025-03-09 12:18:55.626+0200
utcDateModified: 2025-03-09 10:18:56.150Z
content:
  <div class="content">
         

        <div class="ck-content">
          <p>Call <code>utils.reloadFrontendApp</code>, but make sure to wait for the
            option to be saved first.</p><pre><code class="language-text-x-trilium-auto">this.$backgroundEffects.on("change", async () =&gt; {

      await this.updateCheckboxOption("backgroundEffects", this.$backgroundEffects);

      utils.reloadFrontendApp("background effect change");

  });</code></pre>
        </div>
      </div>


blobId: JZ66sDSV54J3OagqzOtf
dateModified: 2025-03-09 12:18:55.626+0200
utcDateModified: 2025-03-09 10:18:56.154Z
content:
  <div class="content">
         

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


blobId: iF9WERZLNX6wxYX1oIsB
dateModified: 2025-03-09 12:18:55.626+0200
utcDateModified: 2025-03-09 10:18:56.158Z
content:
  <div class="content">
         

        <div class="ck-content">
          <p>To make a widget react to a change of a given option, simply add the following
            to the widget:</p><pre><code class="language-application-javascript-env-frontend">async entitiesReloadedEvent({loadResults}) {
      if (loadResults.getOptionNames().includes("firstDayOfWeek")) {
          // Do something.
      }        
  }</code></pre>
        </div>
      </div>


blobId: z7vn501TgGvlXwHQRYBI
dateModified: 2025-03-09 12:18:55.626+0200
utcDateModified: 2025-03-09 10:18:56.162Z
content:
  <div class="content">
         

        <div class="ck-content">
          <h2>Step 1. Create the option</h2>
          <p>To add a new option with a set default, go to <code>options_init.ts</code> in
            the server and add a new entry in the <code>defaultOptions</code>.</p>
          <h2>Step 2. Make the option available to the client</h2>
          <p>By default options are not adjustable or visible to the client. To do
            so, modify <code>routes/api/options.ts</code> to add the newly added option
            to <code>ALLOWED_OPTIONS</code>.</p>
        </div>
      </div>


blobId: OVsqbAP32xgMQrFZmyXm
dateModified: 2025-03-09 12:18:55.626+0200
utcDateModified: 2025-03-09 10:18:56.169Z
content:
  <div class="content">
         

        <div class="ck-content">
          <blockquote>
            <p><strong>Note</strong>: When adding or updating step titles/order, don't
              forget to update the corresponding list in&nbsp;<a class="reference-link"
              href="#root/vXCD0qqdny5c">Note type checklist</a>.</p>
          </blockquote>
          <h2>Step 1. Register the note type in the server</h2>
          <p>Go to <code>src\services\note_types.ts</code> and add a new entry in <code>noteTypes</code> with
            the type ID and the default MIME type.</p>
          <h2>Step 2. Register the note type in the client context menu</h2>
          <p>The client lists the available note types in <code>src\public\app\services\note_types.js</code>.</p>
          <h2>Step 3. Create a type widget</h2>
          <p>Go to <code>src\public\app\widgets\type_widgets</code> directory and create
            a new file corresponding to the new note type.</p>
          <p>A blank implementation looks something like this:</p>
          <section class="include-note"
          data-note-id="7zPG0kz3CodO" data-box-size="full">&nbsp;</section>
          <h2>Step 4. Register the type widget</h2>
          <p>The type widget needs to go in <code>src\public\app\widgets\note_detail.ts</code>where
            there is a <code>typeWidgetClasses</code> map, mapping the type IDs with
            the corresponding type widget that was created at the previous step.</p>
          <h2>Step 5. Add the default icon mapping</h2>
          <p>To set a default icon for this note type, go to <code>src\public\app\entities\fnote.js</code> and
            add it to <code>NOTE_TYPE_ICONS</code>.</p>
          <h2>Step 6. Add to note type selector</h2>
          <p>Go to <code>src/public/app/widgets/note_type.js</code> and register the
            new note type in <code>NOTE_TYPES</code>.</p>
          <h2>Step 7. Add the note to server allowed note types</h2>
          <p>This is required in order to make imports possible, otherwise they will
            be imported as plain text.</p>
          <p>Go to <code>src/becca/entities/rows.ts</code> and add the new note type
            to <code>ALLOWED_NOTE_TYPES</code>.</p>
          <h2>Additional changes</h2>
          <ul>
            <li>If the widget requires a full height, it must be configured in <code>src\public\app\widgets\note_detail.js</code> (look
              for <code>checkFullHeight</code>) then a <code>height: 100%</code> style can
              be applied to the containers to make them fit.</li>
            <li>To make the note always full width (ignoring the user's content width),
              go to <code>note_wrapper</code> and look for the <code>refresh</code> method.
              There is a <code>toggleClass</code> for <code>full-content-width</code> based
              on the note type.</li>
            <li>To allow the note source to be viewed, go to <code>src/public/app/widgets/buttons/note_actions.js</code> and
              look for <code>this.toggleDisabled(this.$showSourceButton</code> in <code>refreshVisibility</code>.</li>
          </ul>
          <h2>Final steps</h2>
          <ul>
            <li>Update the&nbsp;<a class="reference-link" href="#root/N864ORbFlbUC">Demo document</a>&nbsp;to
              showcase the new note type.</li>
          </ul>
          <h2>Troubleshooting</h2>
          <h3>Content does not appear, however it appears as hidden in the DOM</h3>
          <p>Type widgets do a check whenever a note is selected to determine whether
            the widget needs to be displayed or not, based on the note type. Make sure <code>getType()</code> is
            well implemented in the newly added type widget (take great care that the
            value is returned but also that the note type ID matches the ones registered
            in the previous steps):</p><pre><code class="language-text-plain">static getType() { return "foo"; }</code></pre>
        </div>
      </div>


blobId: kulvjBX3YHgyJfILQez1
dateModified: 2025-03-09 12:18:55.626+0200
utcDateModified: 2025-03-09 10:18:56.172Z
content:
  import TypeWidget from "./type_widget.js";

  const TPL = `
  <div class="note-detail-mind-map note-detail-printable">
  </div>
  `;

  export default class MindMapWidget extends TypeWidget {
      static getType() { return "mindMap"; }

      doRender() {
          this.$widget = $(TPL);

          super.doRender();
      }

      async doRefresh(note) {
          this.$widget.html("<p>Hello</p>");
          this.$widget.show();
      }

      async entitiesReloadedEvent({loadResults}) {
          if (loadResults.isNoteReloaded(this.noteId)) {
              this.refresh();
          }
      }
  }


blobId: GXbmhhlr362RML9wuB43
dateModified: 2025-03-09 12:18:55.626+0200
utcDateModified: 2025-03-09 10:18:56.177Z
content:
  <div class="content">
         

        <div class="ck-content">
          <p>The goal of this checklist is to ensure a good implementation or re-test
            of a note type.</p>
          <h2>Implementation checklist</h2>
          <p>The note type widget must be created according to&nbsp;<a class="reference-link"
            href="#root/UNft06cRlBmE">First steps</a>:</p>
          <ul class="todo-list">
            <li>
              <label class="todo-list__label">
                <input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Register the note type in the server</span>
              </label>
            </li>
            <li>
              <label class="todo-list__label">
                <input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Register the note type in the client context menu</span>
              </label>
            </li>
            <li>
              <label class="todo-list__label">
                <input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Create a type widget</span>
              </label>
            </li>
            <li>
              <label class="todo-list__label">
                <input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Register the type widget</span>
              </label>
            </li>
            <li>
              <label class="todo-list__label">
                <input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Add the default icon mapping</span>
              </label>
            </li>
            <li>
              <label class="todo-list__label">
                <input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Add to note type selector</span>
              </label>
            </li>
            <li>
              <label class="todo-list__label">
                <input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Add the note to server allowed note types</span>
              </label>
            </li>
            <li>
              <label class="todo-list__label">
                <input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Update demo document to include this new note type</span>
              </label>
            </li>
            <li>
              <label class="todo-list__label">
                <input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Increase server sync version (see&nbsp;<a class="reference-link" href="#root/XPSyrTI07rbd/DrIXfwu9CVJP">Mindmap gets turned as file</a>).</span>
              </label>
            </li>
          </ul>
          <h2>Validation checklist</h2>
          <h3>Ensure that the note renders properly</h3>
          <ul class="todo-list">
            <li>
              <label class="todo-list__label">
                <input type="checkbox" disabled="disabled"><span class="todo-list__label__description">When refreshing to a note that is already displayed</span>
              </label>
            </li>
            <li>
              <label class="todo-list__label">
                <input type="checkbox" disabled="disabled"><span class="todo-list__label__description">When going to another note and then going back</span>
              </label>
            </li>
            <li>
              <label class="todo-list__label">
                <input type="checkbox" disabled="disabled"><span class="todo-list__label__description">When creating a new note of the given type</span>
              </label>
            </li>
            <li>
              <label class="todo-list__label">
                <input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Have two tabs of the same note type and switch between them</span>
              </label>
            </li>
          </ul>
          <h3>Ensure data persistence</h3>
          <ul class="todo-list">
            <li>
              <label class="todo-list__label">
                <input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Save data when modifying changes via spaced update</span>
              </label>
            </li>
          </ul>
          <h3>Ensure data retrieval</h3>
          <ul class="todo-list">
            <li>
              <label class="todo-list__label">
                <input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Go on a note of this type and refresh the page</span>
              </label>
            </li>
            <li>
              <label class="todo-list__label">
                <input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Create a new note of this type while on another note of this type and ensure that the content is set properly.</span>
              </label>
            </li>
          </ul>
          <h3>Set up a note preview</h3>
          <p>For an implementation reference, see&nbsp;<a class="reference-link" href="#root/NG0MFO2XXtUr">SVG rendering</a>.</p>
          <ul
          class="todo-list">
            <li>
              <label class="todo-list__label">
                <input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Note preview rendering (go to parent and see note list).</span>
              </label>
            </li>
            <li>
              <label class="todo-list__label">
                <input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Include note</span>
              </label>
            </li>
            <li>
              <label class="todo-list__label">
                <input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Share</span>
              </label>
            </li>
            <li>
              <label class="todo-list__label">
                <input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Note revisions</span>
              </label>
            </li>
            </ul>
            <h3>Import/export</h3>
            <ul class="todo-list">
              <li>
                <label class="todo-list__label">
                  <input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Export &amp; Import, making sure no data is lost in the process.</span>
                </label>
              </li>
              <li>
                <label class="todo-list__label">
                  <input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Remove the data folder entirely to test that the demo document is well imported on first setup.</span>
                </label>
                <ul class="todo-list">
                  <li>
                    <label class="todo-list__label">
                      <input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Ensure that the preview also works (check the preview in the root note).</span>
                    </label>
                  </li>
                </ul>
              </li>
            </ul>
        </div>
      </div>


blobId: OkntK7CsRMjLcIuQFH22
dateModified: 2025-03-09 12:18:55.626+0200
utcDateModified: 2025-03-09 10:18:56.180Z
content:
  <div class="content">
         

        <div class="ck-content">
          <p>The data persistence is achieved via the spaced update mechanism which
            is already present and needs to be integrated within the newly created
            type widgets.</p>
          <p>First, the class must implement <code>getData</code>, in order to retrieve
            the data from the custom widget in a serialized form. As an example from
            the mind map implementation:</p><pre><code class="language-text-plain">async getData() {
      const mind = this.mind;
      if (!mind) {
          return;
      }

      return {
          content: mind.getDataString()
      };
  }</code></pre>
          <p>Here the content is a string containing a JSON. It is also possible to
            provide attachments here as well, such as&nbsp;<a class="reference-link"
            href="#root/NG0MFO2XXtUr">SVG rendering</a>&nbsp;to provide a preview
            of the content.</p>
          <p>Then to trigger an update, register a listener within the custom widget
            that calls the spaced update, for example:</p><pre><code class="language-text-plain">mind.bus.addListener("operation", (operation) =&gt; {
      this.spacedUpdate.scheduleUpdate();
  });</code></pre>
        </div>
      </div>


blobId: NiKiC7MmDnPUCi4ZQIlw
dateModified: 2025-03-09 12:18:55.626+0200
utcDateModified: 2025-03-09 10:18:56.184Z
content:
  <div class="content">
         

        <div class="ck-content">
          <p>Data loading can be done in <code>doRefresh()</code> since it gets a reference
            to the note:</p><pre><code class="language-text-plain">const blob = await note.getBlob();        
  const content = blob.getJsonContent();</code></pre>
          <p>Note that <code>doRefresh</code> can sometimes be called by&nbsp;<a class="reference-link"
            href="#root/jW7s0gPVnalP">Saving data via spaced update</a>&nbsp;when
            the user makes a changes, this has to be accounted for.</p>
        </div>
      </div>


blobId: DFMBsCAYSbTY2WUuU1lW
dateModified: 2025-03-09 12:18:55.626+0200
utcDateModified: 2025-03-09 10:18:56.192Z
content:
  <div class="content">
         

        <div class="ck-content">
          <p>For diagrams and similar note types, it makes sense to cache an SVG rendering
            of the content so that it can be used for:</p>
          <ul>
            <li>Content preview in note lists (when viewing the list of notes from the
              parent note).</li>
            <li>Note inclusion</li>
            <li>Share</li>
          </ul>
          <h2>Step 1. Save the SVG content as an attachment</h2>
          <p>The first step is to obtain the SVG from the custom widget used. For example,
            for Mind Elixir there is an <code>exportSvg</code> method.</p>
          <p>If the returned value is a <code>Blob</code>, then the underlying text
            can be obtained via <code>await blob.text()</code>.</p>
          <p>To save the SVG as an attachment alongside the content, simply modify <code>getData()</code>:</p><pre><code class="language-text-plain">async getData() {
      const mind = this.mind;
      if (!mind) {
          return;
      }

      const svgContent = await this.mind.exportSvg().text();   
      return {
          content: mind.getDataString(),
          attachments: [
              {
                  role: "image",
                  title: "mindmap-export.svg",
                  mime: "image/svg+xml",
                  content: svgContent,
                  position: 0
              }
          ]
      };
  }</code></pre>
          <p>You can test this step by making a change to the note and then using the
            “Note attachments” option from the note menu.</p>
          <h2>Step 2. Adapting the server to serve SVG attachment</h2>
          <p>The <code>src/routes/api/image.ts</code> route is in charge for serving
            the image previews of image notes, but also of custom note types such as
            canvases.</p>
          <p>Alter the <code>returnImageInt</code> method as follows:</p>
          <ol>
            <li>Add the image type to the guard condition which returns 400 for unsupported
              note types.</li>
            <li>Add an <code>if</code> statement to render the attachment using the correct
              name:</li>
          </ol><pre><code class="language-text-plain">if (image.type === "mindMap") {
  	renderSvgAttachment(image, res, 'mindmap-export.svg');
  }</code></pre>
          <h2>Step 3. Serve the SVG attachment for note preview</h2>
          <p>The client also needs tweaking to allow it to render SVG attachments by
            calling the previously modified server route.</p>
          <p>The <code>src/public/app/services/content_renderer.js</code> file is in
            charge of handling the previews. To render using the image route, modify <code>getRenderedContent</code> to
            add the new note type to the <code>if</code> which calls <code>renderImage</code>.</p>
          <h2>Step 4. Serve SVG for share</h2>
          <p>By default,<code> Note type cannot be displayed</code> will be displayed
            when trying to access the given note via a share.</p>
          <p>To serve the SVG, open <code>src/share/content_renderer.ts</code> and look
            for <code>getContent</code>. Then add to the <code>if</code> containing <code>renderImage</code> the
            new note type.</p>
          <p>This is not enough, as attempting to access the shared note will result
            in a broken image that fails with <code>Requested note is not a shareable image</code>.
            To solve this one, go to <code>src/share/routes.ts</code> and add a <code>renderImageAttachment</code> statement
            to <code>router.get('/share/api/images/[…])</code>.</p>
          <h2>Step 5. Serve SVG for revisions</h2>
          <p>In the revisions list, to display the SVG, go to <code>src/public/app/widgets/dialogs/revisions.js</code> and
            look for the <code>renderContent</code> method. Simply add the note type
            to one of the already existing <code>if</code>s, such as the one for <code>canvas</code> and <code>mindMap</code> or <code>mermaid</code> (if
            the text content of the diagram should also be displayed).</p>
        </div>
      </div>


blobId: ANSSvu28nhBCY4cHBUJG
dateModified: 2025-03-09 12:18:55.626+0200
utcDateModified: 2025-03-09 10:18:56.196Z
content:
  <div class="content">
         

        <div class="ck-content">
          <p>This function is handled by <code>src/public/app/widgets/floating_buttons/copy_image_reference_button.js</code> and
            it supports multiple note types out of the box.</p>
          <p>To enable the display of the button, simply modify <code>isEnabled</code> to
            add support for the new note type.</p>
          <p>No other modifications should be necessary.</p>
        </div>
      </div>


blobId: GBNAlQPOLvJVQI9AYjLV
dateModified: 2025-03-09 12:18:55.626+0200
utcDateModified: 2025-03-09 10:18:56.200Z
content:
  <div class="content">
         

        <div class="ck-content">
          <p>This mechanism is handled by <code>src/public/app/widgets/floating_buttons/svg_export_button.js</code>.</p>
          <h2>Step 1. Enable the button</h2>
          <p>Modify the &nbsp;<code>isEnabled</code> method in <code>svg_export_button.js</code> to
            add support for the new note type.</p>
          <h2>Step 2. Add support for exporting the image</h2>
          <p>The SVG export needs to be handled inside the note type implementation.&nbsp;</p>
          <p>The first goal is to create a method to handle the&nbsp;<a class="reference-link"
            href="#root/NG0MFO2XXtUr">SVG rendering</a>. Make sure to deduplicate
            the code if the SVG rendering is already handled.</p><pre><code class="language-text-plain">async renderSvg() {
      return await this.mind.exportSvg().text();
  }</code></pre>
          <p>Then create an event handler to manage the SVG export:</p><pre><code class="language-text-plain">async exportSvgEvent({ntxId}) {
      if (!this.isNoteContext(ntxId) || this.note.type !== "mindMap") {
          return;
      }

      const svg = await this.renderSvg();
      utils.downloadSvg(this.note.title, svg);
  }</code></pre>
          <p>Make sure to modify the note type assertion at the beginning of the method.
            This is very important, otherwise there can be errors when navigating through
            multiple note types that support this button.</p>
        </div>
      </div>


blobId: thAPKiIvN3DNY3YJqITj
dateModified: 2025-03-09 12:18:55.626+0200
utcDateModified: 2025-03-09 10:18:56.204Z
content:
  <div class="content">
         

        <div class="ck-content">
          <p>Note printing is handled by <code>note_detail.js</code>, in the <code>printActiveNoteEvent</code> method.</p>
          <p>The application uses the <a href="https://www.npmjs.com/package/print-this"><code>print-this</code></a> library
            to isolate <code>.note-detail-printable:visible</code> and prepare it for
            printing.</p>
          <p>Some scripts like KaTeX are manually injected in the footer, and the CSS
            to be used is manually defined. The most important one is <code>print.css</code>.</p>
          <h2>Syntax highlighting</h2>
          <p>Syntax highlighting for code blocks is supported as well:</p>
          <ul>
            <li>It works by injecting a Highlight.js stylesheet into the print.</li>
            <li>The theme used is hard-coded (the <i>Visual Studio Light theme</i>, at
              the time of writing) in order not to have a dark background in print.</li>
            <li>The Highlight.js library is not needed since the <code>.note-detail-printable</code> which
              is rendered already has the <code>.hljs</code> classes added to it in order
              to achieve the syntax highlighting.</li>
            <li>The user's choice of whether to enable syntax highlighting is also respected.</li>
          </ul>
        </div>
      </div>


blobId: FSn1LoZDgHjeXWcXAp3F
dateModified: 2025-03-09 12:18:55.626+0200
utcDateModified: 2025-03-09 10:18:56.208Z
content:
  <div class="content">
         

        <div class="ck-content">
          <p>Launchers are items that are displayed in the launcher bar (left side
            of the screen). They are of two different types:</p>
          <ul>
            <li>Visible launchers: are displayed by default to the user, can be moved
              to the available launchers section to hide them.</li>
            <li>Available launchers: can be manually added by the user from settings into
              the list of visible launchers.</li>
          </ul>
          <h2>Adding a new launcher</h2>
          <p>Regardless of the type, new launchers are added at server level, inside <code>hidden_subtree.ts</code> file.</p>
          <ul>
            <li>To add a new available launcher, look for <code>_lbAvailableLaunchers</code> and
              add a new item to its <code>children</code>.</li>
            <li>Similarly, to add a visible launcher, look for <code>_lbVisibleLaunchers</code>.
              <ul>
                <li>If you add a visible launcher, it will be available for both new and old
                  users, since the application will identify that there is a new launcher
                  to be added regardless of the user preference.</li>
              </ul>
            </li>
          </ul>
        </div>
      </div>


blobId: BZa82CZybjU14C7Z7PSN
dateModified: 2025-03-09 12:18:55.626+0200
utcDateModified: 2025-03-09 10:18:56.216Z
content:
  <div class="content">
         

        <div class="ck-content">
          <h2>Defining the MIME type</h2>
          <p>The first step to supporting a new language for either code blocks or
            code notes is to define the MIME type. Go to <code>mime_types.ts</code> and
            add a corresponding entry:</p><pre><code class="language-text-x-trilium-auto">{ title: "Batch file (DOS)", mime: "application/x-bat" }</code></pre>
          <h2>Syntax highlighting for Highlight.js</h2>
          <h3>Built-in languages</h3>
          <p>Highlight.js supports a lot of languages out of the box, for some of them
            we just need to enable them by specifying one of the language aliases in
            the <code>highlightJs</code> field in the <code>mime_types</code> definition:</p><pre><code class="language-text-x-trilium-auto">{ title: "Batch file (DOS)", mime: "application/x-bat", highlightJs: "dos" }</code></pre>
          <p>For the full list of supported languages, see <a href="https://highlightjs.readthedocs.io/en/latest/supported-languages.html">Supported Languages — highlight.js 11.9.0 documentation</a>.
            Look for the “Package” column to see if another library needs to be installed
            to support it.</p>
          <p>Note that we are using the CDN build which may or may not have all the
            languages listed as predefined in the “Supported languages” list. To view
            the real list of supported files, see the <code>node_modules/@highlightjs/cdn-assets/languages</code> directory.</p>
          <h3>Custom language</h3>
          <p>When the source code for a language is available, one way is to simply
            copy it to <code>libraries/highlightjs/{id}.js</code> where <code>id</code> matches
            the name for <code>highlightJs</code>.</p>
          <p>Make sure in the script that the language is registered:</p><pre><code class="language-text-x-trilium-auto">hljs.registerLanguage('terraform', hljsDefineTerraform);</code></pre>
          <p>Then in <code>mime_types.ts</code> make sure to set <code>highlightJsSource</code> to <code>libraries</code> to
            load it.</p><pre><code class="language-text-x-trilium-auto">{ title: "Terraform (HCL)", mime: "text/x-hcl", highlightJs: "terraform", highlightJsSource: "libraries", codeMirrorSource: "libraries/codemirror/hcl.js" },</code></pre>
          <h2>Syntax highlighting for CodeMirror</h2>
          <h3>Custom language</h3>
          <p>Generally new languages are not added in the base installation and need
            to be separately registered. For CodeMirror 5 it seems that (at least for
            simple languages), the modes are distributed as <i>simple modes</i> and can
            generally be copy-pasted in <code>libraries/codemirror</code>. An example
            would be:</p><pre><code class="language-text-x-trilium-auto">(() =&gt; {

      CodeMirror.defineSimpleMode("batch", {

          start: [],

          echo: []

      });



      CodeMirror.defineMIME("application/x-bat", "batch");

      CodeMirror.modeInfo.push({

          ext: [ "bat", "cmd" ],

          mime: "application/x-bat",

          mode: "batch",

          name: "Batch file"

      });

  })();

  </code></pre>
          <p>Note that changing <code>modeInfo</code> is crucial, otherwise syntax highlighting
            will not work. The <code>mime</code> field is mandatory, even if <code>mimes</code> is
            used instead.</p>
          <p>Afterwards, register it in <code>mime_types.ts</code>, specifying <code>codeMirrorSource</code> to
            point to the newly created file:</p><pre><code class="language-text-x-trilium-auto">{ title: "Batch file (DOS)", mime: "application/x-bat", highlightJs: "dos", codeMirrorSource: "libraries/codemirror/batch.js" }</code></pre>
        </div>
      </div>


blobId: XUSaIoR55elbzpyTWcMJ
dateModified: 2025-03-09 12:18:55.626+0200
utcDateModified: 2025-03-09 10:18:56.225Z
content:
  <div class="content">
         

        <div class="ck-content">
          <p>To create a basic widget, simply create a code note with type “JS frontend”.
            Add the <code>#widget</code> label in order for it to be loaded at startup.</p><pre><code class="language-text-plain">const template = `&lt;div id="my-widget"&gt;&lt;button&gt;Click Me!&lt;/button&gt;&lt;/div&gt;`;

  class MyWidget extends api.BasicWidget {
      get position() { return 1; }
      get parentWidget() { return "left-pane" }
      
      doRender() {
          this.$widget = $(template);
          return this.$widget;
      }
  }

  module.exports = new MyWidget();</code></pre>
          <p><code>parentWidget()</code> can be given the following values:</p>
          <ul>
            <li><code>left-pane</code> - This renders the widget on the left side of the
              screen where the note tree lives.</li>
            <li><code>center-pane</code> - This renders the widget in the center of the
              layout in the same location that notes and splits appear.</li>
            <li><code>note-detail-pane</code> - This renders the widget <i>with</i> the note
              in the center pane. This means it can appear multiple times with splits.</li>
            <li><code>right-pane</code> - This renders the widget to the right of any opened
              notes.</li>
          </ul>
          <hr>
          <p>Reference:</p>
          <ul>
            <li><a href="https://trilium.rocks/X7pxYpiu0lgU">https://trilium.rocks/X7pxYpiu0lgU</a>&nbsp;</li>
            <li><a href="https://github.com/zadam/trilium/wiki/Widget-Basics">https://github.com/zadam/trilium/wiki/Widget-Basics</a>&nbsp;</li>
            <li><a href="https://github.com/zadam/trilium/wiki/Frontend-Basics">https://github.com/zadam/trilium/wiki/Frontend-Basics</a>&nbsp;</li>
          </ul>
        </div>
      </div>


blobId: 8U5EGU2Z3WteM3YVtUXw
dateModified: 2025-03-09 12:18:55.626+0200
utcDateModified: 2025-03-09 10:18:56.231Z
content:
  <div class="content">
         

        <div class="ck-content">
          <ul>
            <li><code>doRender</code> must not be overridden, instead <code>doRenderBody()</code> has
              to be overridden.</li>
            <li><code>parentWidget()</code> must be set to <code>“rightPane”</code>.</li>
            <li><code>widgetTitle()</code> getter can optionally be overriden, otherwise
              the widget will be displayed as “Untitled widget”.</li>
          </ul><pre><code class="language-text-plain">const template = `&lt;div&gt;Hi&lt;/div&gt;`;

  class ToDoListWidget extends api.RightPanelWidget {
      
      get widgetTitle() {
          return "Title goes here";
      }
          
      get parentWidget() { return "right-pane" }
      
      doRenderBody() {
          this.$body.empty().append($(template));
      }   
      
      async refreshWithNote(note) {
          this.toggleInt(false);                
          this.triggerCommand("reEvaluateRightPaneVisibility");
          this.toggleInt(true);
          this.triggerCommand("reEvaluateRightPaneVisibility");
      }
  }

  module.exports = new ToDoListWidget();</code></pre>
          <p>The implementation is in <code>src/public/app/widgets/right_panel_widget.js</code>.</p>
        </div>
      </div>


blobId: yZRL3IDcl60arVgNUfTN
dateModified: 2025-03-09 12:18:55.626+0200
utcDateModified: 2025-03-09 10:18:56.235Z
content:
  <div class="content">
         

        <div class="ck-content">
          <p>In <code>doRender()</code>:</p><pre><code class="language-text-plain">this.cssBlock(`#my-widget {
  	position: absolute;
      bottom: 40px;
      left: 60px;
      z-index: 1;
  }`)</code></pre>
          <hr>
          <p>Reference: <a href="https://trilium.rocks/X7pxYpiu0lgU">https://trilium.rocks/X7pxYpiu0lgU</a>&nbsp;</p>
        </div>
      </div>


blobId: hCOh86Fzaa55JeBojFo0
dateModified: 2025-03-09 12:18:55.626+0200
utcDateModified: 2025-03-09 10:18:56.240Z
content:
  <div class="content">
         

        <div class="ck-content">
          <p>Trilium Notes allowed the use of Common.js module imports inside backend
            scripts, such as:</p><pre><code class="language-text-plain">const isBetween = require('dayjs/plugin/isBetween')
  api.dayjs.extend(isBetween)</code></pre>
          <p>For TriliumNext, the backend has been switched to use ESM which has a
            slightly more complicated syntax. Instead of <code>require</code> we now
            have <code>import</code> but which is asynchronous so it will require an <code>await</code>:</p><pre><code class="language-text-plain">const isBetween = (await import("dayjs/plugin/isBetween")).default;
  api.dayjs.extend(isBetween);</code></pre>
          <p>Note that <code>.default</code> is also usually needed to obtain the same
            behaviour as a CJS import. When in doubt, use <code>console.log</code> to
            see the output of the value returned by <code>await import</code>.</p>
        </div>
      </div>


blobId: nLUQC1YSk7fYBgnDErya
dateModified: 2025-03-09 12:18:55.626+0200
utcDateModified: 2025-03-09 10:18:56.245Z
content:
  <div class="content">
         

        <div class="ck-content">
          <h2>Hard-coded links</h2>
          <p>Hard-coded links are present throughout the application, either in dialogs
            or in the source code as comments.</p>
          <p>You can identify these links by searching for:</p><pre><code class="language-text-plain">https://triliumnext.github.io/Docs/Wiki/</code></pre>
          <h2>Help buttons</h2>
          <p>There is a pattern of “?” buttons throughout the application which make
            use of the <code>data-help-page</code> attribute. Whenever these buttons
            are pressed, the user is redirected to the corresponding wiki page by prepending
            the wiki root URL to the <code>data-help-page</code> attribute.</p>
          <p>Since the current wiki has a different structure than the original, for
            example to link to <a href="https://github.com/TriliumNext/Docs/blob/main/Wiki/tree-concepts.md">https://github.com/TriliumNext/Docs/blob/main/Wiki/tree-concepts.md</a> the <code>data-help-page</code> attribute
            must be set to <code>tree-concepts.md</code>.</p>
          <p>For links to headings, simply add the heading after the <code>.md</code>: <code>tree-concepts.md#prefix</code>
          </p>
          <p>You can identify those by looking for:</p>
          <ul>
            <li><code>.attr("data-help-page"</code>
            </li>
            <li><code>data-help-page="</code>
            </li>
          </ul>
        </div>
      </div>


blobId: KCvaTWCXDPGLk1vRdd6K
dateModified: 2025-03-09 12:18:55.626+0200
utcDateModified: 2025-03-09 10:18:56.249Z
content:
  <div class="content">
         

        <div class="ck-content">
          <p>The user-facing documentation is available on a dedicated repository inside
            the organization: <a href="https://github.com/TriliumNext/Docs">https://github.com/TriliumNext/Docs</a>&nbsp;</p>
          <p>It is currently organized as a flat tree of MarkDown notes.</p>
          <p>The documentation started as an import of the existing upstream documentation
            in <a href="https://github.com/zadam/trilium/wiki">https://github.com/zadam/trilium/wiki</a>.</p>
          <p>The public documentation is available at <a href="https://triliumnext.github.io/Docs/Wiki">https://triliumnext.github.io/Docs/Wiki</a>.</p>
          <p>The repository is here: <a href="https://github.com/TriliumNext/Docs">https://github.com/TriliumNext/Docs</a>&nbsp;</p>
          <p>The documentation is stored as Markdown files and is meant to be imported
            into Trilium Notes and then exported back in, as per the README. However,
            it's also possible to modify the Markdown files manually and push the changes.</p>
          <p>The documentation is deployed automatically to GitHub Pages on every push
            on the <code>main</code> branch.</p>
        </div>
      </div>


blobId: YY9YC47A6OCGuP0DLyPN
dateModified: 2025-03-09 12:18:55.626+0200
utcDateModified: 2025-03-09 10:18:56.258Z
content:
  <div class="content">
         

        <div class="ck-content">
          <p>There is a setup test that stores the authentication token so that it
            can be reused throughout all the tests.</p>
          <p>If tests fail due to being stuck on login, then it must be run.</p>
          <p>To run it manually press “all” near the “Status:” text on top-left of
            the window</p>
          <figure class="image">
            <img style="aspect-ratio:233/112;" src="api/attachments/kvAn8zjo0NIE/image/1_Setting up authentication_.png"
            width="233" height="112">
          </figure>
          <p>Then check “setup” and look for <code>auth.setup.ts</code> and press its
            corresponding Run button:</p>
          <figure class="image">
            <img style="aspect-ratio:235/223;" src="api/attachments/bXqU7XjyhxGy/image/Setting up authentication_.png"
            width="235" height="223">
          </figure>
        </div>
      </div>


blobId: KuGBkpHPD8rhcvDravUy
dateModified: 2025-03-09 12:18:55.626+0200
utcDateModified: 2025-03-09 10:18:56.290Z
content:
  <div class="content">
         

        <div class="ck-content">
          <p>The integration tests do not use the same database as <code>npm run start-server</code>.
            Instead, the database is located <code>integration-tests/db/document.db</code>.</p>
          <h2>In-memory database</h2>
          <p>Even though we are running our own database, there is still the problem
            of one test affecting the content for the others or accidentally removing
            important test notes.</p>
          <p>To avoid this, the integration test server (run via <code>integration-mem-db</code>)
            loads the database from <code>integration-test</code> into memory and operates
            from there. That means that any changes done on the integration test server
            (port 8082) will not be persisted between restarts of the server.</p>
          <p>Another benefit of having the database in memory for tests is that they
            can run in parallel without the risk on interfering with each other.</p>
          <h2>How to make changes to the database</h2>
          <p>As mentioned previously, the database itself can be edited manually in
            order to add content that is relevant to the tests.</p>
          <p>In order to do so, run a separate integration test server with:</p><pre><code class="language-text-plain">npm run integration-edit-db</code></pre>
          <p>This will open up a server on port 8081 which can be used to alter the
            integration test DB. After finishing the desired changes, it's ideal to
            close the server to prevent any interferences with further running of tests.</p>
          <h2>The database is tracked by Git</h2>
          <p>This is intentional, meaning that any change to the database will mark
            the file as changed in Git as well. Some tests require a specific note
            and it would be too wasteful to have to recreate it via Playwright each
            time. Instead the content is added manually and then the tests operate
            directly on the said notes.</p>
          <p>In order to make the database easier to track, SQLite WAL was disabled
            but only for the integration database. This means that only the <code>.db</code> file
            is present and needs to be committed.</p>
          <h2>Cleaning up the database</h2>
          <p>It's recommended to clean up any deleted notes to avoid unnecessary changes
            being committed. To do so go to Recent Changes in the launcher and select
            “Erase deleted notes now”.</p>
          <p>It's also a good idea to go to Options → Advanced → Vacuum database to
            clean up it.</p>
        </div>
      </div>


blobId: nquew7XiB9AaMXaKDbQR
dateModified: 2025-03-09 12:18:55.626+0200
utcDateModified: 2025-03-09 10:18:56.294Z
content:
  <div class="content">
         

        <div class="ck-content">
          <h2>First-time run</h2>
          <p>Before starting Playwright, it has to be installed locally via:</p><pre><code class="language-text-plain">npx playwright install</code></pre>
          <h2>Starting the integration test server</h2>
          <p>There are two types of integration test servers:</p>
          <ul>
            <li><code>npm run integration-mem-db</code> will run a server with dev mode
              disabled.
              <ul>
                <li>This is usually what the end user will see when accessing a server instance.</li>
                <li>It will not test the Electron/desktop side of the application.</li>
                <li>Changes to the public scripts will not take effect until running <code>npm run webpack</code>.</li>
              </ul>
            </li>
            <li><code>npm run integration-mem-db-dev</code> will run a server with dev
              mode enabled.
              <ul>
                <li>This is usually what a dev sees when running <code>npm run start-server</code>.</li>
                <li>The difference with the production one is that the assets are loaded directly
                  from files and as such it does not require <code>npm run webpack</code> to
                  see changes.</li>
              </ul>
            </li>
          </ul>
          <p>Either options will open up a server on <a href="http://localhost:8082">localhost:8082</a> that
            can be accessed either manually via the browser or via Playwright.</p>
          <p>When asked for a password, the password is <code>demo1234</code>.</p>
          <h2>Starting the interactive test runner</h2>
          <p>After starting the integration test server, to run the Playwright UI,
            run in the terminal:</p><pre><code class="language-text-plain">npx playwright test --ui</code></pre>
          <p>It is also possible to run the interactive code generator instead:</p><pre><code class="language-text-plain">npx playwright codegen</code></pre>
        </div>
      </div>


blobId: Fg5YkM4WmydZ5DjKK5BF
dateModified: 2025-03-09 12:18:55.626+0200
utcDateModified: 2025-03-09 10:18:56.299Z
content:
  <div class="content">
         

        <div class="ck-content">
          <h2>Clone the repository</h2>
          <p>To set up the repository:</p><pre><code class="language-text-plain">git clone https://github.com/TriliumNext/trilium-ckeditor5.git</code></pre>
          <h2>Install dependencies</h2>
          <p>First, install root dependencies:</p><pre><code class="language-text-x-trilium-auto">cd trilium-ckeditor5
  yarn install</code></pre>
          <p>Secondly, install the Trilium build dependencies:</p><pre><code class="language-text-x-trilium-auto">cd packages/ckeditor5-build-trilium
  yarn install</code></pre>
          <p>To trigger the build, see&nbsp;<a class="reference-link" href="#root/4s2JWEEzwx6h">Building the editor</a>.</p>
        </div>
      </div>


blobId: FyCrTYThOlwQbXDAqXyg
dateModified: 2025-03-09 12:18:55.626+0200
utcDateModified: 2025-03-09 10:18:56.301Z
content:
  <div class="content">
         

        <div class="ck-content">
          <p>First, make sure&nbsp;<a class="reference-link" href="#root/oSJs8Ei9nAEp">Environment setup</a>&nbsp;is
            set up.</p>
          <h2>Trigger the build</h2><pre><code class="language-text-plain">cd packages/ckeditor5-build-trilium
  yarn build</code></pre>
          <p>This will trigger a change in the <code>build</code> directory.</p>
          <h2>Copy the build artifact to the main repo</h2>
          <p>Go to <code>packages/ckeditor5-build-balloon-trilium/build</code> and copy <code>ckeditor.js</code> and <code>ckeditor.js.map</code> to <code>libraries/ckeditor</code> in
            the <code>Notes</code> repository.</p>
          <p>An example shell command to copy it:</p><pre><code class="language-text-plain">cp build/ckeditor.* ~/Projects/TriliumNext/Notes/libraries/ckeditor/</code></pre>
          <h2>&nbsp;</h2>
        </div>
      </div>


blobId: wIukyGtYhWKXXCRlmpKm
dateModified: 2025-03-09 12:18:55.626+0200
utcDateModified: 2025-03-09 10:18:56.305Z
content:
  <div class="content">
         

        <div class="ck-content">
          <ul>
            <li>Embeds <a href="https://github.com/isaul32/ckeditor5-math"><code><s>isaul32/ckeditor5-math</s></code></a>&nbsp;
              <a
              class="reference-link" href="#root/G3SCg0165PKB">ckeditor5-math</a>, which is a third-party plugin for adding math support.
                CKEditor itself also has a <a href="https://ckeditor.com/docs/ckeditor5/latest/features/math-equations.html">math plugin</a> with
                MathType and ChemType but it's premium-only.</li>
            <li>Zadam left a TODO in <code>findandreplaceUI</code>: <code>// FIXME: keyboard shortcut doesn't work: </code>
              <a
              href="https://github.com/ckeditor/ckeditor5/issues/10645"><code>https://github.com/ckeditor/ckeditor5/issues/10645</code>
                </a>
            </li>
            <li><code>packages\ckeditor5-build-balloon-block\src\mention_customization.js</code> introduces
              note insertion via <code>@</code> character.</li>
          </ul>
          <figure class="table" style="width:100%;">
            <table class="ck-table-resized">
              <colgroup>
                <col style="width:19.51%;">
                  <col style="width:12.2%;">
                    <col style="width:22.25%;">
                      <col style="width:46.04%;">
              </colgroup>
              <thead>
                <tr>
                  <th>Affected file</th>
                  <th>Affected method</th>
                  <th>Changed in</th>
                  <th>Reason for change</th>
                </tr>
              </thead>
              <tbody>
                <tr>
                  <td rowspan="2"><code>packages/ckeditor5-mention/src/mentionui.ts</code>
                  </td>
                  <td><code>createRegExp()</code>
                  </td>
                  <td><code>6db05043be24bacf9bd51ea46408232b01a1b232</code> (added back)</td>
                  <td>Allows triggering the autocomplete for labels and attributes in the attribute
                    editor.</td>
                </tr>
                <tr>
                  <td><code>init()</code>
                  </td>
                  <td><code>55a63a1934efb9a520fcc2d69f3ce55ac22aca39</code>
                  </td>
                  <td>Allows dismissing @-mention permanently after pressing ESC, otherwise
                    it would automatically show up as soon as a space was entered.</td>
                </tr>
              </tbody>
            </table>
          </figure>
          <h2>Checking the old repo</h2>
          <p>Use the following command to identify commits from Zadam:</p><pre><code class="language-text-x-trilium-auto">git log --oneline --author="adam" --all</code></pre>
          <p>It's best to run the command from zadam's fork of <code>trilium-ckeditor5</code> instead
            of the TriliumNext once since it might not contain all the unmerged branches.</p>
          <p>To show a filtered diff of a commit:</p><pre><code class="language-text-x-trilium-auto">git show d42e772783 -- ':!*yarn.lock' ':!*packages/ckeditor5-build-balloon-block/build/*' ':!*package.json'</code></pre>
        </div>
      </div>


blobId: 78Xfyq6BLYAKUS4xnnNJ
dateModified: 2025-03-09 12:18:55.626+0200
utcDateModified: 2025-03-09 10:18:56.309Z
content:
  <div class="content">
         

        <div class="ck-content">
          <h2>Before updating</h2>
          <p>Make sure that all the plugins are compatible with this version:&nbsp;
            <a
            class="reference-link" href="#root/5i50dAfKSoL9">Versions and external plugins</a>. If not, they will need to be updated
              to the same version as the one you are updating, by altering their <code>package.json</code>.</p>
          <p>If the plugin is external to the Trilium organisation, it needs to be
            forked first.</p>
          <h2>Environment setup</h2>
          <p>The first step is to add the CKEditor source as a remote. This only needs
            to be done once.</p><pre><code class="language-text-x-trilium-auto">git remote add upstream ssh://git@github.com/ckeditor/ckeditor5.git
  git fetch upstream</code></pre>
          <h2>Update steps</h2>
          <p>Due to how the repository is structured, updates to the CKEditor are a
            bit difficult.</p>
          <ol>
            <li><code>git fetch upstream</code>
            </li>
            <li>Pick a version and merge with it: <code>git merge -X theirs v99.2.0</code>
            </li>
            <li>When there are complicated conflicts, sometimes it's easier to take everything
              from the target version instead, for a given path: <code>git checkout v99.2.0 -- "packages/ckeditor5-list/**"</code>.</li>
            <li>Go in <code>packages/ckeditor5-build-trilium/package.json</code> and run <code>node sync-version.js</code> to
              update the <code>package.json</code> with the new versions. Review and commit
              the change.</li>
            <li>Follow again the dependency setup in&nbsp;<a class="reference-link" href="#root/oSJs8Ei9nAEp">Environment setup</a>,
              as they have changed.</li>
            <li><a href="#root/4s2JWEEzwx6h">Run the build</a> and check that
              it works.</li>
          </ol>
          <h2>Final steps</h2>
          <ol>
            <li>Start the TriliumNext server</li>
            <li>If updated to a newer version of CKEditor, check type <code>CKEDITOR_VERSION</code> in
              the browser/Electron console to ensure that the correct version is used.</li>
            <li>Do a basic sanity check as well.</li>
            <li>Commit and push the change on both sides (in the <code>trilium-ckeditor5</code> repo
              and in the <code>Notes</code> repo).</li>
          </ol>
          <h2>Troubleshooting client side errors</h2>
          <p>These errors might show up when testing the Trilium app:</p><pre><code class="language-text-x-trilium-auto">ReferenceError: CKEditor is not defined</code></pre>
          <p>Usually this is a side effect of another error, check the logs carefully
            to see if there is any other related error (perhaps a <code>CKEditorError</code>).</p>
          <hr><pre><code class="language-text-x-trilium-auto">Uncaught error: Message: CKEditorError: ckeditor-duplicated-modules</code></pre>
          <p>Most likely cause is one of the external plugins is incompatible with
            this version.</p>
          <p>For example, to disable the Math plugin, go to <code>packages/ckeditor5-build-trilium/src/config.ts</code> and
            modify:</p><pre><code class="language-text-x-diff">-import Math from '@triliumnext/ckeditor5-math/src/math';
  -import AutoformatMath from '@triliumnext/ckeditor5-math/src/autoformatmath';

  export const COMMON_PLUGINS = [
  -	Math,
  -	AutoformatMath,
  ]</code></pre>
          <p>In this case, make sure to align the version of all the external plugins
            with the one you are updating to, usually by forking the external plugin
            and updating its versions.</p>
        </div>
      </div>


blobId: lPD0Ayy200i6kSdQhCjt
dateModified: 2025-03-09 12:18:55.626+0200
utcDateModified: 2025-03-09 10:18:56.311Z
content:
  <div class="content">
         

        <div class="ck-content">
          <h2>External plugins</h2>
          <figure class="table" style="width:100%;">
            <table class="ck-table-resized">
              <colgroup>
                <col style="width:24.34%;">
                  <col style="width:7.05%;">
                    <col style="width:68.61%;">
              </colgroup>
              <tbody>
                <tr>
                  <td>trilium-ckeditor5</td>
                  <td>43.2.0</td>
                  <td>&nbsp;</td>
                </tr>
                <tr>
                  <td><code>ckeditor5-math</code>
                  </td>
                  <td>&nbsp;</td>
                  <td>See&nbsp;<a class="reference-link" href="#root/G3SCg0165PKB">ckeditor5-math</a>.</td>
                </tr>
                <tr>
                  <td>&nbsp;</td>
                  <td>&nbsp;</td>
                  <td>&nbsp;</td>
                </tr>
              </tbody>
            </table>
          </figure>
        </div>
      </div>


blobId: 3A8XoOXA2u11UgPjDvWo
dateModified: 2025-03-09 12:18:55.626+0200
utcDateModified: 2025-03-09 10:18:56.314Z
content:
  <div class="content">
         

        <div class="ck-content">
          <figure class="image image-style-align-right">
            <img style="aspect-ratio:348/224;" src="api/attachments/QrL3Av91aXjT/image/ckeditor5-math_image.png" width="348"
            height="224">
            <figcaption><code>ckeditor5-math</code> in action.</figcaption>
          </figure>
          <p>A fork of <a href="https://github.com/isaul32/ckeditor5-math">isaul32/ckeditor5-math</a>,
            which is the CKEditor5 plugin which adds the math functionality. The fork
            was created to handle&nbsp;<a class="reference-link" href="#root/OeKBfN6JbMIq/MF99QFRe1gVy/orRZgNnWETTw/tXFiNo5IYd31/jMHQCKORhZge">#297: Insert Math appears to be broken</a>.</p>
          <h2>Development environment</h2>
          <ul>
            <li>Tested on Node.js 20.</li>
            <li>The package manager is yarn 1 (v1.22.22 is known to be working fine for
              it at the time of writing).</li>
            <li>Committing is protected by <code>husky</code> which runs <code>eslint</code> to
              ensure that the code is clean.</li>
          </ul>
          <p>Important commands:</p>
          <ul>
            <li>To check if the code has any formatting issues: <code>yarn lint</code>
            </li>
            <li>To start a live preview: <code>yarn start</code>
            </li>
            <li>To run the tests: <code>yarn test</code>
              <ul>
                <li>Note that this requires Chromium, on NixOS this can be achieved by running
                  a <code>nix-shell -p chromium</code>, and running <code>CHROME_BIN=$(which chromium) yarn test</code> inside
                  it.</li>
              </ul>
            </li>
          </ul>
          <h2>📦 Packages</h2>
          <p>The built artifact of the plugin is released by the CI and available on
            the <a href="https://github.com/TriliumNext/ckeditor5-math/pkgs/npm/ckeditor5-math">GitHub NPM registry</a>.</p>
          <p>Note that due to limitations on GitHub's registry, it is not possible
            to install this package without setting up a personal access token (even
            though the package itself is public). See&nbsp;<a class="reference-link"
            href="#root/ZlxZh8NH5frM/jUH2zJGXM67N">[missing note]</a>&nbsp;for more
            information.</p>
          <h2>⬆️ Integrating with&nbsp;<a class="reference-link" href="#root/tT5fmlAAvngr">CKEditor</a></h2>
          <ol>
            <li>Release a new version:&nbsp;<a class="reference-link" href="#root/HEh24JrjBfZf">Release management &amp; continuous integration</a>
            </li>
            <li>In <code>trilium-ckeditor5</code>, go to <code>packages/ckeditor5-build-trilium/package.json</code> in
              the CKEditor repository and change the dependency of <code>@triliumnext/ckeditor5-math</code> to
              the newly released version.</li>
            <li>Run <code>yarn install</code>.</li>
            <li>Proceed with&nbsp;<a class="reference-link" href="#root/4s2JWEEzwx6h">Building the editor</a>&nbsp;to
              integrate everything into TriliumNext and then commit the change.</li>
          </ol>
        </div>
      </div>


blobId: dU6t66p6IayaXPULm4ws
dateModified: 2025-03-09 12:18:55.626+0200
utcDateModified: 2025-03-09 10:18:56.318Z
content:
  <div class="content">
         

        <div class="ck-content">
          <p>If there was a change in the upstream repository (<a href="https://github.com/isaul32/ckeditor5-math">isaul32/ckeditor5-math</a>),
            it can be integrated as follows:</p>
          <ol>
            <li>Add the upstream as remote (<code>git remote add upstream ssh://git@github.com/isaul32/ckeditor5-math.git</code>).</li>
            <li>Fetch the changes: <code>git fetch upstream</code>
            </li>
            <li>Merge with a tag: <code>git merge v43.1.2</code>
            </li>
            <li>Solve the conflict in <code>package.json</code> by:
              <ol>
                <li>Taking the same version as the upcoming one and appending <code>-hotfix1</code>.</li>
                <li>Keeping the <code>@triliumnext/ckeditor5-math</code> name.</li>
              </ol>
            </li>
            <li>Install dependencies: <code>yarn install</code>
            </li>
            <li>Check that the build works via <code>yarn prepublishOnly</code>.</li>
            <li>Commit the changes, push them.</li>
            <li>Release a version with&nbsp;<a class="reference-link" href="#root/HEh24JrjBfZf">Release management &amp; continuous integration</a>.</li>
          </ol>
          <h2>CI job not triggered after pushing all the upstream tags</h2>
          <p>If the CI job was not triggered, you might have accidentally pushed a
            lot of tags using <code>git push --tags</code>. Manually delete the tag
            and push it again:</p><pre><code class="language-text-x-diff">git push -d origin v43.1.2-hotfix1 &amp;&amp; git push --tags</code></pre>
        </div>
      </div>


blobId: 8DuubAeNFboHNyMP6XP8
dateModified: 2025-03-09 12:18:55.626+0200
utcDateModified: 2025-03-09 10:18:56.320Z
content:
  <div class="content">
         

        <div class="ck-content">
          <p>To automate the release process, a GitHub workflow has been added which
            builds the package and releases it over to GitHub NPM registry.</p>
          <p>The workflow publishes a release whenever a tag with the correct format
            is pushed.</p>
          <p>The steps are as follows:</p>
          <ol>
            <li>Ensure that the source code is clean and ready for a release.</li>
            <li>Go to <code>package.json</code> and bump the <code>version</code> field.</li>
            <li>Commit the changes.</li>
            <li>Tag the commit with <code>v1.2.3</code>, with the correct version number.</li>
            <li>Push the changes.</li>
          </ol>
          <p>Then follow the CI and it should indicate success. Afterwards, check the
            <a
            href="https://github.com/TriliumNext/ckeditor5-math/pkgs/npm/ckeditor5-math">package</a>section to ensure that the package is in the “Recent Versions”
              section.</p>
          <p>If the changes could benefit upstream, consider opening a pull request
            with the changes there as well.</p>
        </div>
      </div>


blobId: K8abiGfxRwBlkM9EfYoN
dateModified: 2025-03-09 12:18:55.626+0200
utcDateModified: 2025-03-09 10:18:56.329Z
content:
  <div class="content">
         

        <div class="ck-content">
          <p>Full log:</p><pre><code class="language-text-x-trilium-auto">&gt; trilium@0.91.1-beta start-server
  &gt; cross-env TRILIUM_DATA_DIR=./data TRILIUM_ENV=dev TRILIUM_SYNC_SERVER_HOST=http://tsyncserver:4000 nodemon src/main.ts

  [nodemon] 3.1.9
  [nodemon] to restart at any time, enter `rs`
  [nodemon] watching path(s): src/**/* translations/**/*
  [nodemon] watching extensions: ts,js,json
  [nodemon] starting `tsx src/main.ts`

  node:internal/process/promises:391
      triggerUncaughtException(err, true /* fromPromise */);
      ^
  Error [TransformError]: The package "@esbuild/linux-x64" could not be found, and is needed by esbuild.

  If you are installing esbuild with npm, make sure that you don't specify the
  "--no-optional" or "--omit=optional" flags. The "optionalDependencies" feature
  of "package.json" is used by esbuild to install the correct binary executable
  for your current platform.
      at generateBinPath (/home/elian/Projects/TriliumNext/Notes/node_modules/esbuild/lib/main.js:1752:15)
      at esbuildCommandAndArgs (/home/elian/Projects/TriliumNext/Notes/node_modules/esbuild/lib/main.js:1822:33)
      at ensureServiceIsRunning (/home/elian/Projects/TriliumNext/Notes/node_modules/esbuild/lib/main.js:1979:25)
      at transform (/home/elian/Projects/TriliumNext/Notes/node_modules/esbuild/lib/main.js:1880:37)
      at file:///home/elian/Projects/TriliumNext/Notes/node_modules/tsx/dist/index-DlKgSVBb.mjs:16:2755
      at applyTransformers (file:///home/elian/Projects/TriliumNext/Notes/node_modules/tsx/dist/index-DlKgSVBb.mjs:16:1266)
      at transform (file:///home/elian/Projects/TriliumNext/Notes/node_modules/tsx/dist/index-DlKgSVBb.mjs:16:2702)
      at load (file:///home/elian/Projects/TriliumNext/Notes/node_modules/tsx/dist/esm/index.mjs?1734213798404:2:2245)
      at async nextLoad (node:internal/modules/esm/hooks:868:22)
      at async Hooks.load (node:internal/modules/esm/hooks:451:20)</code></pre>
          <p>The solution is to remove <code>node_modules</code> and reinstall all dependencies:</p><pre><code class="language-text-x-trilium-auto">rm -r node_modules
  npm install</code></pre>
        </div>
      </div>


blobId: i5GYZZ8ERTpJksMesV2t
dateModified: 2025-03-09 12:18:55.626+0200
utcDateModified: 2025-03-09 10:18:56.331Z
content:
  <div class="content">
         

        <div class="ck-content">
          <p>On Ubuntu:</p><pre><code class="language-text-x-trilium-auto">#!/usr/bin/env bash

  name=TriliumNextNotes-linux-x64-nightly.deb
  rm -f $name*
  wget https://github.com/TriliumNext/Notes/releases/download/nightly/$name
  sudo apt-get install ./$name
  rm $name</code></pre>
        </div>
      </div>


blobId: 962ZBRCtIiiR55W7Fpon
dateModified: 2025-03-09 12:25:52.627+0200
utcDateModified: 2025-03-09 10:25:52.627Z
content:
  <ul class="todo-list"><li><label class="todo-list__label"><input type="checkbox" checked="checked" disabled="disabled"><span class="todo-list__label__description">Integrate titles of the notes</span></label></li><li><label class="todo-list__label"><input type="checkbox" checked="checked" disabled="disabled"><span class="todo-list__label__description">Set <code>#shareAlias</code> for all the notes</span></label></li><li><label class="todo-list__label"><input type="checkbox" checked="checked" disabled="disabled"><span class="todo-list__label__description">Recreate structure of notes</span></label></li><li><label class="todo-list__label"><input type="checkbox" checked="checked" disabled="disabled"><span class="todo-list__label__description">Add icons to the notes</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Merge images into their corresponding notes</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Review and delete each note from Pikapod</span></label></li></ul><h2>Content changes</h2><ul class="todo-list"><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description"><a class="reference-link" href="#root/krkLW8AwcYf2/poXkQfguuA0U">Desktop Installation</a></span></label><ul class="todo-list"><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Mention Windows installation.</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Integrate Fedora documentation</span></label></li></ul></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description"><a class="reference-link" href="#root/krkLW8AwcYf2/Hdf1kG6Kvcl1">Link map</a>&nbsp;– it's empty</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description"><a class="reference-link" href="#root/krkLW8AwcYf2/QEAPj01N5f7w">Links</a>&nbsp;- extremely old GIFs.</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Broken images</span></label><ul class="todo-list"><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description"><a class="reference-link" href="#root/krkLW8AwcYf2/l0tKav7yLHGF">Day Notes</a></span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description"><a class="reference-link" href="#root/krkLW8AwcYf2/aCE9SFyzUrod">Home</a></span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description"><a class="reference-link" href="#root/krkLW8AwcYf2/VbjZvtUek0Ln">Theme Gallery</a></span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description"><a class="reference-link" href="#root/krkLW8AwcYf2/9sRHySam5fXb">Workspace</a></span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description"><a class="reference-link" href="#root/krkLW8AwcYf2/iRwzGnHPzonm">Relation Map</a></span></label></li></ul></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Check for <code>%%{WARNING}%%.</code>.</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Integrate&nbsp;<a class="reference-link" href="#root/x1DxoyI27DXY/MGHZEjw7PAIZ">Syntax highlighting &amp; word wrapping for code blocks</a>&nbsp;into documentation.</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Document each note type</span></label><ul class="todo-list"><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Text</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Code</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Saved Search</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Relation Map</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Note Map</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Render Note</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Book</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Mermaid Diagram</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Canvas</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Web View</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Mind Map</span></label></li><li><label class="todo-list__label"><input type="checkbox" checked="checked" disabled="disabled"><span class="todo-list__label__description">Geo Map</span></label></li></ul></li></ul><h2>Generic improvements</h2><ul class="todo-list"><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Add some promoted attributes for when the page was last reviewed.</span></label></li></ul><h2>Development improvements</h2><ul class="todo-list"><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Integrate <a href="https://trilium.rocks/xecUJ8eL3pvM">Trilium Rocks theme</a>.</span></label></li></ul>


blobId: BJazh2si0j2WX523lTjw
dateModified: 2025-03-09 12:36:18.541+0200
utcDateModified: 2025-03-09 10:36:18.541Z
content:
  <p>A common pattern in note-taking is that a lot of notes will be centered around a certain date - e.g. you have some tasks which needs to be done on a certain date, you have meeting minutes from a certain date, you have your thoughts etc. and it all revolves around a date on which they occurred. For this reason, it makes sense to create a certain "day workspace" which will centralize all those notes relevant for a certain date.</p><p>For this, Trilium provides a concept of "day note". Trilium semi-automatically generates a single note for each day. Under this note you can save all those relevant notes.</p><p>Select an existing day note, and the menubar contains a calendar widget. Select any day to create a note for that day.&nbsp;</p><p><img src="api/attachments/H3Iy9PpIDd0Z/image/image.png" width="533" height="364"></p><p>This pattern works well also because of <a href="#root/pOsGYCXsbNQG/gh7bpGYxajRS/BFs8mudNFgCS/IakOLONlIfGI">Cloning Notes</a> functionality - note can appear in multiple places in the note tree, so besides appearing under day note, it can also be categorized into other notes.</p><h2>Demo</h2><figure class="image"><img style="aspect-ratio:1060/758;" src="api/attachments/9wmaElfXYjWM/image/image.png" width="1060" height="758"></figure><p>You can see the structure of day notes appearing under "Journal" note - there's a note for the whole year 2017, under it, you have "12 - December" which then contains "18 - Monday". This is our "day note" which contains some text in its content and also has some child notes (some of them are from <a href="#root/xYjQUYhpbUEW">Task manager</a>).</p><p>You can also notice how this day note has <a href="#root/OFXdgB2nNk1F">promoted attribute</a> "weight" where you can track your daily weight. This data is then used in <a href="#root/R7abl2fc6Mxi">Weight tracker</a>.</p><h2>Templates</h2><p>Trilium provides <a href="#root/KC1HB96bqqHX">template</a> functionality, and it could be used together with day notes.</p><p>You can define one of the following relations on the root of the journal (identified by <code>#calendarRoot</code> label):</p><ul><li>yearTemplate</li><li>monthTemplate</li><li>dateTemplate</li></ul><p>All of these are relations. When Trilium creates a new note for year or month or date, it will take a look at the root and attach a corresponding <code>~template</code> relation to the newly created role. Using this, you can e.g. create your daily template with e.g. checkboxes for daily routine etc.</p><h2>Date pattern</h2><p>It's possible to customize the title of generated date notes by defining a <code>#datePattern</code> label on a root calendar note (identified by <code>#calendarRoot</code> label). Following are possible values:</p><ul><li><code>{dayInMonthPadded} - {weekDay}</code> day notes are named e.g. "24 - Monday"</li><li><code>{dayInMonthPadded}: {weekDay3}</code> day notes are named e.g. "24: Mon"</li><li><code>{dayInMonthPadded}: {weekDay2}</code> day notes are named e.g. "24: Mo"</li><li><code>{isoDate} - {weekDay}</code> day notes are named e.g. "2020-12-24 - Monday"</li><li><code>{ordinal}</code> is replaced with the ordinal date (e.g. 1st, 2nd, 3rd) etc.</li></ul><h2>Month pattern</h2><p>It is also possible to customize the title of generated month notes through the <code>#monthPattern</code> attribute, much like <code>#datePattern</code>. The options are:</p><ul><li><code>{monthNumberPadded}</code> results in a number like <code>09</code> for September, and <code>11</code> for November</li><li><code>{month}</code> results in the full month name (e.g. <code>September</code> or <code>October</code>)</li><li><code>{shortMonth3}</code> is replaced with the first 3 letters of the month, e.g. Jan, Feb, etc.</li><li><code>{shortMonth4}</code> is replaced with the first 4 letters of the month, e.g. Sept, Octo, etc.</li></ul><p>The default is <code>{monthNumberPadded} - {month}</code></p><h2>Implementation</h2><p>Trilium has some special support for day notes in the form of <a href="https://triliumnext.github.io/Notes/backend_api/BackendScriptApi.html">backend Script API</a> - see e.g. getDayNote() function.</p><p>Day (and year, month) notes are created with a label - e.g. <code>#dateNote="2018-08-16"</code> this can then be used by other scripts to add new notes to day note etc.</p><p>Journal also has relation <code>child:child:child:template=Day template</code> (see [[attribute inheritance]]) which effectively adds [[template]] to day notes (grand-grand-grand children of Journal).</p>


blobId: HDuY5rRznerR5TJRpfis
dateModified: 2025-03-09 12:37:33.825+0200
utcDateModified: 2025-03-09 10:37:33.826Z
content:
  <ul class="todo-list"><li><label class="todo-list__label"><input type="checkbox" checked="checked" disabled="disabled"><span class="todo-list__label__description">Integrate titles of the notes</span></label></li><li><label class="todo-list__label"><input type="checkbox" checked="checked" disabled="disabled"><span class="todo-list__label__description">Set <code>#shareAlias</code> for all the notes</span></label></li><li><label class="todo-list__label"><input type="checkbox" checked="checked" disabled="disabled"><span class="todo-list__label__description">Recreate structure of notes</span></label></li><li><label class="todo-list__label"><input type="checkbox" checked="checked" disabled="disabled"><span class="todo-list__label__description">Add icons to the notes</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Merge images into their corresponding notes</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Review and delete each note from Pikapod</span></label></li></ul><h2>Content changes</h2><ul class="todo-list"><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description"><a class="reference-link" href="#root/krkLW8AwcYf2/poXkQfguuA0U">Desktop Installation</a></span></label><ul class="todo-list"><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Mention Windows installation.</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Integrate Fedora documentation</span></label></li></ul></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description"><a class="reference-link" href="#root/krkLW8AwcYf2/Hdf1kG6Kvcl1">Link map</a>&nbsp;– it's empty</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description"><a class="reference-link" href="#root/krkLW8AwcYf2/QEAPj01N5f7w">Links</a>&nbsp;- extremely old GIFs.</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Broken images</span></label><ul class="todo-list"><li><label class="todo-list__label"><input type="checkbox" checked="checked" disabled="disabled"><span class="todo-list__label__description"><a class="reference-link" href="#root/krkLW8AwcYf2/l0tKav7yLHGF">Day Notes</a></span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description"><a class="reference-link" href="#root/krkLW8AwcYf2/VbjZvtUek0Ln">Theme Gallery</a></span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description"><a class="reference-link" href="#root/krkLW8AwcYf2/9sRHySam5fXb">Workspace</a></span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description"><a class="reference-link" href="#root/krkLW8AwcYf2/iRwzGnHPzonm">Relation Map</a></span></label></li></ul></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Check for <code>%%{WARNING}%%.</code>.</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Integrate&nbsp;<a class="reference-link" href="#root/x1DxoyI27DXY/MGHZEjw7PAIZ">Syntax highlighting &amp; word wrapping for code blocks</a>&nbsp;into documentation.</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Document each note type</span></label><ul class="todo-list"><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Text</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Code</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Saved Search</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Relation Map</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Note Map</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Render Note</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Book</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Mermaid Diagram</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Canvas</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Web View</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Mind Map</span></label></li><li><label class="todo-list__label"><input type="checkbox" checked="checked" disabled="disabled"><span class="todo-list__label__description">Geo Map</span></label></li></ul></li></ul><h2>Generic improvements</h2><ul class="todo-list"><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Add some promoted attributes for when the page was last reviewed.</span></label></li></ul><h2>Development improvements</h2><ul class="todo-list"><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Integrate <a href="https://trilium.rocks/xecUJ8eL3pvM">Trilium Rocks theme</a>.</span></label></li></ul>


blobId: kFK3zeMCIufB4dMKQLuY
dateModified: 2025-03-09 12:42:29.626+0200
utcDateModified: 2025-03-09 10:42:29.626Z
content:
  <p>These are user-created themes which were made publicly available:</p><figure class="table"><table><thead><tr><th>&nbsp;</th><th>Author</th></tr></thead><tbody><tr><td><a href="https://github.com/tobealive/trilium-midnight-theme">Midnight</a>&nbsp;</td><td><a href="https://github.com/tobealive">tobealive</a></td></tr><tr><td><a href="https://github.com/tobealive/trilum-eote-theme">EOTE</a>&nbsp;</td><td><a href="https://github.com/tobealive">tobealive</a></td></tr><tr><td><a href="https://github.com/Abourass/TriliumThemes">Trilium Themes</a>&nbsp;</td><td><a href="https://github.com/Abourass">Abourass</a>&nbsp;</td></tr><tr><td><a href="https://github.com/ZMonk91/Material-Dark-Trilium">MaterialDark</a>&nbsp;</td><td><a href="https://github.com/ZMonk91">ZMonk91</a>&nbsp;</td></tr><tr><td><a href="https://github.com/jaroet/trilium-theme-lightslategray">lightslategray</a>&nbsp;</td><td><a href="https://github.com/jaroet">jaroet</a>&nbsp;</td></tr><tr><td><a href="https://github.com/raphwriter/trilium-theme-melon">melon-4</a>&nbsp;</td><td><a href="https://github.com/raphwriter">raphwriter</a>&nbsp;</td></tr><tr><td><a href="https://github.com/Engr-AllanG/trilium-themes">Neon_Dark</a>&nbsp;</td><td><a href="https://github.com/Engr-AllanG">Engr-AllanG</a>&nbsp;</td></tr><tr><td><a href="https://github.com/Engr-AllanG/trilium-themes">Coder_Dark</a>&nbsp;</td><td><a href="https://github.com/Engr-AllanG">Engr-AllanG</a>&nbsp;</td></tr><tr><td><a href="https://github.com/idelem/trilium-theme-velvet">velvet</a>&nbsp;</td><td><a href="https://github.com/idelem">idelem</a>&nbsp;</td></tr><tr><td><a href="https://github.com/SADAVA/trilium-notes-theme-dark-plus">Dark Plus</a>&nbsp;</td><td><a href="https://github.com/SADAVA">SADAVA</a>&nbsp;</td></tr><tr><td><a href="https://github.com/WKSu/trilium-solarized-theme">Solarized</a>&nbsp;</td><td><a href="https://github.com/WKSu">WKSu</a>&nbsp;</td></tr><tr><td><a href="https://github.com/en3r0/Trilium-Nord-Theme">Nord</a>&nbsp;</td><td><a href="https://github.com/en3r0">en3r0</a>&nbsp;</td></tr><tr><td><a href="https://github.com/AllanZyne/trilium-bear-theme">Bear Note Light</a>&nbsp;</td><td><a href="https://github.com/AllanZyne">AllanZyne</a>&nbsp;</td></tr><tr><td><a href="https://github.com/AllanZyne/trilium-bear-theme">Bear Note Dark</a>&nbsp;</td><td><a href="https://github.com/AllanZyne">AllanZyne</a>&nbsp;</td></tr><tr><td><a href="https://github.com/Sebiann/miku-hatsune-trilium-theme">Miku Hatsune</a>&nbsp;</td><td><a href="https://github.com/Sebiann">Sebiann</a>&nbsp;</td></tr><tr><td><a href="https://github.com/cwilliams5/Midnight-Trilium-Dark-Mode">Midnight</a>&nbsp;</td><td><a href="https://github.com/cwilliams5">cwilliams5</a>&nbsp;</td></tr><tr><td><a href="https://github.com/SiriusXT/trilium-theme-blue">Blue</a> (light)&nbsp;</td><td><a href="https://github.com/SiriusXT">SiriusXT</a>&nbsp;</td></tr><tr><td><a href="https://github.com/SiriusXT/trilium-theme-blue">Blue</a> (dark)&nbsp;</td><td><a href="https://github.com/SiriusXT">SiriusXT</a>&nbsp;</td></tr></tbody></table></figure><p>If you would like to add your theme to this gallery, write a new post in <a href="https://github.com/TriliumNext/Notes/discussions/categories/show-and-tell">👐 Show and tell</a>.</p>


blobId: NS1skdFIUu9drbbFwZZH
dateModified: 2025-03-09 13:00:28.876+0200
utcDateModified: 2025-03-09 11:00:28.876Z
content:
  <p>These are user-created themes which were made publicly available:</p><h2>Legacy Themes</h2><p>These themes may or may not be compatible with the latest versions of TriliumNext and are based on the original/legacy theme.</p><figure class="table"><table><thead><tr><th>Theme</th><th>Author</th></tr></thead><tbody><tr><td><a href="https://github.com/tobealive/trilium-midnight-theme">Midnight</a>&nbsp;</td><td><a href="https://github.com/tobealive">tobealive</a></td></tr><tr><td><a href="https://github.com/tobealive/trilum-eote-theme">EOTE</a>&nbsp;</td><td><a href="https://github.com/tobealive">tobealive</a></td></tr><tr><td><a href="https://github.com/Abourass/TriliumThemes">Trilium Themes</a>&nbsp;</td><td><a href="https://github.com/Abourass">Abourass</a>&nbsp;</td></tr><tr><td><a href="https://github.com/ZMonk91/Material-Dark-Trilium">MaterialDark</a>&nbsp;</td><td><a href="https://github.com/ZMonk91">ZMonk91</a>&nbsp;</td></tr><tr><td><a href="https://github.com/jaroet/trilium-theme-lightslategray">lightslategray</a>&nbsp;</td><td><a href="https://github.com/jaroet">jaroet</a>&nbsp;</td></tr><tr><td><a href="https://github.com/raphwriter/trilium-theme-melon">melon-4</a>&nbsp;</td><td><a href="https://github.com/raphwriter">raphwriter</a>&nbsp;</td></tr><tr><td><a href="https://github.com/Engr-AllanG/trilium-themes">Neon_Dark</a>&nbsp;</td><td><a href="https://github.com/Engr-AllanG">Engr-AllanG</a>&nbsp;</td></tr><tr><td><a href="https://github.com/Engr-AllanG/trilium-themes">Coder_Dark</a>&nbsp;</td><td><a href="https://github.com/Engr-AllanG">Engr-AllanG</a>&nbsp;</td></tr><tr><td><a href="https://github.com/idelem/trilium-theme-velvet">velvet</a>&nbsp;</td><td><a href="https://github.com/idelem">idelem</a>&nbsp;</td></tr><tr><td><a href="https://github.com/SADAVA/trilium-notes-theme-dark-plus">Dark Plus</a>&nbsp;</td><td><a href="https://github.com/SADAVA">SADAVA</a>&nbsp;</td></tr><tr><td><a href="https://github.com/WKSu/trilium-solarized-theme">Solarized</a>&nbsp;</td><td><a href="https://github.com/WKSu">WKSu</a>&nbsp;</td></tr><tr><td><a href="https://github.com/en3r0/Trilium-Nord-Theme">Nord</a>&nbsp;</td><td><a href="https://github.com/en3r0">en3r0</a>&nbsp;</td></tr><tr><td><a href="https://github.com/AllanZyne/trilium-bear-theme">Bear Note Light</a>&nbsp;</td><td><a href="https://github.com/AllanZyne">AllanZyne</a>&nbsp;</td></tr><tr><td><a href="https://github.com/AllanZyne/trilium-bear-theme">Bear Note Dark</a>&nbsp;</td><td><a href="https://github.com/AllanZyne">AllanZyne</a>&nbsp;</td></tr><tr><td><a href="https://github.com/Sebiann/miku-hatsune-trilium-theme">Miku Hatsune</a>&nbsp;</td><td><a href="https://github.com/Sebiann">Sebiann</a>&nbsp;</td></tr><tr><td><a href="https://github.com/cwilliams5/Midnight-Trilium-Dark-Mode">Midnight</a>&nbsp;</td><td><a href="https://github.com/cwilliams5">cwilliams5</a>&nbsp;</td></tr><tr><td><a href="https://github.com/SiriusXT/trilium-theme-blue">Blue</a> (light)&nbsp;</td><td><a href="https://github.com/SiriusXT">SiriusXT</a>&nbsp;</td></tr><tr><td><a href="https://github.com/SiriusXT/trilium-theme-blue">Blue</a> (dark)&nbsp;</td><td><a href="https://github.com/SiriusXT">SiriusXT</a>&nbsp;</td></tr></tbody></table></figure><p>If you would like to add your theme to this gallery, write a new post in <a href="https://github.com/TriliumNext/Notes/discussions/categories/show-and-tell">👐 Show and tell</a>.</p>


blobId: xKTBgZ6UHhyRCk2LO1uX
dateModified: 2025-03-09 13:04:39.256+0200
utcDateModified: 2025-03-09 11:04:39.257Z
content:
  <p>Workspace is a concept built up on top of <a href="#root/OR8WJ7Iz9K4U">note hoisting</a>. It is based on the idea that a user has several distinct spheres of interest. An example might be "Personal" and "Work", these two spheres are quite distinct and don't interact together. When I focus on Work, I don't really care about personal notes.</p><p>So far workspace consists of these features:</p><ul><li><a href="#root/OR8WJ7Iz9K4U">note hoisting</a> - you can "zoom" into a workspace subtree to focus only on the relevant notes</li><li><p>easy entering of workspace:&nbsp;</p><p><img src="api/attachments/vZSH2mOKzWBx/image/image.png" width="452" height="251"></p></li><li>visual identification of workspace in tabs:<br><img src="api/attachments/V4TIsmtBh8P7/image/image.png" width="736" height="87"></li></ul><h3>How to use workspaces</h3><p>Let's say you have identified the workspaces and their subtrees. Define on the root of this subtree following labels:</p><ul><li><code>#workspace</code> - Marks this note as a workspace, button to enter the workspace is controlled by this</li><li><code>#workspaceIconClass</code> - controls the box icon to be displayed in the tree and tabs, example <code>bx bx-home</code>. See <a href="https://boxicons.com/">https://boxicons.com/</a></li><li><code>#workspaceTabBackgroundColor</code> - Background color of the tab, use any CSS color format, e.g. "lightblue" or "#ddd". See <a href="https://www.w3schools.com/cssref/css_colors.asp">https://www.w3schools.com/cssref/css_colors.asp</a>.</li><li><code>#workspaceCalendarRoot</code> - marking a note with this label will define a new per-workspace calendar. If there's no such note, the global calendar will be used.</li><li><code>#workspaceTemplate</code> - This note will appear in the selection of available templates when creating a new note, but only when you are currently hoisted into a workspace containing this template.</li></ul>


blobId: Icba0Xvr8Q73MgpzbBa9
dateModified: 2025-03-09 13:04:53.497+0200
utcDateModified: 2025-03-09 11:04:53.497Z
content:
  <ul class="todo-list"><li><label class="todo-list__label"><input type="checkbox" checked="checked" disabled="disabled"><span class="todo-list__label__description">Integrate titles of the notes</span></label></li><li><label class="todo-list__label"><input type="checkbox" checked="checked" disabled="disabled"><span class="todo-list__label__description">Set <code>#shareAlias</code> for all the notes</span></label></li><li><label class="todo-list__label"><input type="checkbox" checked="checked" disabled="disabled"><span class="todo-list__label__description">Recreate structure of notes</span></label></li><li><label class="todo-list__label"><input type="checkbox" checked="checked" disabled="disabled"><span class="todo-list__label__description">Add icons to the notes</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Merge images into their corresponding notes</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Review and delete each note from Pikapod</span></label></li></ul><h2>Content changes</h2><ul class="todo-list"><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description"><a class="reference-link" href="#root/krkLW8AwcYf2/poXkQfguuA0U">Desktop Installation</a></span></label><ul class="todo-list"><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Mention Windows installation.</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Integrate Fedora documentation</span></label></li></ul></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description"><a class="reference-link" href="#root/krkLW8AwcYf2/Hdf1kG6Kvcl1">Link map</a>&nbsp;– it's empty</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description"><a class="reference-link" href="#root/krkLW8AwcYf2/QEAPj01N5f7w">Links</a>&nbsp;- extremely old GIFs.</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Broken images</span></label><ul class="todo-list"><li><label class="todo-list__label"><input type="checkbox" checked="checked" disabled="disabled"><span class="todo-list__label__description"><a class="reference-link" href="#root/krkLW8AwcYf2/l0tKav7yLHGF">Day Notes</a></span></label></li><li><label class="todo-list__label"><input type="checkbox" checked="checked" disabled="disabled"><span class="todo-list__label__description"><a class="reference-link" href="#root/krkLW8AwcYf2/VbjZvtUek0Ln">Theme Gallery</a></span></label></li><li><label class="todo-list__label"><input type="checkbox" checked="checked" disabled="disabled"><span class="todo-list__label__description"><a class="reference-link" href="#root/krkLW8AwcYf2/9sRHySam5fXb">Workspace</a></span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description"><a class="reference-link" href="#root/krkLW8AwcYf2/iRwzGnHPzonm">Relation Map</a></span></label></li></ul></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Check for <code>%%{WARNING}%%.</code>.</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Integrate&nbsp;<a class="reference-link" href="#root/x1DxoyI27DXY/MGHZEjw7PAIZ">Syntax highlighting &amp; word wrapping for code blocks</a>&nbsp;into documentation.</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Document each note type</span></label><ul class="todo-list"><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Text</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Code</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Saved Search</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Relation Map</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Note Map</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Render Note</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Book</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Mermaid Diagram</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Canvas</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Web View</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Mind Map</span></label></li><li><label class="todo-list__label"><input type="checkbox" checked="checked" disabled="disabled"><span class="todo-list__label__description">Geo Map</span></label></li></ul></li></ul><h2>Generic improvements</h2><ul class="todo-list"><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Add some promoted attributes for when the page was last reviewed.</span></label></li></ul><h2>Development improvements</h2><ul class="todo-list"><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Integrate <a href="https://trilium.rocks/xecUJ8eL3pvM">Trilium Rocks theme</a>.</span></label></li></ul>


blobId: pFeiBBX4lSdtLO4qmbh3
dateModified: 2025-03-09 22:28:24.703+0200
utcDateModified: 2025-03-09 20:28:24.704Z
content:
  <div><div><div><div><h2>💡 Key highlights</h2><ul><li>…</li></ul><h2>🐞 Bugfixes</h2><ul><li>Login screen not rendering correctly under dark mode.</li><li><a href="https://github.com/TriliumNext/Notes/issues/1218">Some valid javascript syntax are highlighted as error</a></li><li><a href="https://github.com/TriliumNext/Notes/issues/1308">Clarify misleading message about deleting revisions</a></li><li><a href="https://github.com/TriliumNext/Notes/issues/357">Note creation issues with certain template types</a></li><li><a href="https://github.com/TriliumNext/Notes/issues/1378">Child note preview: a "broken picture" icon appears for empty canvas notes</a></li></ul><h2>✨ Improvements</h2><ul><li><a href="https://github.com/TriliumNext/Notes/pull/1361">Allow light and dark theme as base theme</a></li></ul><h2>🌍 Internationalization</h2><ul><li>…</li></ul><h2>🛠️ Technical updates</h2><ul><li>Updated test dependencies</li><li>build: improvements for TS &amp; Webpack &amp; Docker by @pano9000 </li></ul><p>&nbsp;</p></div></div></div></div>


blobId: 50SLzh2nUsztTpcXoj7L
dateModified: 2025-03-09 22:31:43.582+0200
utcDateModified: 2025-03-09 20:31:43.583Z
content:
  <ul class="todo-list"><li><label class="todo-list__label"><input type="checkbox" checked="checked" disabled="disabled"><span class="todo-list__label__description">Integrate titles of the notes</span></label></li><li><label class="todo-list__label"><input type="checkbox" checked="checked" disabled="disabled"><span class="todo-list__label__description">Set <code>#shareAlias</code> for all the notes</span></label></li><li><label class="todo-list__label"><input type="checkbox" checked="checked" disabled="disabled"><span class="todo-list__label__description">Recreate structure of notes</span></label></li><li><label class="todo-list__label"><input type="checkbox" checked="checked" disabled="disabled"><span class="todo-list__label__description">Add icons to the notes</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Merge images into their corresponding notes</span></label></li><li><label class="todo-list__label"><input type="checkbox" checked="checked" disabled="disabled"><span class="todo-list__label__description">Review and delete each note from Pikapod</span></label></li></ul><h2>Content changes</h2><ul class="todo-list"><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description"><a class="reference-link" href="#root/krkLW8AwcYf2/poXkQfguuA0U">Desktop Installation</a></span></label><ul class="todo-list"><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Mention Windows installation.</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Integrate Fedora documentation</span></label></li></ul></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description"><a class="reference-link" href="#root/krkLW8AwcYf2/Hdf1kG6Kvcl1">Link map</a>&nbsp;– it's empty</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description"><a class="reference-link" href="#root/krkLW8AwcYf2/QEAPj01N5f7w">Links</a>&nbsp;- extremely old GIFs.</span></label></li><li><label class="todo-list__label"><input type="checkbox" checked="checked" disabled="disabled"><span class="todo-list__label__description">Broken images</span></label><ul class="todo-list"><li><label class="todo-list__label"><input type="checkbox" checked="checked" disabled="disabled"><span class="todo-list__label__description"><a class="reference-link" href="#root/krkLW8AwcYf2/l0tKav7yLHGF">Day Notes</a></span></label></li><li><label class="todo-list__label"><input type="checkbox" checked="checked" disabled="disabled"><span class="todo-list__label__description"><a class="reference-link" href="#root/krkLW8AwcYf2/VbjZvtUek0Ln">Theme Gallery</a></span></label></li><li><label class="todo-list__label"><input type="checkbox" checked="checked" disabled="disabled"><span class="todo-list__label__description"><a class="reference-link" href="#root/krkLW8AwcYf2/9sRHySam5fXb">Workspace</a></span></label></li></ul></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Check for <code>%%{WARNING}%%.</code>.</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Integrate&nbsp;<a class="reference-link" href="#root/x1DxoyI27DXY/MGHZEjw7PAIZ">Syntax highlighting &amp; word wrapping for code blocks</a>&nbsp;into documentation.</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Document each note type</span></label><ul class="todo-list"><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Text</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Code</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Saved Search</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Relation Map</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Note Map</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Render Note</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Book</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Mermaid Diagram</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Canvas</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Web View</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Mind Map</span></label></li><li><label class="todo-list__label"><input type="checkbox" checked="checked" disabled="disabled"><span class="todo-list__label__description">Geo Map</span></label></li></ul></li></ul><h2>Generic improvements</h2><ul class="todo-list"><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Add some promoted attributes for when the page was last reviewed.</span></label></li></ul><h2>Development improvements</h2><ul class="todo-list"><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Integrate <a href="https://trilium.rocks/xecUJ8eL3pvM">Trilium Rocks theme</a>.</span></label></li></ul>


blobId: hbXmUWecAY32BXJpPtE8
dateModified: 2025-03-09 22:50:23.055+0200
utcDateModified: 2025-03-09 20:50:23.068Z
content:
  <div class="content">
         

        <div class="ck-content">
          <p>A good use case of promoted attributes is to easily define the various
            parameters a script might need, for example an input and output note if
            it's processing data, or a checkbox to define a particular change in behavior
            for the script.</p>
          <p>
            <img src="api/attachments/7XMQhZVw2qKn/image/Using promoted attributes .png" width="425" height="179">
          </p>
          <h2>Using check boxes to toggle flags</h2>
          <p>Instead of asking the user to modify a boolean value in the script, it's
            much more intuitive to use a checkbox for it as a promoted attribute.</p>
          <p>To do so, first define the promoted attribute:</p><pre><code class="language-text-x-trilium-auto">#label:groupByExtension="promoted,alias=Group by extension,single,boolean"</code></pre>
          <p>Then use it:</p><pre><code class="language-application-javascript-env-frontend">const byExtension = api.currentNote.getLabelValue("groupByExtension") === "true";
  if (byExtension) {
  	// Do something.
  }</code></pre>
          <p>This will work equally well in both front-end and back-end scripts.</p>
          <h2>Using relations to select notes</h2>
          <p>One common use case for a script is to read data from another note and
            perhaps output its result in another note. To do so we need to define the
            following promoted attributes:</p><pre><code class="language-text-x-trilium-auto">#relation:input="promoted,alias=Input,single" #relation:output="promoted,alias=Output,single"</code></pre>
          <p>Once we have this, we can add some basic error handling to ensure that
            the fields are completed by the user:</p><pre><code class="language-text-x-trilium-auto">const inputNoteId = api.currentNote.getRelationValue("input");   
  if (!inputNoteId) {
  	api.showError("Missing input.");
      return;
  }

  const outputNoteId = api.currentNote.getRelationValue("output");
  if (!outputNoteId) {
      api.showError("Missing output.");
      return;
  }</code></pre>
          <p>Note that here we are using <code>api.showError</code> which is only available
            for frontend notes. If you are writing a backend note, simply remove <code>api.showError</code> but
            the user will no feedback on why the script did not execute properly.</p>
          <p>Afterwards we can simply read the note and do something with it:</p><pre><code class="language-text-x-trilium-auto">const note = api.getNote(inputNoteId);
  if (!note) {
  	return;
  }
  const content = note.getContent().toString("utf-8");</code></pre>
        </div>
      </div>


blobId: tHK2FqkgIvQ0p8gn28dI
dateModified: 2025-03-09 22:50:35.980+0200
utcDateModified: 2025-03-09 20:50:35.992Z
content:
  <div><div><p>A good use case of promoted attributes is to easily define the various parameters a script might need, for example an input and output note if it's processing data, or a checkbox to define a particular change in behavior for the script.</p><p><img src="api/attachments/7P3jzVEa1mk7/image/Using promoted attributes .png" width="425" height="179"></p><h2>Using check boxes to toggle flags</h2><p>Instead of asking the user to modify a boolean value in the script, it's much more intuitive to use a checkbox for it as a promoted attribute.</p><p>To do so, first define the promoted attribute:</p><pre><code class="language-text-x-trilium-auto">#label:groupByExtension="promoted,alias=Group by extension,single,boolean"</code></pre><p>Then use it:</p><pre><code class="language-application-javascript-env-frontend">const byExtension = api.currentNote.getLabelValue("groupByExtension") === "true";
  if (byExtension) {
  	// Do something.
  }</code></pre><p>This will work equally well in both front-end and back-end scripts.</p><h2>Using relations to select notes</h2><p>One common use case for a script is to read data from another note and perhaps output its result in another note. To do so we need to define the following promoted attributes:</p><pre><code class="language-text-x-trilium-auto">#relation:input="promoted,alias=Input,single" #relation:output="promoted,alias=Output,single"</code></pre><p>Once we have this, we can add some basic error handling to ensure that the fields are completed by the user:</p><pre><code class="language-application-javascript-env-frontend">const inputNoteId = api.currentNote.getRelationValue("input");
  if (!inputNoteId) {
  	api.showError("Missing input.");
      return;
  }

  const outputNoteId = api.currentNote.getRelationValue("output");
  if (!outputNoteId) {
      api.showError("Missing output.");
      return;
  }</code></pre><p>Note that here we are using <code>api.showError</code> which is only available for frontend notes. If you are writing a backend note, simply remove <code>api.showError</code> but the user will no feedback on why the script did not execute properly.</p><p>Afterwards we can simply read the note and do something with it:</p><pre><code class="language-application-javascript-env-frontend">const note = api.getNote(inputNoteId);
  if (!note) {
  	return;
  }
  const content = note.getContent().toString("utf-8");</code></pre></div></div>


blobId: jpD1faEXSITYa1jl2ZTW
dateModified: 2025-03-09 22:57:30.620+0200
utcDateModified: 2025-03-09 20:57:30.621Z
content:
  <div><div><p>This tutorial showcases a basic integration with Google Forms, where we are able to download the responses of a form using the “Link to Sheets" functionality.</p><p>Note that the link will be publicly accessible to everyone (however the link is in a hard-to-guess format such as <code>https://docs.google.com/spreadsheets/d/e/2PACX-1vTA8NU2_eZFhc8TFadCZPreBfvP7un8IHd6J0SchrLLw3ueGmntNZjwRmsH2ZRcp1pJYDAzMz1FmFaj/pub?output=csv</code>). Make sure you are not accidentally publishing sensitive information.</p><h2>Obtaining the CSV link</h2><ol><li>Open the Google Forms in a browser.</li><li>Select the “Responses” tab and click on “Link to Sheets”.</li><li>Select “Create a new spreadsheet” and press “Create”.</li><li>In Google Sheets, select File → Share → Publish to web.</li><li>In the “Publish to the web” screen, make sure the “Link” tab is selected and instead of “Web page”, select “Comma-separated values (.csv)”.</li><li>Copy the given link which will be used for the upcoming script.</li></ol><h2>Creating the script</h2><p>Create a “JS Frontend” script:</p><pre><code class="language-text-x-trilium-auto">const CSV_URL = "https://docs.google.com/spreadsheets/d/e/2PACX-1vTiwooLV2whjCSVa49dJ99p_G3_qhqHHRqttMjYCJVfLXVdTgUSNJu5K0rpqmaHYF2k7Vofi3o7gW82/pub?output=csv";

  async function fetchData() {
      try {
          const response = await fetch(CSV_URL);
          return await response.text();
      } catch (e) {
          api.showError(e.message);
      }
  }

  const data = await fetchData();
  console.log(data);
  // Do something with the data.</code></pre><p>Note that the data will be received as a string and there is no library to do the CSV parsing for us. To do a very simple parsing of CSV:</p><pre><code class="language-text-x-trilium-auto">const content = data
  	.split("\n")
  	.slice(1)
  	.map((row) =&gt; row.split(","));</code></pre><p>This will return the data as an array of arrays.</p></div></div>


blobId: xvsESjpjcnZP6kyMXEKh
dateModified: 2025-03-09 23:06:12.970+0200
utcDateModified: 2025-03-09 21:06:12.970Z
content:
  <p>Trilium provides a mechanism for <a href="#root/CdNpE2pqjmI6">scripts</a> to open a public REST endpoint. This opens a way for various integrations with other services - a simple example would be creating new note from Slack by issuing a slash command (e.g. <code>/trilium buy milk</code>).</p><h2>Create note from outside Trilium</h2><p>Let's take a look at an example. The goal is to provide a REST endpoint to which we can send title and content and Trilium will create a note.</p><p>We'll start with creating a JavaScript backend <a href="#root/6f9hih2hXXZk">code note</a> containing:</p><pre><code class="language-text-x-trilium-auto">const {req, res} = api;
  const {secret, title, content} = req.body;

  if (req.method == 'POST' &amp;&amp; secret === 'secret-password') {
      // notes must be saved somewhere in the tree hierarchy specified by a parent note. 
      // This is defined by a relation from this code note to the "target" parent note
      // alternetively you can just use constant noteId for simplicity (get that from "Note Info" dialog of the desired parent note)
      const targetParentNoteId = api.currentNote.getRelationValue('targetNote');
      
      const {note} = api.createTextNote(targetParentNoteId, title, content);
      const notePojo = note.getPojo();

      res.status(201).json(notePojo);
  }
  else {
      res.send(400);
  }</code></pre><p>This script note has also following two attributes:</p><ul><li>label <code>#customRequestHandler</code> with value <code>create-note</code></li><li>relation <code>~targetNote</code> pointing to a note where new notes should be saved</li></ul><h3>Explanation</h3><p>Let's test this by using an HTTP client to send a request:</p><pre><code class="language-text-x-trilium-auto">POST http://my.trilium.org/custom/create-note
  Content-Type: application/json

  {
    "secret": "secret-password",
    "title": "hello",
    "content": "world"
  }+++++++++++++++++++++++++++++++++++++++++++++++</code></pre><p>Notice the <code>/custom</code> part in the request path - Trilium considers any request with this prefix as "custom" and tries to find a matching handler by looking at all notes which have <code>customRequestHandler</code> <a href="#root/zEY4DaJG4YT5">label</a>. Value of this label then contains a regular expression which will match the request path (in our case trivial regex "create-note").</p><p>Trilium will then find our code note created above and execute it. <code>api.req</code>, <code>api.res</code> are set to <a href="https://expressjs.com/en/api.html#req">request</a> and <a href="https://expressjs.com/en/api.html#res">response</a> objects from which we can get details of the request and also respond.</p><p>In the code note we check the request method and then use trivial authentication - keep in mind that these endpoints are by default totally unauthenticated, and you need to take care of this yourself.</p><p>Once we pass these checks we will just create the desired note using <a href="#root/GLks18SNjxmC">Script API</a>.</p><h2>Custom resource provider</h2><p>Another common use case is that you want to just expose a file note - in such case you create label <code>customResourceProvider</code> (value is again path regex).</p><p>For more information, see&nbsp;<a class="reference-link" href="#root/tC7s2alapj8V/d3fAXQ2diepH">Custom Resource Providers</a>.</p><h2>Advanced concepts</h2><p><code>api.req</code> and <code>api.res</code> are Express.js objects - you can always look into its <a href="https://expressjs.com/en/api.html">documentation</a> for details.</p><h3>Parameters</h3><p>REST request paths often contain parameters in the URL, e.g.:</p><pre><code class="language-text-x-trilium-auto">http://my.trilium.org/custom/notes/123</code></pre><p>The last part is dynamic so the matching of the URL must also be dynamic - for this reason the matching is done with regular expressions. Following <code>customRequestHandler</code> value would match it:</p><pre><code class="language-text-x-trilium-auto">notes/([0-9]+)</code></pre><p>Additionally, this also defines a matching group with the use of parenthesis which then makes it easier to extract the value. The matched groups are available in <code>api.pathParams</code>:</p><pre><code class="language-text-x-trilium-auto">const noteId = api.pathParams[0];</code></pre><p>Often you also need query params (as in e.g. <code>http://my.trilium.org/custom/notes?noteId=123</code>), you can get those with standard express <code>req.query.noteId</code>.</p>


blobId: 7kZ3hrw9ywZOyY5q5Lx2
dateModified: 2025-03-09 23:09:22.575+0200
utcDateModified: 2025-03-09 21:09:22.581Z
content:
  <div class="content">
         

        <div class="ck-content">
          <figure class="image image-style-align-right image_resized" style="width:50.63%;">
            <img style="aspect-ratio:951/432;" src="api/attachments/mig37zJeViA5/image/Export as PDF_image.png" width="951"
            height="432">
            <figcaption>Screenshot of the note contextual menu indicating the “Export as PDF”
              option.</figcaption>
          </figure>
          <p>On the desktop application of Trilium it is possible to export a note
            as PDF. On the server or PWA (mobile), the option is not available due
            to technical constraints and it will be hidden.</p>
          <p>To print a note, select the
            <img src="api/attachments/l9SFcOBSQcaD/image/1_Export as PDF_image.png" width="29"
            height="31">button to the right of the note and select <i>Export as PDF</i>.</p>
          <p>Afterwards you will be prompted to select where to save the PDF file.
            Upon confirmation, the resulting PDF will be opened automatically using
            the default/system application configured for PDFs.</p>
          <p>Should you encounter any visual issues in the resulting PDF file (e.g.
            a table does not fit properly, there is cut off text, etc.) feel free to
            <a
            href="#root/OeKBfN6JbMIq/jRV1MPt4mNSP/hrC6xn7hnDq5">report the issue</a>. In this case, it's best to offer a sample note (click
              on the
              <img src="api/attachments/l9SFcOBSQcaD/image/1_Export as PDF_image.png" width="29" height="31">button, select Export note → This note and all of its descendants → HTML
              in ZIP archive). Make sure not to accidentally leak any personal information.</p>
          <h2>Landscape mode</h2>
          <p>When exporting to PDF, there are no customizable settings such as page
            orientation, size, etc. However, it is possible to specify a given note
            to be printed as a PDF in landscape mode by adding the <code>#printLandscape</code> attribute
            to it (see&nbsp;<a class="reference-link" href="#root/9QRytp0ZYFIf/PnO38wN0ffOA">Adding an attribute to a note</a>).</p>
          <h2>Page size</h2>
          <p>By default, the resulting PDF will be in Letter format. It is possible
            to adjust it to another page size via the <code>#printPageSize</code> attribute,
            with one of the following values: <code>A0</code>, <code>A1</code>, <code>A2</code>, <code>A3</code>, <code>A4</code>, <code>A5</code>, <code>A6</code>, <code>Legal</code>, <code>Letter</code>, <code>Tabloid</code>, <code>Ledger</code>.</p>
          <h2>Keyboard shortcut</h2>
          <p>It's possible to trigger the export to PDF from the keyboard by going
            to&nbsp;<i>Keyboard shortcuts</i>&nbsp;and assigning a key combination
            for the <code>exportAsPdf</code> action.</p>
        </div>
      </div>


blobId: MSjIqwrsPxtqMqjZbwxj
dateModified: 2025-03-09 23:09:22.575+0200
utcDateModified: 2025-03-09 21:09:22.582Z
content:
  <div><div><figure class="image image-style-align-right image_resized" style="width:50.63%;"><img style="aspect-ratio:951/432;" src="api/attachments/NfSjRsArIQHy/image/Export as PDF_image.png" width="951" height="432"><figcaption>Screenshot of the note contextual menu indicating the “Export as PDF” option.</figcaption></figure><p>On the desktop application of Trilium it is possible to export a note as PDF. On the server or PWA (mobile), the option is not available due to technical constraints and it will be hidden.</p><p>To print a note, select the <img src="api/attachments/Om2EmdZr54vy/image/1_Export as PDF_image.png" width="29" height="31">button to the right of the note and select <i>Export as PDF</i>.</p><p>Afterwards you will be prompted to select where to save the PDF file. Upon confirmation, the resulting PDF will be opened automatically using the default/system application configured for PDFs.</p><p>Should you encounter any visual issues in the resulting PDF file (e.g. a table does not fit properly, there is cut off text, etc.) feel free to <a href="#root/OeKBfN6JbMIq/jRV1MPt4mNSP/hrC6xn7hnDq5">report the issue</a>. In this case, it's best to offer a sample note (click on the <img src="api/attachments/Om2EmdZr54vy/image/1_Export as PDF_image.png" width="29" height="31"> button, select Export note → This note and all of its descendants → HTML in ZIP archive). Make sure not to accidentally leak any personal information.</p><h2>Landscape mode</h2><p>When exporting to PDF, there are no customizable settings such as page orientation, size, etc. However, it is possible to specify a given note to be printed as a PDF in landscape mode by adding the <code>#printLandscape</code> attribute to it (see&nbsp;<a class="reference-link" href="#root/9QRytp0ZYFIf/PnO38wN0ffOA">[missing note]</a>).</p><h2>Page size</h2><p>By default, the resulting PDF will be in Letter format. It is possible to adjust it to another page size via the <code>#printPageSize</code> attribute, with one of the following values: <code>A0</code>, <code>A1</code>, <code>A2</code>, <code>A3</code>, <code>A4</code>, <code>A5</code>, <code>A6</code>, <code>Legal</code>, <code>Letter</code>, <code>Tabloid</code>, <code>Ledger</code>.</p><h2>Keyboard shortcut</h2><p>It's possible to trigger the export to PDF from the keyboard by going to&nbsp;<i>Keyboard shortcuts</i>&nbsp;and assigning a key combination for the <code>exportAsPdf</code> action.</p></div></div>


blobId: 5Xcr03kwoHywlWvCTX1d
dateModified: 2025-03-09 23:10:48.332+0200
utcDateModified: 2025-03-09 21:10:48.344Z
content:
  <div class="content">
         

        <div class="ck-content">
          <p>Trilium now has basic support for right-to-left text, at note level.</p>
          <figure
          class="table">
            <table>
              <tbody>
                <tr>
                  <td>
                    <figure class="image">
                      <img style="aspect-ratio:906/557;" src="api/attachments/ymQtFSsXd1oI/image/3_Right-to-left text notes_i.png"
                      width="906" height="557">
                    </figure>
                  </td>
                  <td>
                    <figure class="image">
                      <img style="aspect-ratio:906/557;" src="api/attachments/ew1HT9ASFqKK/image/2_Right-to-left text notes_i.png"
                      width="906" height="557">
                    </figure>
                  </td>
                </tr>
              </tbody>
            </table>
            </figure>
            <p>Note that only the Text note type supports this.</p>
            <p>The list of languages is configurable via the a new dedicated settings
              page:</p>
            <figure class="image">
              <img style="aspect-ratio:1248/635;" src="api/attachments/v9RoaLqqJ7TP/image/4_Right-to-left text notes_i.png"
              width="1248" height="635">
            </figure>
            <p>To select the corresponding language of the text, go to “Basic Properties”
              and select your desired language.</p>
            <p>
              <img src="api/attachments/BDXJ5onnbvo8/image/1_Right-to-left text notes_i.png" width="635" height="492">
            </p>
            <p>Feel free to report any issues regarding right to left support.</p>
            <p>&nbsp;</p>
        </div>
      </div>


blobId: Ivlg4zoOyWC5xgmJlJEf
dateModified: 2025-03-09 23:13:14.587+0200
utcDateModified: 2025-03-09 21:13:14.588Z
content:
  <ul class="todo-list"><li><label class="todo-list__label"><input type="checkbox" checked="checked" disabled="disabled"><span class="todo-list__label__description">Integrate titles of the notes</span></label></li><li><label class="todo-list__label"><input type="checkbox" checked="checked" disabled="disabled"><span class="todo-list__label__description">Set <code>#shareAlias</code> for all the notes</span></label></li><li><label class="todo-list__label"><input type="checkbox" checked="checked" disabled="disabled"><span class="todo-list__label__description">Recreate structure of notes</span></label></li><li><label class="todo-list__label"><input type="checkbox" checked="checked" disabled="disabled"><span class="todo-list__label__description">Add icons to the notes</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Merge images into their corresponding notes</span></label></li><li><label class="todo-list__label"><input type="checkbox" checked="checked" disabled="disabled"><span class="todo-list__label__description">Review and delete each note from Pikapod</span></label></li></ul><h2>Content changes</h2><ul class="todo-list"><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description"><a class="reference-link" href="#root/krkLW8AwcYf2/poXkQfguuA0U">Desktop Installation</a></span></label><ul class="todo-list"><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Mention Windows installation.</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Integrate Fedora documentation</span></label></li></ul></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description"><a class="reference-link" href="#root/krkLW8AwcYf2/Hdf1kG6Kvcl1">Link map</a>&nbsp;– it's empty</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description"><a class="reference-link" href="#root/krkLW8AwcYf2/QEAPj01N5f7w">Links</a>&nbsp;- extremely old GIFs.</span></label></li><li><label class="todo-list__label"><input type="checkbox" checked="checked" disabled="disabled"><span class="todo-list__label__description">Broken images</span></label><ul class="todo-list"><li><label class="todo-list__label"><input type="checkbox" checked="checked" disabled="disabled"><span class="todo-list__label__description"><a class="reference-link" href="#root/krkLW8AwcYf2/l0tKav7yLHGF">Day Notes</a></span></label></li><li><label class="todo-list__label"><input type="checkbox" checked="checked" disabled="disabled"><span class="todo-list__label__description"><a class="reference-link" href="#root/krkLW8AwcYf2/VbjZvtUek0Ln">Theme Gallery</a></span></label></li><li><label class="todo-list__label"><input type="checkbox" checked="checked" disabled="disabled"><span class="todo-list__label__description"><a class="reference-link" href="#root/krkLW8AwcYf2/9sRHySam5fXb">Workspace</a></span></label></li></ul></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Check for <code>%%{WARNING}%%.</code>.</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Integrate&nbsp;<a class="reference-link" href="#root/x1DxoyI27DXY/MGHZEjw7PAIZ">Syntax highlighting &amp; word wrapping for code blocks</a>&nbsp;into documentation.</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Document each note type</span></label><ul class="todo-list"><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Text</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Code</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Saved Search</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Relation Map</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Note Map</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Render Note</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Book</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Mermaid Diagram</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Canvas</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Web View</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Mind Map</span></label></li><li><label class="todo-list__label"><input type="checkbox" checked="checked" disabled="disabled"><span class="todo-list__label__description">Geo Map</span></label></li></ul></li></ul><h2>Generic improvements</h2><ul class="todo-list"><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Add some promoted attributes for when the page was last reviewed.</span></label></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Document&nbsp;<a class="reference-link" href="#root/xegaRGkDMfkv/ivYnonVFBxbQ">Bulk actions</a>.</span></label></li></ul><h2>Development improvements</h2><ul class="todo-list"><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">Integrate <a href="https://trilium.rocks/xecUJ8eL3pvM">Trilium Rocks theme</a>.</span></label></li></ul>


blobId: d26NGsOJtOGkHusNXuKM
dateModified: 2025-03-09 23:14:04.971+0200
utcDateModified: 2025-03-09 21:14:04.975Z
content:
  <div class="content">
         

        <div class="ck-content">
          <div class="content">
            <div class="ck-content">
              <p> </p>
              <figure class="table">
                <table>
                  <tbody>
                    <tr>
                      <td>
                        <p> </p>
                        <figure class="image">
                          <img src="api/attachments/COuDmnEKWg1k/image/Custom CSS_image.png" />
                        </figure>
                      </td>
                      <td>Start by creating a new note and changing the note type to CSS</td>
                    </tr>
                    <tr>
                      <td>
                        <p> </p>
                        <figure class="image">
                          <img src="api/attachments/ofbMkZwJG1JG/image/1_Custom CSS_image.png" />
                        </figure>
                      </td>
                      <td>In the ribbon, press the “Owned Attributes” section and type <code>#appCss</code>.</td>
                    </tr>
                    <tr>
                      <td>
                        <figure class="image">
                          <img src="api/attachments/lc4T5IlH0cof/image/2_Custom CSS_image.png" />
                        </figure>
                      </td>
                      <td>
                        <p>Type the desired CSS.</p>
                        <p>Generally it's a good idea to append <code>!important</code> for the styles
                          that are being changed, in order to prevent other </p>
                      </td>
                    </tr>
                  </tbody>
                </table>
              </figure>
            </div>
          </div>
        </div>
      </div>


blobId: u2lNB6ZmrWhYRoY55eKg
dateModified: 2025-03-09 23:14:08.309+0200
utcDateModified: 2025-03-09 21:14:08.312Z
content:
  <div><div><p>It is possible to provide a CSS file to be used regardless of the theme set by the user.</p><figure class="table"><table><tbody><tr><td><p>&nbsp;</p><figure class="image"><img style="aspect-ratio:281/273;" src="api/attachments/fkMLaf6reA6I/image/Custom CSS_image.png" width="281" height="273"></figure></td><td>Start by creating a new note and changing the note type to CSS</td></tr><tr><td><p>&nbsp;</p><figure class="image"><img style="aspect-ratio:229/208;" src="api/attachments/TIerrMjmeich/image/1_Custom CSS_image.png" width="229" height="208"></figure></td><td>In the ribbon, press the “Owned Attributes” section and type <code>#appCss</code>.</td></tr><tr><td><figure class="image"><img style="aspect-ratio:300/166;" src="api/attachments/YUrNq5vsCwHe/image/2_Custom CSS_image.png" width="300" height="166"></figure></td><td><p>Type the desired CSS.</p><p>Generally it's a good idea to append <code>!important</code> for the styles that are being changed, in order to prevent other&nbsp;</p></td></tr></tbody></table></figure><h2>Seeing the changes</h2><p>Adding a new <i>app CSS note </i>or modifying an existing one does not immediately apply changes. To see the changes, press Ctrl+Shift+R to refresh the page first.</p><h2>Example use-case: customizing the printing stylesheet</h2><p>When printing a document or exporting as PDF, it is possible to adjust the style by creating a CSS note that uses the <code>@media</code> selector.</p><p>For example, to change the font of the document from the one defined by the theme or the user to a serif one:</p><pre><code class="language-text-x-trilium-auto">@media print {

  	body {

          --main-font-family: serif !important;

          --detail-font-family: var(--main-font-family) !important;

      }

  }</code></pre><p>&nbsp;</p></div></div>


blobId: NclVuQqfogftHcZtKLP1
dateModified: 2025-03-09 23:15:34.960+0200
utcDateModified: 2025-03-09 21:15:34.961Z
content:
  <div><div><div><div><p>Trilium supports Mermaid, which adds support for various diagrams such as flowchart, sequence diagram, class diagram, state diagram, pie charts, etc., all using a text description of the chart instead of manually drawing the diagram.</p><p>For the official documentation of Mermaid.js see <a href="https://mermaid.js.org/intro/">mermaid.js.org/intro/</a>.</p><h2>ELK layout engine</h2><p>Mermaid supports a different layout engine which supports slightly more complex diagrams, called the <a href="https://eclipse.dev/elk/">Eclipse Layout Kernel (ELK)</a>. Trilium has support for these as well, but it's not enabled by default.</p><p>In order to activate ELK for any diagram, insert the following YAML frontmatter right at the beginning of the diagram:</p><pre><code class="language-text-x-yaml">---
  config:
    layout: elk
  ---</code></pre><figure class="table" style="width:920px;"><table><thead><tr><th>With ELK off</th><th>With ELK on</th></tr></thead><tbody><tr><td><figure class="image image_resized" style="width:100%;"><img src="api/images/r44dpvA1xFu8/ELK off.txt"></figure></td><td><figure class="image image_resized" style="width:100%;"><img src="api/images/opAFABmyb3CU/ELK on.txt"></figure></td></tr></tbody></table></figure></div></div></div></div>


blobId: zkXurgphbHbKJtA1eRFZ
dateModified: 2025-03-09 23:18:48.549+0200
utcDateModified: 2025-03-09 21:18:48.550Z
content:
  <p>Trilium utilizes the powerful <a href="https://ckeditor.com/ckeditor-5/">CKEditor 5</a> as its text editing component.</p><h2>Formatting Options</h2><p>The Trilium text note interface does not display toolbars or formatting options by default. These can be accessed by:</p><p><img src="api/images/FtmPLgGmgZVC/text-notes-formatting-inline.png" alt="inline note formatting"></p><ol><li>Selecting text to bring up an inline toolbar.</li></ol><p><img src="api/images/oRWfJLUbb7j7/text-notes-formatting-block.png" alt="formating note block"> 2. Clicking on the block toolbar.</p><h2>Read-Only vs. Editing Mode</h2><p>Text notes are usually opened in edit mode. However, they may open in read-only mode under the following circumstances:</p><ul><li>The note is long and would take time to load, so it is opened in read-only mode by default for quicker access.</li><li>The note has a <code>readOnly</code> <a href="#root/zEY4DaJG4YT5">label</a>.</li></ul><p>In both cases, it is possible to switch back to editable mode using [Edit note] <img src="api/images/hKNMMxsbCuE8/bx-edit-alt.svg" alt="edit-alt icon"> at top right of page.</p><p>For more information, see&nbsp;<a class="reference-link" href="#root/BFs8mudNFgCS/CoFPLs3dRlXc">Read-Only Notes</a>.</p><h2>General Formatting</h2><p>Since Trilium uses CKEditor, all of its formatting options are available here. You may use the graphical toolbar shown above, or enter formatting such as markdown markdown directly in the text. Examples include:</p><ul><li><strong>Bold</strong>: Type <code>**text**</code> or <code>__text__</code></li><li><i>Italic</i>: Type <code>*text*</code> or <code>_text_</code></li><li><code>Code</code>: Type `text`</li><li><s>Strikethrough</s>: Type <code>~~text~~</code></li></ul><h3>Lists</h3><ul><li>Bulleted list: Start a line with <code>*</code> or <code>-</code> followed by a space</li><li>Numbered list: Start a line with <code>1.</code> or <code>1)</code> followed by a space</li><li>To-do list: Start a line with <code>[ ]</code> for an unchecked item or <code>[x]</code> for a checked item</li></ul><h3>Blocks</h3><ul><li>Block quote: Start a line with <code>&gt;</code> followed by a space</li></ul><h3>Multi-Line Code Blocks</h3><p>To create a multi-line code block, start a line with "```[lang]", for example:</p><pre><code class="language-text-x-trilium-auto">if (1 &gt; 2) {
      console.log("Error in the matrix");
  }</code></pre><h3>Headings</h3><p>Create headings by starting a line with <code>##</code> for heading 2, <code>###</code> for heading 3, and so on up to heading 6. Note that <code>#</code> is reserved for the title.</p><h3>Horizontal Line</h3><p>Insert a horizontal line by starting a line with <code>---</code>.</p><h2>Markdown &amp; Autoformat</h2><p>CKEditor supports a markdown-like editing experience, recognizing syntax and automatically converting it to rich text.</p><p>Complete documentation for this feature is available in the <a href="https://ckeditor.com/docs/ckeditor5/latest/features/autoformat.html">CKEditor documentation</a>.</p><p>If autoformatting is not desirable, press <code>CTRL-Z</code> to revert the text to its original form.</p><p>Note: The use of <code>#</code> for Heading 1 is not supported because it is reserved for the title. Start with <code>##</code> for Heading 2. More information is available <a href="https://ckeditor.com/docs/ckeditor5/latest/features/headings.html#heading-levels">here</a>.</p><h2>Math Support</h2><p>Trilium provides math support through <a href="https://katex.org/">KaTeX</a>.</p><h2>Cutting Selection to Sub-Note</h2><p>When editing a document that becomes too large, you can split it into sub-notes:</p><ol><li>Select the desired text and cut it to the clipboard.</li><li>Create a new sub-note and name it.</li><li>Paste the content from the clipboard into the sub-note.</li></ol><p>Trilium can automate this process. Select some text within the note, and in the selection toolbar, click the scissors icon for the "cut &amp; pasted selection to sub-note" action. The heading is automatically detected and the new sub-note is named accordingly. You can also assign a keyboard shortcut for this action. This functionality is available through the block toolbar icon.</p><h2>Including a Note</h2><p>Text notes can "include" another note as a read only widget. This can be useful for e.g. including a dynamically generated chart (from scripts &amp; "render HTML" note) or other more advanced use cases.</p><p>This functionality is available in the block toolbar icon.</p>


blobId: YIx8owZUVgdDxNBEP4cB
dateModified: 2025-03-09 23:20:46.727+0200
utcDateModified: 2025-03-09 21:20:46.729Z
content:
  <p>As Trilium is currently in beta, encountering bugs is to be expected.</p><h2>General Quick Fix</h2><p>The first step in troubleshooting is often a restart.</p><p>If you experience an UI issue, the frontend may have entered an inconsistent state. Reload the application by pressing <code>CTRL-R</code>. This will reload the frontend.</p><p>If the issue persists or appears to be a backend problem, restart the entire application. For the desktop (Electron) build, simply close and reopen the window. If you're using a Docker build, restart the container.</p><h2>Broken Note Crashes Trilium</h2><p>Certain problems, such as rendering a note with a faulty script, can cause Trilium to crash. If Trilium attempts to reload the problematic note upon restart, it will continue to crash.</p><p>To resolve this, use the <code>TRILIUM_START_NOTE_ID</code> environment variable to reset the open tabs to a single specified note ID (e.g., <code>root</code>). In Linux, you can set it as follows:</p><pre><code class="language-text-x-trilium-auto">TRILIUM_START_NOTE_ID=root ./trilium</code></pre><h2>Broken Script Prevents Application Startup</h2><p>If a custom script causes Triliumto crash, and it is set as a startup script or in an active <a href="#root/MgibgPcfeuGz">custom widget</a>, start Triliumin "safe mode" to prevent any custom scripts from executing:</p><pre><code class="language-text-x-trilium-auto">TRILIUM_SAFE_MODE=true ./trilium</code></pre><p>Depending on your Trilium distribution, you may have pre-made scripts available: <code>trilium-safe-mode.bat</code> and <code>trilium-safe-mode.sh</code>.</p><p>Once Trilium starts, locate and fix or delete the problematic note.</p><h2>Sync and Consistency Checks</h2><p>Trilium periodically verifies the logical consistency of the database (e.g., ensuring every note has a parent). If inconsistencies are detected, you will be notified via the UI.</p><p>In such cases, file a bug report and attach an <a href="#root/x59R8J8KV5Bp">anonymized database</a> if necessary.</p><h2>Restoring Backup</h2><p>Trilium makes regular automatic backups. If issues become severe, you can <a href="#root/ODY7qQn5m2FT">restore from a backup</a>.</p><h2>Forgotten Password</h2><p>If you forget your password:</p><ul><li>Protected notes are irretrievable without the password.</li><li>Unprotected notes can be recovered. Follow these steps:</li></ul><p>Access the <a href="#root/wX4HbRucYSDD">database</a> file in the <a href="#root/tAassRL4RSQL">data directory</a>. Open the <code>document.db</code> file with an SQLite client (e.g., <a href="https://sqlitebrowser.org/">DB Browser</a>) and execute the following queries:</p><pre><code class="language-text-x-trilium-auto">UPDATE options SET value = '77/twC5O00cuQgNC63VK32qOKKYwj21ev3jZDXoytVU=' WHERE name = 'passwordVerificationSalt';
  UPDATE options SET value = '710BMasZCAgibzIc07X4P9Q4TeBd4ONnqJOho+pWcBM=' WHERE name = 'passwordDerivedKeySalt';
  UPDATE options SET value = 'Eb8af1/T57b89lCRuS97tPEl4CwxsAWAU7YNJ77oY+s=' WHERE name = 'passwordVerificationHash';
  UPDATE options SET value = 'QpC8XoiYYeqHPtHKRtbNxfTHsk+pEBqVBODYp0FkPBa22tlBBKBMigdLu5GNX8Uu' WHERE name = 'encryptedDataKey';</code></pre><p>After executing the changes, commit/write the changes. <strong>This sets the password to "password," allowing you to log in again.</strong></p><p>For pre-existing protected notes (now unrecoverable), consider deleting them or exporting the unprotected notes. Then, delete <code>document.db</code> and start fresh.</p><p>If you continue using the existing document file, change your password (Options -&gt; Change Password).</p><h2>Reporting Bugs</h2><p>Reporting bugs is highly valuable. Here are some tips:</p><ul><li>Use GitHub issues for reporting: <a href="https://github.com/TriliumNext/Notes/issues">https://github.com/TriliumNext/Notes/issues</a></li><li>Refer to the <a href="#root/qzNzp9LYQyPT">error logs</a> page for information on providing necessary details.</li></ul>


blobId: jqxhK4h4ks3Fhe62F2c9
dateModified: 2025-03-09 23:23:16.460+0200
utcDateModified: 2025-03-09 21:23:16.464Z
content:
  <p>Sometimes the fastest way to assess the software is just through screenshots so here they are:</p><p><img src="api/images/V01a3OdC9O06/screenshot.png" alt=""></p><p><img src="api/images/zaQnUsJTbvjr/dark-theme.png" alt=""></p><p>See <a href="#root/Wy267RK4M69c">Themes</a>.</p><p><img src="api/images/8jgXl1RUGL4H/code-note.png" alt=""></p><p>This shows <a href="#root/6f9hih2hXXZk">code note</a> editor.</p><p><img src="api/images/umjOUcnZi4z2/promoted-attributes-queen.png" alt=""></p><p>See <a href="#root/OFXdgB2nNk1F">promoted attributes</a></p><p><img src="api/images/xeZPrfi77XPu/relation-map-family.png" alt=""></p><p>See <a href="#root/iRwzGnHPzonm">relation map</a>.</p><p><img src="api/images/5nE2aM3crNI6/link-map.png" alt=""></p><p>See <a href="#root/Hdf1kG6Kvcl1">link map</a>.</p><figure class="image"><img style="aspect-ratio:1060/758;" src="api/attachments/qzFGC9mctJ4M/image/image.png" width="1060" height="758"></figure><p>See <a href="#root/l0tKav7yLHGF">Day notes</a>.</p><p><img src="api/images/PFrpANAUte0M/weight-tracker.png" alt=""></p><p>See <a href="#root/R7abl2fc6Mxi">Weight tracker</a>.</p><p><img src="api/images/92KeXdKh3Ca1/task-manager.png" alt=""></p><p>See <a href="#root/xYjQUYhpbUEW">Task manager</a>.</p><p><img src="api/images/MA2uvkVloWXl/note-revisions.png" alt=""></p><p>See <a href="#root/vZWERwf8U3nx">Note revisions</a>.</p><p><img src="api/images/TFAiJIXJFfqv/mobile-smartphone.png" alt=""></p><p><img src="api/images/fi37V32TNyzm/mobile-tablet.png" alt=""></p><p>See <a href="#root/RDslemsQ6gCp">Mobile frontend</a>.</p>


blobId: ILXmil95QGuCzZU5xYq2
dateModified: 2025-03-09 23:23:22.484+0200
utcDateModified: 2025-03-09 21:23:22.486Z
content:
  <p>Sometimes the fastest way to assess the software is just through screenshots so here they are:</p><p><img src="api/images/V01a3OdC9O06/screenshot.png" alt=""></p><p><img src="api/images/zaQnUsJTbvjr/dark-theme.png" alt=""></p><p>See <a href="#root/Wy267RK4M69c">Themes</a>.</p><p><img src="api/images/8jgXl1RUGL4H/code-note.png" alt=""></p><p>This shows <a href="#root/6f9hih2hXXZk">code note</a> editor.</p><p><img src="api/images/umjOUcnZi4z2/promoted-attributes-queen.png" alt=""></p><p>See <a href="#root/OFXdgB2nNk1F">promoted attributes</a></p><p><img src="api/images/xeZPrfi77XPu/relation-map-family.png" alt=""></p><p>See <a href="#root/iRwzGnHPzonm">relation map</a>.</p><p><img src="api/images/5nE2aM3crNI6/link-map.png" alt=""></p><p>See&nbsp;<a class="reference-link" href="#root/KSZ04uQ2D1St/bdUJEHsAPYQR">Note Map</a>.</p><figure class="image"><img style="aspect-ratio:1060/758;" src="api/attachments/aladsLQ9qJGS/image/image.png" width="1060" height="758"></figure><p>See <a href="#root/l0tKav7yLHGF">Day notes</a>.</p><p><img src="api/images/PFrpANAUte0M/weight-tracker.png" alt=""></p><p>See <a href="#root/R7abl2fc6Mxi">Weight tracker</a>.</p><p><img src="api/images/92KeXdKh3Ca1/task-manager.png" alt=""></p><p>See <a href="#root/xYjQUYhpbUEW">Task manager</a>.</p><p><img src="api/images/MA2uvkVloWXl/note-revisions.png" alt=""></p><p>See <a href="#root/vZWERwf8U3nx">Note revisions</a>.</p><p><img src="api/images/TFAiJIXJFfqv/mobile-smartphone.png" alt=""></p><p><img src="api/images/fi37V32TNyzm/mobile-tablet.png" alt=""></p><p>See <a href="#root/RDslemsQ6gCp">Mobile frontend</a>.</p>


blobId: DzXC4IJYWIQzMwTUVwcn
dateModified: 2025-03-09 23:24:21.360+0200
utcDateModified: 2025-03-09 21:24:21.362Z
content:
  <p>Trilium supports configuration via a file named <code>config.ini</code> and environment variables. Please review the file named <a href="https://github.com/TriliumNext/Notes/blob/develop/config-sample.ini">config-sample.ini</a> in the <a href="https://github.com/TriliumNext/Notes">Notes</a> repository to see what values are supported.</p><p>You can provide the same values via environment variables instead of the <code>config.ini</code> file, and these environment variables use the following format:</p><ol><li>Environment variables should be prefixed with <code>TRILIUM_</code> and use underscores to represent the INI section structure.</li><li>The format is: <code>TRILIUM_&lt;SECTION&gt;_&lt;KEY&gt;=&lt;VALUE&gt;</code></li><li>The environment variables will override any matching values from config.ini</li></ol><p>For example, if you have this in your config.ini:</p><pre><code class="language-text-x-trilium-auto">[Network]
  host=localhost
  port=8080</code></pre><p>You can override these values using environment variables:</p><pre><code class="language-text-x-sh">TRILIUM_NETWORK_HOST=0.0.0.0
  TRILIUM_NETWORK_PORT=9000</code></pre><p>The code will:</p><ol><li>First load the <code>config.ini</code> file as before</li><li>Then scan all environment variables for ones starting with <code>TRILIUM_</code></li><li>Parse these variables into section/key pairs</li><li>Merge them with the config from the file, with environment variables taking precedence</li></ol>


blobId: FVvFLzPWHTgEJqL3HKlr
dateModified: 2025-03-09 23:25:39.502+0200
utcDateModified: 2025-03-09 21:25:39.515Z
content:
  <div class="content">
         

        <div class="ck-content">
          <figure class="image image-style-align-right image_resized">
            <img src="api/attachments/EgZajhB7c3Yg/image/TriliumNext Notes Not Open.png" />
          </figure>
          <p>When running TriliumNext for the first time or updating to a newer version,
            macOS will prevent its execution.</p>
          <p>On older versions of macOS it was possible to bypass this step simply
            by right clicking and selecting Open, which would show a button to run
            anyway. This got removed since macOS 15.0.</p>
          <p>To bypass this issue, follow these steps:</p>
          <ol>
            <li>Go to System Settings → Privacy &amp; Security and look for the “Security”
              section.</li>
            <li>There should be a “TriliumNext Notes was blocked to protect your Mac”
              item. Simply click “Open Anyway”.</li>
            <li>Select “Open Anyway” and proceed with the authentication. Afterwards the
              application should start on its own.</li>
          </ol>
          <figure class="table" style="width:100%">
            <table class="ck-table-resized">
              <colgroup>
                <col></col>
                  <col></col>
              </colgroup>
              <tbody>
                <tr>
                  <td>
                    <figure class="image">
                      <img src="api/attachments/GTnYXPb1F9g0/image/2_TriliumNext Notes Not Open.png" />
                      <figcaption>The privacy settings in “System Settings”, showing the alert that TriliumNext
                        was blocked.</figcaption>
                    </figure>
                  </td>
                  <td>
                    <p> </p>
                    <figure class="image image_resized">
                      <img src="api/attachments/O8zDs6xvdvIZ/image/1_TriliumNext Notes Not Open.png" />
                      <figcaption>The confirmation screen to bypass the run restrictions.</figcaption>
                    </figure>
                  </td>
                </tr>
              </tbody>
            </table>
          </figure>
        </div>
      </div>


blobId: k1TXrzXAfA7a8wa9rMCd
dateModified: 2025-03-09 23:26:14.429+0200
utcDateModified: 2025-03-09 21:26:14.435Z
content:
  <div><div><p>&nbsp;</p><p>When running TriliumNext for the first time or updating to a newer version, macOS will prevent its execution.</p><p>On older versions of macOS it was possible to bypass this step simply by right clicking and selecting Open, which would show a button to run anyway. This got removed since macOS 15.0.</p><p>To bypass this issue, follow these steps:</p><ol><li>Go to System Settings → Privacy &amp; Security and look for the “Security” section.</li><li>There should be a “TriliumNext Notes was blocked to protect your Mac” item. Simply click “Open Anyway”.</li><li>Select “Open Anyway” and proceed with the authentication. Afterwards the application should start on its own.</li></ol><figure class="table" style="width:100%;"><table class="ck-table-resized"><colgroup><col style="width:50%;"><col style="width:50%;"></colgroup><tbody><tr><td><figure class="image"><img src="api/attachments/OVes4YwxlP8W/image/2_TriliumNext Notes Not Open.png"><figcaption>The privacy settings in “System Settings”, showing the alert that TriliumNext was blocked.</figcaption></figure></td><td><p>&nbsp;</p><figure class="image"><img src="api/attachments/DTGyBgy4VEZB/image/1_TriliumNext Notes Not Open.png"><figcaption>The confirmation screen to bypass the run restrictions.</figcaption></figure></td></tr></tbody></table></figure></div></div>


blobId: 4wkh5DjkfeIEWO2NCKTJ
dateModified: 2025-03-09 23:26:14.429+0200
utcDateModified: 2025-03-09 21:26:14.443Z
content:
  <div class="content">
         

        <div class="ck-content">
          <figure class="image image-style-align-right image_resized">
            <img src="api/attachments/QuuFBSQMTz05/image/TriliumNext Notes Not Open.png" />
          </figure>
          <p>When running TriliumNext for the first time or updating to a newer version,
            macOS will prevent its execution.</p>
          <p>On older versions of macOS it was possible to bypass this step simply
            by right clicking and selecting Open, which would show a button to run
            anyway. This got removed since macOS 15.0.</p>
          <p>To bypass this issue, follow these steps:</p>
          <ol>
            <li>Go to System Settings → Privacy &amp; Security and look for the “Security”
              section.</li>
            <li>There should be a “TriliumNext Notes was blocked to protect your Mac”
              item. Simply click “Open Anyway”.</li>
            <li>Select “Open Anyway” and proceed with the authentication. Afterwards the
              application should start on its own.</li>
          </ol>
          <figure class="table" style="width:100%">
            <table class="ck-table-resized">
              <colgroup>
                <col></col>
                  <col></col>
              </colgroup>
              <tbody>
                <tr>
                  <td>
                    <figure class="image">
                      <img src="api/attachments/sSEXTY7mQ3Cx/image/2_TriliumNext Notes Not Open.png" />
                      <figcaption>The privacy settings in “System Settings”, showing the alert that TriliumNext
                        was blocked.</figcaption>
                    </figure>
                  </td>
                  <td>
                    <p> </p>
                    <figure class="image image_resized">
                      <img src="api/attachments/sC4ORfLsTFhF/image/1_TriliumNext Notes Not Open.png" />
                      <figcaption>The confirmation screen to bypass the run restrictions.</figcaption>
                    </figure>
                  </td>
                </tr>
              </tbody>
            </table>
          </figure>
        </div>
      </div>


blobId: Zr5qihPOsZ9cw1dlXQYj
dateModified: 2025-03-10 11:04:21.215+0200
utcDateModified: 2025-03-10 09:04:21.217Z
content:
  <p>There are some situations where modifying the SQLite database that Trilium uses is desirable.</p><h2>Modifying it internally using the SQL Console</h2><p>The SQL Console is Trilium's built-in database editor.</p><p>It can be accessed by going to the <a href="#root/pOsGYCXsbNQG/gh7bpGYxajRS/Vc8PjrjAGuOp">global menu</a>&nbsp;</p><figure class="image"><img style="aspect-ratio:1301/287;" src="api/attachments/NM6wQU6kLR0D/image/image.png" width="1301" height="287"></figure><h2>Externally modifying the database</h2><h2>Using DB Browser for SQLite</h2><p>DB Browser for SQLite is a cross-platform editor that can be used to alter the database using a graphical user interface.</p><figure class="image"><img style="aspect-ratio:1186/1130;" src="api/attachments/J4qMYs4xGl1Z/image/image.png" width="1186" height="1130"></figure>


blobId: HCDBOAfqAgZ6vONvRSwQ
dateModified: 2025-03-10 11:14:18.120+0200
utcDateModified: 2025-03-10 09:14:18.120Z
content:
  <p>Synchronization can sometimes take a long amount of time in order to compute the items that require update. When running behind a reverse proxy, the request can time out.</p><p>The solution is to increase the timeout at proxy level.</p><h2>Nginx</h2><p>Add the following to the configuration file:</p><pre><code class="language-text-x-nginx-conf">proxy_connect_timeout 300;
  proxy_send_timeout 300;
  proxy_read_timeout 300;
  send_timeout 300;</code></pre><p>And restart the server.</p><p>See&nbsp;<a class="reference-link" href="#root/WOcw2SLH6tbX/ud6MShXL4WpO">Nginx Proxy Setup</a>&nbsp;for more information about the Nginx setup.</p><p>If it still doesn't work, try increasing the timeout.</p>


blobId: TdGwMCIoAtykA2nxrJII
dateModified: 2025-03-10 11:15:35.516+0200
utcDateModified: 2025-03-10 09:15:35.516Z
content:
  <p>Configure Nginx proxy and HTTPS. The operating system here is Ubuntu 18.04.</p><ol><li>Download Nginx and remove Apache2</li></ol><pre><code class="language-text-x-sh">sudo apt-get install nginx
  sudo apt-get remove apache2</code></pre><ol start="2"><li>Create configure file</li></ol><pre><code class="language-text-x-sh">cd /etc/nginx/conf.d
  vim default.conf</code></pre><ol start="3"><li>Fill the file with the context shown below, part of the setting show be changed. Then you can enjoy your web with HTTPS forced and proxy.</li></ol><pre><code class="language-text-x-nginx-conf"># This part is for proxy and HTTPS configure
  server {
      listen 443 ssl;
      server_name trilium.example.net; #change trilium.example.net to your domain without HTTPS or HTTP.
      ssl_certificate /etc/ssl/note/example.crt; #change /etc/ssl/note/example.crt to your path of crt file.
      ssl_certificate_key /etc/ssl/note/example.net.key; #change /etc/ssl/note/example.net.key to your path of key file.
      ssl_session_cache builtin:1000 shared:SSL:10m;
      ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
      ssl_ciphers HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4;
      ssl_prefer_server_ciphers on;
      access_log /var/log/nginx/access.log; #check the path of access.log, if it doesn't fit your file, change it
      
      location / {
          proxy_set_header Host $host;
          proxy_set_header X-Real-IP $remote_addr;
          proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
          proxy_set_header X-Forwarded-Proto $scheme;
          proxy_set_header Upgrade $http_upgrade;
          proxy_set_header Connection "upgrade";
          proxy_pass http://127.0.0.1:8080; # change it to a different port if non-default is used
          proxy_read_timeout 90;
          proxy_redirect http://127.0.0.1:8080 https://trilium.example.net; # change them based on your IP, port and domain
      }
  }
  # This part is for HTTPS forced
  server {
              listen 80;
              server_name trilium.example.net; # change to your domain
              return 301 https://$server_name$request_uri;
  }</code></pre>


blobId: KKhP7XXIHxsCKnz5nFHA
dateModified: 2025-03-10 11:19:18.175+0200
utcDateModified: 2025-03-10 09:19:18.176Z
content:
  <p><span style="color:hsl(0, 75%, 60%);"><strong>Note: This feature has not been merged yet, so it is not available.</strong></span></p><p>Multi-factor authentication (MFA) is a security process that requires users to provide two or more verification factors to gain access to a system, application, or account. This adds an extra layer of protection beyond just using a password.</p><p>By requiring more than one verification method, MFA helps reduce the risk of unauthorized access, even if someone has obtained your password. It’s highly recommended for securing sensitive information stored in your notes.</p><p>Warning! OpenID and TOTP cannot be both used at the same time!</p><h2>Log in with your Google Account with OpenID!</h2><p>OpenID is a standardized way to let you log into websites using an account from another service, like Google, to verify your identity.</p><h2>Why Time-based One Time Passwords?</h2><p>TOTP (Time-Based One-Time Password) is a security feature that generates a unique, temporary code on your device, like a smartphone, which changes every 30 seconds. You use this code, along with your password, to log into your account, making it much harder for anyone else to access them.</p><h2>Setup</h2><h3>TOTP</h3><ol><li>Start Trilium Notes normally.</li><li>Go to "Menu" -&gt; "Options" -&gt; "MFA"</li><li>Click the "Generate TOTP Secret" button</li><li>Copy the generated secret to your authentication app/extension</li><li><p>Set an environment variable "TOTP_SECRET" as the generated secret. Environment variables can be set with a .env file in the root directory, by defining them in the command line, or with a docker container.</p><pre><code class="language-text-x-trilium-auto"># .env in the project root directory
  TOTP_ENABLED="true"
  TOTP_SECRET="secret"</code></pre><pre><code class="language-text-x-trilium-auto"># Terminal/CLI
  export TOTP_ENABLED="true"
  export TOTP_SECRET="secret"</code></pre><pre><code class="language-text-x-trilium-auto"># Docker
  docker run -p 8080:8080 -v ~/trilium-data:/home/node/trilium-data -e TOTP_ENABLED="true" -e TOTP_SECRET="secret" triliumnext/notes:[VERSION]</code></pre></li><li>Restart Trilium</li><li>Go to "Options" -&gt; "MFA"</li><li>Click the "Generate Recovery Codes" button</li><li>Save the recovery codes. Recovery codes can be used once in place of the TOTP if you loose access to your authenticator. After a rerecovery code is used, it will show the unix timestamp when it was used in the MFA options tab.</li><li>Load the secret into an authentication app like google authenticator</li></ol><h3>OpenID</h3><p><i>Currently only compatible with Google. Other services like Authentik and Auth0 are planned on being added.</i></p><p>In order to setup OpenID, you will need to setup a authentication provider. This requires a bit of extra setup. Follow <a href="https://developers.google.com/identity/openid-connect/openid-connect">these instructions</a> to setup an OpenID service through google.</p><p>Set an environment variable "SSO_ENABLED" to true and add the client ID and secret you obtained from google. Environment variables can be set with a .env file in the root directory, by defining them in the command line, or with a docker container.</p><h4>.env File</h4><pre><code class="language-text-x-trilium-auto"># .env in the project root directory
  SSO_ENABLED="true"
  BASE_URL="http://localhost:8080"
  CLIENT_ID=
  SECRET=</code></pre><h4>Environment variable (linux)</h4><pre><code class="language-text-x-trilium-auto">export SSO_ENABLED="true"
  export BASE_URL="http://localhost:8080"
  export CLIENT_ID=
  export SECRET=</code></pre><h4>Docker</h4><pre><code class="language-text-x-trilium-auto">docker run -d -p 8080:8080 -v ~/trilium-data:/home/node/trilium-data -e SSO_ENABLED="true" -e BASE_URL="http://localhost:8080" -e CLIENT_ID= -e SECRET= triliumnext/notes:[VERSION]</code></pre><p>After you restart Trilium Notes, you will be redirected to Google's account selection page. Login to an account and Trilium Next will bind to that account, allowing you to login with it.</p><p>You can now login using your google account.</p>


blobId: cGvpJKZg4TtYkd4P3x9G
dateModified: 2025-03-10 11:23:23.260+0200
utcDateModified: 2025-03-10 09:23:23.263Z
content:
  <p>There are some situations where modifying the SQLite database that Trilium uses is desirable.</p><h2>Modifying it internally using the SQL Console</h2><p>The SQL Console is Trilium's built-in database editor.</p><p>It can be accessed by going to the <a href="#root/pOsGYCXsbNQG/gh7bpGYxajRS/Vc8PjrjAGuOp">global menu</a>&nbsp;</p><figure class="image"><img style="aspect-ratio:1301/287;" src="api/attachments/ya2fkBq4bcfk/image/image.png" width="1301" height="287"></figure><h2>Externally modifying the database</h2><h3>Using DB Browser for SQLite</h3><p>DB Browser for SQLite is a cross-platform editor that can be used to alter the database using a graphical user interface.</p><figure class="image"><img style="aspect-ratio:1186/1130;" src="api/attachments/XeKqQ9NtSaRc/image/image.png" width="1186" height="1130"></figure>


blobId: U8100fbZFSzYfMaRlGrT
dateModified: 2025-03-10 11:33:24.033+0200
utcDateModified: 2025-03-10 09:33:24.036Z
content:
  <p>There are some situations where modifying the SQLite database that Trilium uses is desirable.</p><h2>Modifying it internally using the SQL Console</h2><p>&nbsp;</p><h2>Externally modifying the database</h2><p>Sometimes the SQL Console cannot be used t</p><h3>Using DB Browser for SQLite</h3><p>DB Browser for SQLite is a cross-platform editor that can be used to alter the database using a graphical user interface.</p><figure class="image"><img style="aspect-ratio:1186/1130;" src="api/attachments/kJKfng4XptU2/image/image.png" width="1186" height="1130"></figure>


blobId: d35JUXHX61pf4YPvI2bq
dateModified: 2025-03-10 11:36:28.212+0200
utcDateModified: 2025-03-10 09:36:28.212Z
content:
  <p>The SQL Console is Trilium's built-in database editor.</p><p>It can be accessed by going to the <a href="#root/pOsGYCXsbNQG/gh7bpGYxajRS/Vc8PjrjAGuOp">global menu</a> → Advanced → Open SQL Console.</p><figure class="image"><img style="aspect-ratio:1301/287;" src="api/attachments/1YS10Qg7S4YR/image/image.png" width="1301" height="287"></figure><h3>Interaction</h3><ul><li>Hovering the mouse over one of the tables listed at the top of the document will show the columns and their data type.</li><li>Only one SQL statement can be run at once.</li><li>To run the statement, press the <img src="api/attachments/pP87PB9ELjQn/image/image.png" width="17" height="18"> icon.</li><li><p>For queries that return a result, the data will displayed in a table.</p><p><img src="api/attachments/827EgLgWhZWF/image/image.png" width="968" height="272"></p></li></ul><h3>Saved SQL console</h3><p>SQL queries or commands can be saved into a dedicated note.</p><p>To do so, simply write the query and press the <img src="api/attachments/gIbK7NNLu3iZ/image/image.png" width="19" height="19"> button. Once saved, the note will appear in&nbsp;<a class="reference-link" href="#root/5668rwcirq1t/l0tKav7yLHGF">Day Notes</a>.</p><ul><li>The SQL expression will not be displayed by default, but it can still be viewed by going to the note context menu and selecting <i>Note source</i>.</li><li>The expression cannot be modified. If needed, recreate it by copying the statement back into the SQL console and then saving it again.</li></ul>


blobId: yIT1usds1sTmzfJFE662
dateModified: 2025-03-10 11:38:17.818+0200
utcDateModified: 2025-03-10 09:38:17.819Z
content:
  <p>Your Trilium data is stored in a <a href="https://www.sqlite.org">SQLite</a> database which contains all notes, tree structure, metadata, and most of the configuration. The database file is named <code>document.db</code> and is stored in the application's default <a href="#root/tAassRL4RSQL">data directory</a>.</p><h2>Demo Notes</h2><p>When you run Trilium for the first time, it will generate a new database containing demo notes. These notes showcase its many features, such as:</p><ul><li><a href="#root/iRwzGnHPzonm">Relation Map</a></li><li><a href="#root/l0tKav7yLHGF">Day Notes</a></li><li><a href="#root/R7abl2fc6Mxi">Weight Tracker</a></li><li><a href="#root/xYjQUYhpbUEW">Task Manager</a></li><li><a href="#root/Wy267RK4M69c">Custom CSS Themes</a></li></ul><h3>Restoring Demo Notes</h3><p>There are some cases in which you may want to restore the original demo notes. For example, if you experimented with some of the more advanced features and want to see the original reference, or if you simply want to explore the latest version of the demo notes, which might showcase new features.</p><p>You can easily restore the demo notes by using Trilium's built-in import feature by importing them:</p><ul><li>Download <a href="https://github.com/TriliumNext/Notes/raw/develop/db/demo.zip">this .zip archive</a> with the latest version of the demo notes</li><li>Right click on any note in your tree under which you would like the demo notes to be imported</li><li>Click "Import into note"</li><li>Select the .zip archive to import it</li></ul><h2>Manually Modifying the Database</h2><p>Trilium provides a lot of flexibility, and with it, opportunities for advanced users to tweak it. If you need to explore or modify the database directly, you can use a tool such as <a href="https://sqlitebrowser.org/">SQLite Browser</a> to work directly on the database file.</p><p>See&nbsp;<a class="reference-link" href="#root/pOsGYCXsbNQG/tC7s2alapj8V/wX4HbRucYSDD/oyIAJ9PvvwHX">Manually altering the database</a>&nbsp;for more information.</p><p>If you are doing any advanced development or troubleshooting where you manually modify the database, you might want to consider creating backups of your <code>document.db</code> file.</p><h2>How to Reset the Database</h2><p>If you are experimenting with Trilium and want to return it to its original state, you can do that by deleting the current database. When you restart the application, it will generate a new database containing the original demo notes.</p><p>To delete the database, simply go to the <a href="#root/tAassRL4RSQL">data directory</a> and delete the <code>document.db</code> file (and any other files starting with <code>document.db</code>).</p><p>If you do not need to preserve any configurations that might be stored in the <code>config.ini</code> file, you can just delete all of the <a href="#root/tAassRL4RSQL">data directory's</a> contents to fully restore the application to its original state. You can also review the <a href="#root/Gzjqa934BdH4">configuration</a> file to provide all <code>config.ini</code> values as environment variables instead.</p>


blobId: dp8zDml23IkMzYzCTii5
dateModified: 2025-03-10 11:45:10.211+0200
utcDateModified: 2025-03-10 09:45:10.214Z
content:
  <p>There are some situations where modifying the SQLite database that Trilium uses is desirable.</p><p>If you are doing any advanced development or troubleshooting where you manually modify the database, you might want to consider creating backups of your <code>document.db</code> file.</p><h2>Modifying it internally using the SQL Console</h2><p>The SQL Console is Trilium's built-in database editor.</p><p>See&nbsp;<a class="reference-link" href="#root/oyIAJ9PvvwHX/YKWqdJhzi2VY">SQL Console</a>.</p><h2>Externally modifying the database</h2><p>Sometimes the SQL Console cannot be used (for example if the application cannot start).</p><p>When making external modifications, consider closing the desktop application. If modifying the server database, then stop the service or Docker container.</p><h3>Using DB Browser for SQLite</h3><p>DB Browser for SQLite is a cross-platform editor that can be used to alter the database using a graphical user interface.</p><p>To do so:</p><ol><li>In the main menu, select File → Open database… and navigate to the database in the&nbsp;<a class="reference-link" href="#root/Otzi9La2YAUX/tAassRL4RSQL">Data directory</a>.</li><li>Select the <i>Execute SQL</i> tab.</li><li>Type in the desired SQL statement.</li><li>Press the "Play" button in the toolbar underneath the "Execute SQL" tab (or F5 key).</li><li>Press "Write Changes" in the main toolbar.</li><li>Close the application or close the database.</li></ol><figure class="image"><img style="aspect-ratio:1186/1130;" src="api/attachments/izpLGrcsrVRu/image/image.png" width="1186" height="1130"></figure>


blobId: L8fll2V0yWXviFJPRUzx
dateModified: 2025-03-10 11:51:43.474+0200
utcDateModified: 2025-03-10 09:51:43.476Z
content:
  <h2>Global menu</h2><p>The position of the global menu differs based on which layout is selected in settings:</p><ul><li>For the vertical layout, the icon is in the top-left of the screen, in the form of the Trilium icon.</li><li>For the horizontal layout, the icon is in the top-right of the screen, in form of a hamburger menu icon.</li></ul><figure class="table"><table><tbody><tr><td><figure class="image"><img style="aspect-ratio:295/434;" src="api/attachments/uggqVDX70e0K/image/image.png" width="295" height="434"><figcaption>The global menu in the vertical layout.</figcaption></figure></td><td><figure class="image"><img style="aspect-ratio:380/482;" src="api/attachments/w37Mn7Wnjijy/image/image.png" width="380" height="482"><figcaption>The global menu in the horizontal layout.</figcaption></figure></td></tr></tbody></table></figure><p>&nbsp;</p>


blobId: shIkpbHsOeCZNoSXilyq
dateModified: 2025-03-10 11:52:13.401+0200
utcDateModified: 2025-03-10 09:52:13.402Z
content:
  <p>The position of the global menu differs based on which layout is selected in settings:</p><ul><li>For the vertical layout, the icon is in the top-left of the screen, in the form of the Trilium icon.</li><li>For the horizontal layout, the icon is in the top-right of the screen, in form of a hamburger menu icon.</li></ul><figure class="table"><table><tbody><tr><td><figure class="image"><img style="aspect-ratio:295/434;" src="api/attachments/8fNGILWWQodv/image/image.png" width="295" height="434"><figcaption>The global menu in the vertical layout.</figcaption></figure></td><td><figure class="image"><img style="aspect-ratio:380/482;" src="api/attachments/PhNb7G9OgPVt/image/image.png" width="380" height="482"><figcaption>The global menu in the horizontal layout.</figcaption></figure></td></tr></tbody></table></figure><p>&nbsp;</p>


blobId: eZpmInzzXdKXFBaYrWvK
dateModified: 2025-03-10 11:55:51.637+0200
utcDateModified: 2025-03-10 09:55:51.640Z
content:
  <p>There are some situations where modifying the SQLite database that Trilium uses is desirable.</p><p>If you are doing any advanced development or troubleshooting where you manually modify the database, you might want to consider creating backups of your <code>document.db</code> file.</p><h2>Modifying it internally using the SQL Console</h2><p>The SQL Console is Trilium's built-in database editor.</p><p>See&nbsp;<a class="reference-link" href="#root/oyIAJ9PvvwHX/YKWqdJhzi2VY">SQL Console</a>.</p><h2>Externally modifying the database</h2><p>Sometimes the SQL Console cannot be used (for example if the application cannot start).</p><p>When making external modifications, consider closing the desktop application. If modifying the server database, then stop the service or Docker container.</p><h3>Using DB Browser for SQLite</h3><p>DB Browser for SQLite is a cross-platform editor that can be used to alter the database using a graphical user interface.</p><p>To do so:</p><ol><li>In the main menu, select File → Open database… and navigate to the database in the&nbsp;<a class="reference-link" href="#root/Otzi9La2YAUX/tAassRL4RSQL">Data directory</a>.</li><li>Select the <i>Execute SQL</i> tab.</li><li>Type in the desired SQL statement.</li><li>Press the "Play" button in the toolbar underneath the "Execute SQL" tab (or F5 key).</li><li>Press "Write Changes" in the main toolbar.</li><li>Close the application or close the database.</li></ol><figure class="image"><img style="aspect-ratio:1186/1130;" src="api/attachments/VO21brIL19xQ/image/image.png" width="1186" height="1130"></figure><h3>Using the SQLite CLI</h3><p>First, start the SQLite 3 CLI by specifying the path to the database:</p><pre><code class="language-text-x-trilium-auto">sqlite3 ~/.local/share/trilium-data/document.db</code></pre><ul><li>In the prompt simply type the statement and make sure it ends with a <code>;</code> character.</li><li>To exit, simply type <code>.quit</code> and enter.</li></ul>


blobId: CSY7Kdlv82p8IaTYe4Fs
dateModified: 2025-03-10 11:55:51.637+0200
utcDateModified: 2025-03-10 09:55:51.641Z
content:
  <p>There are some situations where modifying the SQLite database that Trilium uses is desirable.</p><p>If you are doing any advanced development or troubleshooting where you manually modify the database, you might want to consider creating backups of your <code>document.db</code> file.</p><h2>Modifying it internally using the SQL Console</h2><p>The SQL Console is Trilium's built-in database editor.</p><p>See&nbsp;<a class="reference-link" href="#root/oyIAJ9PvvwHX/YKWqdJhzi2VY">SQL Console</a>.</p><h2>Externally modifying the database</h2><p>Sometimes the SQL Console cannot be used (for example if the application cannot start).</p><p>When making external modifications, consider closing the desktop application. If modifying the server database, then stop the service or Docker container.</p><h3>Using DB Browser for SQLite</h3><p>DB Browser for SQLite is a cross-platform editor that can be used to alter the database using a graphical user interface.</p><p>To do so:</p><ol><li>In the main menu, select File → Open database… and navigate to the database in the&nbsp;<a class="reference-link" href="#root/Otzi9La2YAUX/tAassRL4RSQL">Data directory</a>.</li><li>Select the <i>Execute SQL</i> tab.</li><li>Type in the desired SQL statement.</li><li>Press the "Play" button in the toolbar underneath the "Execute SQL" tab (or F5 key).</li><li>Press "Write Changes" in the main toolbar.</li><li>Close the application or close the database.</li></ol><figure class="image"><img style="aspect-ratio:1186/1130;" src="api/attachments/0740ph4lJ4rv/image/image.png" width="1186" height="1130"></figure><h3>Using the SQLite CLI</h3><p>First, start the SQLite 3 CLI by specifying the path to the database:</p><pre><code class="language-text-x-sh">sqlite3 ~/.local/share/trilium-data/document.db</code></pre><ul><li>In the prompt simply type the statement and make sure it ends with a <code>;</code> character.</li><li>To exit, simply type <code>.quit</code> and enter.</li></ul>


blobId: 39JHbYXP4KW7KEA9VGNn
dateModified: 2025-03-10 11:57:46.861+0200
utcDateModified: 2025-03-10 09:57:46.861Z
content:
  <p>Your Trilium data is stored in a <a href="https://www.sqlite.org">SQLite</a> database which contains all notes, tree structure, metadata, and most of the configuration. The database file is named <code>document.db</code> and is stored in the application's default&nbsp;<a class="reference-link" href="#root/pOsGYCXsbNQG/Otzi9La2YAUX/tAassRL4RSQL">Data directory</a>.</p><h2>Demo Notes</h2><p>When you run Trilium for the first time, it will generate a new database containing demo notes. These notes showcase its many features, such as:</p><ul><li><a href="#root/iRwzGnHPzonm">Relation Map</a></li><li><a href="#root/l0tKav7yLHGF">Day Notes</a></li><li><a href="#root/R7abl2fc6Mxi">Weight Tracker</a></li><li><a href="#root/xYjQUYhpbUEW">Task Manager</a></li><li><a href="#root/Wy267RK4M69c">Custom CSS Themes</a></li></ul><h3>Restoring Demo Notes</h3><p>There are some cases in which you may want to restore the original demo notes. For example, if you experimented with some of the more advanced features and want to see the original reference, or if you simply want to explore the latest version of the demo notes, which might showcase new features.</p><p>You can easily restore the demo notes by using Trilium's built-in import feature by importing them:</p><ul><li>Download <a href="https://github.com/TriliumNext/Notes/raw/develop/db/demo.zip">this .zip archive</a> with the latest version of the demo notes</li><li>Right click on any note in your tree under which you would like the demo notes to be imported</li><li>Click "Import into note"</li><li>Select the .zip archive to import it</li></ul><h2>Manually Modifying the Database</h2><p>Trilium provides a lot of flexibility, and with it, opportunities for advanced users to tweak it. If you need to explore or modify the database directly, you can use a tool such as <a href="https://sqlitebrowser.org/">SQLite Browser</a> to work directly on the database file.</p><p>See&nbsp;<a class="reference-link" href="#root/pOsGYCXsbNQG/tC7s2alapj8V/wX4HbRucYSDD/oyIAJ9PvvwHX">Manually altering the database</a>&nbsp;for more information.</p><h2>How to Reset the Database</h2><p>If you are experimenting with Trilium and want to return it to its original state, you can do that by deleting the current database. When you restart the application, it will generate a new database containing the original demo notes.</p><p>To delete the database, simply go to the <a href="#root/tAassRL4RSQL">data directory</a> and delete the <code>document.db</code> file (and any other files starting with <code>document.db</code>).</p><p>If you do not need to preserve any configurations that might be stored in the <code>config.ini</code> file, you can just delete all of the <a href="#root/tAassRL4RSQL">data directory's</a> contents to fully restore the application to its original state. You can also review the <a href="#root/Gzjqa934BdH4">configuration</a> file to provide all <code>config.ini</code> values as environment variables instead.</p>


blobId: hUqFoqxQSsWnWeLUHk7g
dateModified: 2025-03-10 12:07:14.069+0200
utcDateModified: 2025-03-10 10:07:14.069Z
content:
  <p>Data directory contains:</p><ul><li><code>document.db</code> - <a href="#root/wX4HbRucYSDD">database</a></li><li><code>config.ini</code> - instance level settings like port on which the Trilium application runs</li><li><code>backup</code> - contains automatically <a href="#root/ODY7qQn5m2FT">backup</a> of documents</li><li><code>log</code> - contains application log files</li></ul><h2>Location</h2><p>Easy way how to find out which data directory Trilium uses is to look at the "About Trilium Notes" dialog (from "Menu" in upper left corner):</p><p><img src="api/images/0QpFiijcbMem/about-trilium-data-dir.png" alt=""></p><p>Here's how the location is decided:</p><p>Data directory is normally named <code>trilium-data</code> and it is stored in:</p><ul><li><code>/home/[user]/.local/share</code> for Linux</li><li><code>C:\Users\[user]\AppData\Roaming</code> for Windows Vista and up</li><li><code>/Users/[user]/Library/Application Support</code> for Mac OS</li><li>user's home is a fallback if some of the paths above don't exist</li><li>user's home is also a default setup for [[docker|Docker server installation]]</li></ul><p>If you want to back up your Trilium data, just backup this single directory - it contains everything you need.</p><h3>Changing the location of data directory</h3><p>If you want to use some other location for the data directory than the default one, you may change it via TRILIUM_DATA_DIR environment variable to some other location:</p><h4>Linux</h4><pre><code class="language-text-x-trilium-auto">export TRILIUM_DATA_DIR=/home/myuser/data/my-trilium-data</code></pre><h4>Mac OS X</h4><p>You need to create a <code>.plist</code> file under <code>~/Library/LaunchAgents</code> to load it properly each login.</p><p>To load it manually, you need to use <code>launchctl setenv TRILIUM_DATA_DIR &lt;yourpath&gt;</code></p><p>Here is a pre-defined template, where you just need to add your path to:</p><pre><code class="language-text-x-trilium-auto">



      
          Label
          set.trilium.env
          RunAtLoad
          
          ProgramArguments
          
              launchctl
              setenv
              TRILIUM_DATA_DIR
              /Users/YourUserName/Library/Application Support/trilium-data
          
      
  </code></pre><h3>Create a script to run with specific data directory</h3><p>An alternative to globally setting environment variable is to run only the Trilium Notes with this environment variable. This then allows for different setup styles like two <a href="#root/wX4HbRucYSDD">database</a> instances or "portable" installation.</p><p>To do this in unix based systems simply run trilium like this:</p><pre><code class="language-text-x-trilium-auto">TRILIUM_DATA_DIR=/home/myuser/data/my-trilium-data trilium</code></pre><p>You can then save the above command as a shell script on your path for convenience.</p><h3>Fine-grained directory/path location</h3><p>It's possible to configure e.g. backup and log directories separately, with following environment variables:</p><ul><li><code>TRILIUM_DOCUMENT_PATH</code></li><li><code>TRILIUM_BACKUP_DIR</code></li><li><code>TRILIUM_LOG_DIR</code></li><li><code>TRILIUM_ANONYMIZED_DB_DIR</code></li><li><code>TRILIUM_CONFIG_INI_PATH</code></li></ul><p>If these are not set, default paths within the data directory will be used.</p>


blobId: NqMckWhtic2afDoYnwkm
dateModified: 2025-03-10 12:08:35.549+0200
utcDateModified: 2025-03-10 10:08:35.550Z
content:
  <div class="content">
         

        <div class="ck-content">
          <p>A language hint can be provided for text notes. This option informs the
            browser or the desktop application about the language the note is written
            in (for example this might help with spellchecking), and it also determines
            whether the text is displayed from right-to-left for languages such as
            Arabic, Hebrew, etc.</p>
          <p>For more information about right-to-left support, see&nbsp;<a class="reference-link"
            href="#root/BMf2nEbYlcUt">Right-to-left text notes</a>.</p>
          <p>To set the language of the content, go to “Basic Properties” and look
            for the “Language” field. By default there will be no content languages
            set, they can be configured by going to settings or by selecting the “Configure
            languages” item in the list.</p>
          <p>
            <img src="api/attachments/HqGY8V2LUsSR/image/Content language_image.png" width="635" height="492">
          </p>
        </div>
      </div>


blobId: OzRkmE8WgqzhhMoqqUv0
dateModified: 2025-03-10 12:08:52.566+0200
utcDateModified: 2025-03-10 10:08:52.571Z
content:
  <div class="content">
         

        <div class="ck-content">
          <p>Trilium now has basic support for right-to-left text, at note level.</p>
          <figure
          class="table">
            <table>
              <tbody>
                <tr>
                  <td>
                    <figure class="image">
                      <img style="aspect-ratio:906/557;" src="api/attachments/W6rRVYqhXWS1/image/3_Right-to-left text notes_i.png"
                      width="906" height="557">
                    </figure>
                  </td>
                  <td>
                    <figure class="image">
                      <img style="aspect-ratio:906/557;" src="api/attachments/BrGpsyosF4BW/image/2_Right-to-left text notes_i.png"
                      width="906" height="557">
                    </figure>
                  </td>
                </tr>
              </tbody>
            </table>
            </figure>
            <p>Note that only the Text note type supports this.</p>
            <p>The list of languages is configurable via the a new dedicated settings
              page:</p>
            <figure class="image">
              <img style="aspect-ratio:1248/635;" src="api/attachments/ggwXHmQsYUQR/image/4_Right-to-left text notes_i.png"
              width="1248" height="635">
            </figure>
            <p>To select the corresponding language of the text, go to “Basic Properties”
              and select your desired language.</p>
            <p>
              <img src="api/attachments/kAlNkaw8OX7H/image/1_Right-to-left text notes_i.png" width="635" height="492">
            </p>
            <p>Feel free to report any issues regarding right to left support.</p>
            <p>&nbsp;</p>
        </div>
      </div>


blobId: 7kRu4uJtMRkKzZkesxd3
dateModified: 2025-03-10 12:09:10.727+0200
utcDateModified: 2025-03-10 10:09:10.727Z
content:
  <div><div><p>Trilium now has basic support for right-to-left text, but only for&nbsp;<a class="reference-link" href="#root/pOsGYCXsbNQG/gh7bpGYxajRS/BFs8mudNFgCS/iPIMuisry3hd">Text</a>&nbsp;note types (both editable and read-only).</p><figure class="table"><table><tbody><tr><td><figure class="image"><img style="aspect-ratio:906/557;" src="api/attachments/J25q0es2PQGJ/image/3_Right-to-left text notes_i.png" width="906" height="557"></figure></td><td><figure class="image"><img style="aspect-ratio:906/557;" src="api/attachments/hLJbTJdMAAjW/image/2_Right-to-left text notes_i.png" width="906" height="557"></figure></td></tr></tbody></table></figure><p>Note that only the Text note type supports this.</p><p>The list of languages is configurable via the a new dedicated settings page:</p><figure class="image"><img style="aspect-ratio:1248/635;" src="api/attachments/V7U0KMPHxH2I/image/4_Right-to-left text notes_i.png" width="1248" height="635"></figure><p>To select the corresponding language of the text, go to “Basic Properties” and select your desired language.</p><p><img src="api/attachments/oW5LpuCUuq1z/image/1_Right-to-left text notes_i.png" width="635" height="492"></p><p>Feel free to report any issues regarding right to left support.</p><p>&nbsp;</p></div></div>


blobId: CqDXsW3Mpay5i63AhcPX
dateModified: 2025-03-10 12:10:27.416+0200
utcDateModified: 2025-03-10 10:10:27.417Z
content:
  <ol><li><a class="reference-link" href="#root/KSZ04uQ2D1St/81SGnPGMk7Xc">Geo map</a></li><li><a class="reference-link" href="#root/BFs8mudNFgCS/NRnIZmSMc5sj">Export as PDF</a></li><li><a class="reference-link" href="#root/gh7bpGYxajRS/rC3pL2aptaRE">Zen mode</a></li><li><a class="reference-link" href="#root/GTwFsgaA0lCt/xWbu3jpNWapp">Calendar View</a></li><li><a class="reference-link" href="#root/BFs8mudNFgCS/BMf2nEbYlcUt">Right-to-Left Support</a></li></ol>


blobId: jQeYwx7NkYjCk7PRgBnv
dateModified: 2025-03-10 12:12:15.514+0200
utcDateModified: 2025-03-10 10:12:15.515Z
content:
  <h2>Mac OS support</h2><p>Originally, desktop builds of Trilium Notes has been available for Windows &amp; Linux, but there has been a considerable demand for macOS build.</p><p>So I made one, but I underestimated the differences and specifics of Mac platform which seems to require special handling in several places. My lack of knowledge and frankly willingness to learn &amp; code Mac specific functionality resulted in a current state where <a href="https://github.com/TriliumNext/Notes/issues/511">Trilium does not integrate well into the OS</a>&nbsp;</p><p>%%{WARNING}%%.</p><p>macOS build is from now on considered "unsupported". I will strive to keep it fundamentally functional, but I won't work on Mac specific features or integrations. Note that this is more of an acknowledgment of an existing state rather than sudden change of direction.</p><p>Of course, PRs are welcome.</p><h2>Translation / localization support</h2><p>Trilium is currently available only in English. Translation to other languages is not planned in the near/medium term because it brings a significant maintenance overhead. This decision might be revisited once Trilium stabilizes into a more mature product.</p><p>For Chinese, there's an unofficial fork <a href="https://github.com/Nriver/trilium-translation">here</a>. Use at your own risk.</p><h2>Multi user support</h2><p>Common request is to allow multiple users collaborate, share notes etc. So far I'm resisting this because of these reasons:</p><ul><li>it's a huge feature, or rather a Pandora's box of collaboration features like user management, permissions, conflict resolution, real-time editing of a note by multiple people etc. This would be a huge amount of work. Trilium Notes is project made mostly by one person in free time and that's unlikely to change in the future.</li><li>given its size it would probably pivot the attention away from my main focus which is a personal note-taking</li><li>the assumption that only single person has access to the app simplifies many things, or just outright makes them possible. In multi-user app, our <a href="#root/CdNpE2pqjmI6">scripting</a> support would be a XSS security hole, while with the single user assumption it's an endless customizable tool.</li></ul><h2>How to open multiple documents in one Trilium instance</h2><p>This is normally not supported - one Trilium process can open only a single instance of a <a href="#root/wX4HbRucYSDD">database</a>. However, you can run two Trilium processes (from one installation), each connected to a separate document. To achieve this, you need to set a location for the <a href="#root/tAassRL4RSQL">data directory</a> in the <code>TRILIUM_DATA_DIR</code> environment variable and separate port on <code>TRILIUM_PORT</code> environment variable. How to do that depends on the platform, in Unix-based systems you can achieve that by running command such as this:</p><pre><code class="language-text-x-trilium-auto">TRILIUM_DATA_DIR=/home/me/path/to/data/dir TRILIUM_PORT=12345 trilium </code></pre><p>You can save this command into a <code>.sh</code> script file or make an alias. Do this similarly for a second instance with different data directory and port.</p><h2>Can I use Dropbox / Google Drive / OneDrive to sync data across multiple computers.</h2><p>No.</p><p>These general purpose sync apps are not suitable to sync database files which are open and being worked on by another application. The result is that they will corrupt the database file, resulting in data loss and this message in the Trilium logs:</p><blockquote><p>SqliteError: database disk image is malformed</p></blockquote><p>The only supported way to sync Trilium's data across the network is to use a <a href="#root/cbkrhQjrkKrh">sync/web server</a>.</p><h2>Why database instead of flat files?</h2><p>Trilium stores notes in a <a href="#root/wX4HbRucYSDD">database</a> which is an SQLite database. People often ask why doesn't Trilium rather use flat files for note storage - it's fair question since flat files are easily interoperable, work with SCM/git etc.</p><p>Short answer is that file systems are simply not powerful enough for what we want to achieve with Trilium. Using filesystem would mean fewer features with probably more problems.</p><p>More detailed answer:</p><ul><li><a href="#root/IakOLONlIfGI">clones</a> are what you might call "hard directory link" in filesystem lingo, but this concept is not implemented in any filesystem</li><li>filesystems make a distinction between directory and file while there's intentionally no such difference in Trilium</li><li>files are stored in no particular order and user can't change this</li><li>Trilium allows storing note <a href="#root/zEY4DaJG4YT5">attributes</a> which could be represented in extended user attributes but their support differs greatly among different filesystems / operating systems</li><li>Trilium makes links / relations between different notes which can be quickly retrieved / navigated (e.g. for <a href="#root/BCkXAVs63Ttv">note map</a>). There's no such support in file systems which means these would have to be stored in some kind of side-car files (mini-databases).</li><li>Filesystems are generally not transactional. While this is not completely required for a note-taking application, having transactions make it way easier to keep notes and their metadata in predictable and consistent state.</li></ul>


blobId: R9Q0ttUBoH1Ced30AQeX
dateModified: 2025-03-10 12:13:39.045+0200
utcDateModified: 2025-03-10 10:13:39.046Z
content:
  <p>Trilium is an offline-first note-taking application that stores all data locally on the desktop client. However, it also offers the option to set up synchronization with a server instance, allowing multiple desktop clients to sync with a central server. This creates a star-shaped topology:</p><p><img src="api/images/bunenMGMmaN6/star-topology.png" alt="topology visualization"></p><p>In this setup, a central server (referred to as the <i>sync server</i>) and multiple <i>client</i> (or <i>desktop</i>) instances synchronize with the sync server. Once configured, synchronization is automatic and ongoing, requiring no manual intervention.</p><h2>Setting Up Synchronization</h2><h3>Security Considerations</h3><p>Setting up the server securely is critical and can be complex. It is crucial to use a valid <a href="#root/l2VkvOwUNfZj">TLS certificate</a> (HTTPS) rather than an unencrypted HTTP connection to ensure security and avoid potential vulnerabilities.</p><h3>Synchronizing a Desktop Instance with a Sync Server</h3><p>This method is used when you already have a desktop instance of Trilium and want to set up a sync server on your web host.</p><ol><li><strong>Server Deployment</strong>: Ensure your server instance is deployed but uninitialized.</li><li><strong>Desktop Configuration</strong>: Open your desktop instance, navigate to Options -&gt; Sync tab -&gt; Sync configuration, and set the "Server instance address" to your sync server's address. Click Save.</li></ol><p><img src="api/images/676Ekdv73T7I/sync-config.png" alt="screenshot of the sync settings options modal"></p><ol><li><strong>Testing Sync</strong>: Click the "Test sync" button to verify the connection to the sync server. If successful, the client will start pushing all data to the server instance. This process may take some time, but you can continue using Trilium. Periodically check the server instance to confirm when the sync is complete. Once finished, you should see the login screen on the server.</li></ol><h3>Synchronizing a Desktop Instance from a Sync Server</h3><p>This method is used when you already have a sync server and want to configure a new desktop instance to sync with it.</p><ol><li><strong>Desktop Setup</strong>: Follow the <a href="#root/poXkQfguuA0U">desktop installation page</a>.</li><li><strong>Initial Configuration</strong>: When prompted, choose the option to set up sync with a sync server.</li></ol><p><img src="api/images/SDHWNDsB68aJ/sync-init.png" alt="screenshot of the sync from server setup page"></p><ol><li><strong>Server Details</strong>: Configure the Trilium server address and enter the correct username and password for authentication.</li><li><strong>Finish Setup</strong>: Click the "Finish setup" button. If successful, you will see the following screen:</li></ol><p><img src="api/images/qGTyyKX4TceE/sync-in-progress.png" alt="screenshot of the sync page"></p><p>Once synchronization is complete, you will be automatically redirected to the Trilium application.</p><h2>Proxy Configuration</h2><p>Two proxy setups are supported:</p><ul><li><strong>Explicit Proxy Configuration</strong>: Set the proxy server in Options / Sync. Only unauthenticated proxy servers are supported.</li><li><strong>System Proxy Settings</strong>: If no proxy server is explicitly configured, Trilium will use the system proxy settings.</li></ul><h2>Troubleshooting</h2><h3>Date/Time Synchronization</h3><p>For successful synchronization, both client and server must have the same date and time, with a tolerance of up to five minutes.</p><h3>Certificate Issues</h3><p>When using TLS, Trilium will verify the server certificate. If verification fails (e.g., due to self-signed certificates or certain corporate proxies), you can run the Trilium client with the <code>NODE_TLS_REJECT_UNAUTHORIZED</code> environment variable set to <code>0</code>:</p><pre><code class="language-text-x-trilium-auto">export NODE_TLS_REJECT_UNAUTHORIZED=0</code></pre><p>This will disable TLS certificate verification, significantly reducing security and exposing the setup to MITM attacks. It is strongly recommended to use a valid signed server certificate. Newer Trilium versions include a script called <code>trilium-no-cert-check.sh</code> for this purpose.</p><h3>Conflict Resolution</h3><p>If you edit the same note on multiple instances before synchronization, Trilium resolves conflicts by retaining the newer change and discarding the older one. The older version remains accessible in <a href="#root/vZWERwf8U3nx">note revisions</a>, allowing data recovery if needed.</p><h3>Hash Check</h3><p>After each synchronization, Trilium computes a hash of all synced data on both the client and the sync server. If there is a discrepancy, Trilium will automatically initiate a recovery mechanism to resolve the issue.</p>


blobId: 0bsLdn8SqtkHXOTGF0IX
dateModified: 2025-03-10 12:49:18.730+0200
utcDateModified: 2025-03-10 10:49:18.731Z
content:
  <p>Trilium utilizes the powerful <a href="https://ckeditor.com/ckeditor-5/">CKEditor 5</a> as its text editing component.</p><h2>Formatting Options</h2><p>The Trilium text note interface does not display toolbars or formatting options by default. These can be accessed by:</p><p><img src="api/images/FtmPLgGmgZVC/text-notes-formatting-inline.png" alt="inline note formatting"></p><ol><li>Selecting text to bring up an inline toolbar.</li></ol><p><img src="api/images/oRWfJLUbb7j7/text-notes-formatting-block.png" alt="formating note block"> 2. Clicking on the block toolbar.</p><h2>Read-Only vs. Editing Mode</h2><p>Text notes are usually opened in edit mode. However, they may open in read-only mode under the following circumstances:</p><ul><li>The note is long and would take time to load, so it is opened in read-only mode by default for quicker access.</li><li>The note has a <code>readOnly</code> <a href="#root/zEY4DaJG4YT5">label</a>.</li></ul><p>In both cases, it is possible to switch back to editable mode using the&nbsp;<img src="api/attachments/nTpioygHxXvr/image/bx-edit-alt.svg?2025-03-10%2010:16:45.755Z%22%3E" width="24" height="24">&nbsp;button at top right of page.</p><p>For more information, see&nbsp;<a class="reference-link" href="#root/BFs8mudNFgCS/CoFPLs3dRlXc">Read-Only Notes</a>.</p><h2>General Formatting</h2><p>Since Trilium uses CKEditor, all of its formatting options are available here. You may use the graphical toolbar shown above, or enter formatting such as markdown markdown directly in the text. Examples include:</p><ul><li><strong>Bold</strong>: Type <code>**text**</code> or <code>__text__</code></li><li><i>Italic</i>: Type <code>*text*</code> or <code>_text_</code></li><li><code>Code</code>: Type `text`</li><li><s>Strikethrough</s>: Type <code>~~text~~</code></li></ul><h3>Lists</h3><ul><li>Bulleted list: Start a line with <code>*</code> or <code>-</code> followed by a space</li><li>Numbered list: Start a line with <code>1.</code> or <code>1)</code> followed by a space</li><li>To-do list: Start a line with <code>[ ]</code> for an unchecked item or <code>[x]</code> for a checked item</li></ul><h3>Blocks</h3><ul><li>Block quote: Start a line with <code>&gt;</code> followed by a space</li></ul><h3>Multi-Line Code Blocks</h3><p>To create a multi-line code block, start a line with "```[lang]", for example:</p><pre><code class="language-text-x-trilium-auto">if (1 &gt; 2) {
      console.log("Error in the matrix");
  }</code></pre><h3>Headings</h3><p>Create headings by starting a line with <code>##</code> for heading 2, <code>###</code> for heading 3, and so on up to heading 6. Note that <code>#</code> is reserved for the title.</p><h3>Horizontal Line</h3><p>Insert a horizontal line by starting a line with <code>---</code>.</p><h2>Markdown &amp; Autoformat</h2><p>CKEditor supports a markdown-like editing experience, recognizing syntax and automatically converting it to rich text.</p><p>Complete documentation for this feature is available in the <a href="https://ckeditor.com/docs/ckeditor5/latest/features/autoformat.html">CKEditor documentation</a>.</p><p>If autoformatting is not desirable, press <code>CTRL-Z</code> to revert the text to its original form.</p><p>Note: The use of <code>#</code> for Heading 1 is not supported because it is reserved for the title. Start with <code>##</code> for Heading 2. More information is available <a href="https://ckeditor.com/docs/ckeditor5/latest/features/headings.html#heading-levels">here</a>.</p><h2>Math Support</h2><p>Trilium provides math support through <a href="https://katex.org/">KaTeX</a>.</p><h2>Cutting Selection to Sub-Note</h2><p>When editing a document that becomes too large, you can split it into sub-notes:</p><ol><li>Select the desired text and cut it to the clipboard.</li><li>Create a new sub-note and name it.</li><li>Paste the content from the clipboard into the sub-note.</li></ol><p>Trilium can automate this process. Select some text within the note, and in the selection toolbar, click the scissors icon for the "cut &amp; pasted selection to sub-note" action. The heading is automatically detected and the new sub-note is named accordingly. You can also assign a keyboard shortcut for this action. This functionality is available through the block toolbar icon.</p><h2>Including a Note</h2><p>Text notes can "include" another note as a read only widget. This can be useful for e.g. including a dynamically generated chart (from scripts &amp; "render HTML" note) or other more advanced use cases.</p><p>This functionality is available in the block toolbar icon.</p>


blobId: qYsuD28neW5uQCSxhXbL
dateModified: 2025-03-10 12:50:34.733+0200
utcDateModified: 2025-03-10 10:50:34.733Z
content:
  <ul><li>This is a list<ul><li><p>Here's a code block within the list:</p><pre><code class="language-text-x-trilium-auto">console.log("Hello world");</code></pre></li></ul></li><li>asdfsd<ul><li>asdfads<ul><li>adf<br>&nbsp;</li></ul></li><li><pre><code class="language-text-x-trilium-auto">asdfsdaf
  asdfsadfsafd
  </code></pre></li></ul></li></ul><p>&nbsp;</p><ul class="todo-list"><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">asdfsdaf</span></label><ul class="todo-list"><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">asfasdf</span></label><pre><code class="language-text-x-trilium-auto">sadfs</code></pre></li><li><label class="todo-list__label"><input type="checkbox" disabled="disabled"><span class="todo-list__label__description">&nbsp;</span></label></li></ul></li></ul>


blobId: 6mfbZPeYRQ7p0otzbRlN
dateModified: 2025-03-10 12:50:42.342+0200
utcDateModified: 2025-03-10 10:50:42.343Z
content:
  <p>There are three types of lists supported by text notes:</p><ul><li>Bulleted lists (also known as unordered lists).</li><li>Numbered lists (or ordered lists).</li><li>To-do lists</li></ul><h2>Keyboard shortcuts</h2><ul><li>Bulleted list: Start a line with <code>*</code> or <code>-</code> followed by a space;</li><li>Numbered list: Start a line with <code>1.</code> or <code>1)</code> followed by a space;</li><li>To-do list: Start a line with <code>[ ]</code> for an unchecked item or <code>[x]</code> for a checked item.</li></ul><h2>Headings, code blocks within lists</h2><p>It possible to add content-level blocks such as headings, code blocks, tables within lists, as follows:</p><figure class="table" style="width:100%;"><table class="ck-table-resized"><colgroup><col style="width:59.27%;"><col style="width:40.73%;"></colgroup><tbody><tr><td><img src="api/attachments/If3k6Tt5cPBt/image/image.png" width="298" height="46"></td><td>First, create a list.</td></tr><tr><td><img src="api/attachments/eL11eZMPwpmH/image/image.png" width="295" height="72"></td><td>Press Enter to create a new list item.</td></tr><tr><td><img src="api/attachments/EnkTpdeLJ6Ft/image/image.png" width="295" height="72"></td><td>Press Backspace to get rid of the bullet point. Notice the cursor position.</td></tr><tr><td><figure class="image"><img style="aspect-ratio:676/112;" src="api/attachments/6jl7tboJfutt/image/image.png" width="676" height="112"></figure></td><td>At this point, insert any desired block-level item such as a code block.</td></tr><tr><td><figure class="image"><img style="aspect-ratio:675/129;" src="api/attachments/5cmICTYfg13g/image/image.png" width="675" height="129"></figure></td><td>To continue with a new bullet point, press Enter until the cursor moves to a new blank position.</td></tr><tr><td><figure class="image"><img style="aspect-ratio:675/129;" src="api/attachments/d4XfLoK5srYZ/image/image.png" width="675" height="129"></figure></td><td>Press Enter once more to create the new bullet.</td></tr></tbody></table></figure><p>The same principle applies to all three list types (bullet, numbered and to-do).</p>


blobId: g9BURrJi14i13X3es654
dateModified: 2025-03-10 14:40:16.141+0200
utcDateModified: 2025-03-10 12:40:16.142Z
content:
  <p><img src="api/attachments/fhKf5Otv0M5Y/image/image.png" width="316" height="263"></p><p>Trilium Web Clipper is a web browser extension which allows user to clip text, screenshots, whole pages and short notes and save them directly to Trilium Notes.</p><p>Project is hosted <a href="https://github.com/TriliumNext/web-clipper">here</a>.</p><p>Firefox and Chrome are supported browsers, but the chrome build should work on other chromium based browsers as well.</p><h2>Functionality</h2><ul><li>select text and clip it with the right-click context menu</li><li>click on an image or link and save it through context menu</li><li>save whole page from the popup or context menu</li><li>save screenshot (with crop tool) from either popup or context menu</li><li>create short text note from popup</li></ul><p>Trilium will save these clippings as a new child note under a "clipper inbox" note.</p><p>By default, that's the <a href="#root/l0tKav7yLHGF">day note</a> but you can override that by setting the <a href="#root/zEY4DaJG4YT5">label</a> <code>clipperInbox</code>, on any other note.</p><p>If there's multiple clippings from the same page (and on the same day), then they will be added to the same note.</p><p><strong>Extension is available from:</strong></p><ul><li><a href="https://github.com/TriliumNext/web-clipper/releases">Project release page</a> - .xpi for Firefox and .zip for Chromium based browsers.</li><li>%%{WARNING}%% <a href="https://chromewebstore.google.com/detail/trilium-web-clipper/dfhgmnfclbebfobmblelddiejjcijbjm">Chrome Web Store</a></li></ul><h2>Configuration</h2><p>The extension needs to connect to a running Trilium instance. By default, it scans a port range on the local computer to find a desktop Trilium instance.</p><p>It's also possible to configure the <a href="#root/WOcw2SLH6tbX">server</a> address if you don't run the desktop application, or want it to work without the desktop application running.</p><h2>Username</h2><p>Older versions of Trilium (before 0.50) required username &amp; password to authenticate, but this is no longer the case. You may enter anything in that field, it will not have any effect.</p>


blobId: s9GxR6sn2rGMC9igyhrO
dateModified: 2025-03-10 14:42:18.028+0200
utcDateModified: 2025-03-10 12:42:18.029Z
content:
  <p>Trilium supports creating "code" notes, i.e. notes which contain some sort of formal code - be it programming language (C++, JavaScript), structured data (JSON, XML) or other types of codes (CSS etc.).</p><p>This can be useful for a few things:</p><ul><li>computer programmers can store code snippets as notes with syntax highlighting</li><li>JavaScript code notes can be executed inside Trilium for some extra functionality<ul><li>we call such JavaScript code notes "scripts" - see <a href="#root/CdNpE2pqjmI6">Scripts</a></li></ul></li><li>JSON, XML etc. can be used as storage for structured data (typically used in conjunction with scripting)</li></ul><figure class="image"><img style="aspect-ratio:910/703;" src="api/attachments/hajUVeLs3EOM/image/image.png" width="910" height="703"></figure><h2>Extra languages</h2><p>Trilium supports syntax highlighting for many languages, but by default displays only some of them (to reduce the number of items). You can add extra languages in Options -&gt; Code notes.</p><h2>Code blocks</h2><p>An alternative to the code note is a "code block" - feature of a text note which can add short snippets of code to the text editor. Starting with TriliumNext v0.90.12, the code blocks also support syntax highlighting.</p><figure class="image"><img style="aspect-ratio:912/705;" src="api/attachments/OTcapNOcNaBL/image/image.png" width="912" height="705"></figure>


blobId: QtVXwLq9oKiK3uZayeiu
dateModified: 2025-03-10 14:44:04.545+0200
utcDateModified: 2025-03-10 12:44:04.546Z
content:
  <figure class="image"><img style="aspect-ratio:979/630;" src="api/attachments/xh9biKiOnMJv/image/image.png" width="979" height="630"></figure><p>In certain scenarios, understanding the structure of a database is crucial for troubleshooting issues. However, sharing your actual <a href="#root/wX4HbRucYSDD">database</a> file with personal notes is not advisable. To address this, Trilium offers a feature to anonymize the database. This feature can be accessed via Menu -&gt; Options -&gt; Advanced tab.</p><p>This feature creates a copy of your database with all sensitive data removed. Specifically, it strips out note titles, contents, revisions, history, and some non-system attributes while retaining the overall structure and metadata, such as modification dates. After anonymization, the database undergoes a <a href="https://sqlite.org/lang_vacuum.html">vacuuming process</a> to ensure no sensitive data remnants remain in the file. The anonymized database is saved in the <code>anonymized</code> directory within the <a href="#root/tAassRL4RSQL">data directory</a>, making it safe to share with bug reports.</p><p>This will create a copy of your document and remove all sensitive data (currently note titles, contents, revisions, history and some of the options, and non-system attributes) while leaving all structure and metadata (e.g. date of last change). After this is done, the database is <a href="https://sqlite.org/lang_vacuum.html">VACUUMed</a> to make sure there's no stale sensitive data in the document file. The resulting file is stored in <code>anonymized</code> directory (placed in the <a href="#root/tAassRL4RSQL">data directory</a>). You can safely attach it to a bug report.</p><h2>Command Line Anonymization</h2><p>If your <a href="#root/wX4HbRucYSDD">database</a> is corrupted to the point where Trilium cannot start, the anonymization process can still be executed via the command line:</p><pre><code class="language-text-x-trilium-auto">node src/anonymize.js</code></pre><p>Run this command from the directory containing Trilium's source files, typically found in the <code>resources/app</code> directory for desktop builds.</p>


blobId: Uv2hYbw0AN57YID5xMIf
dateModified: 2025-03-10 14:45:03.531+0200
utcDateModified: 2025-03-10 12:45:03.532Z
content:
  <p>It's important to provide all available error logs together with bug reports. This page will show you how to do it.</p><h2>Backend logs</h2><p>Open <a href="#root/tAassRL4RSQL">data directory</a>, go to <code>log</code> subdirectory and find the latest log file, e.g. <code>trilium-2022-12-14.log</code>. You can attach the whole file to the bug report (preferable) or open it and copy-paste only the last lines / lines you believe are relevant.</p><p>If you have trouble finding it the log files, there's also an in-app option in top-left menu button -&gt; Advanced -&gt; Show backend log.</p><h2>Frontend logs</h2><p>To provide frontend logs, we need to open the Developer Console. Often the easiest way is to press <code>CTRL-SHIFT-I</code> which should work in most browsers (and desktop app). Make sure that the error producing action happened right before you copy&amp;paste the errors, the console is cleared on app restart.</p><p>If that doesn't work, then:</p><ul><li>in Trilium desktop app, go to top-left menu button -&gt; Advanced -&gt; Open Dev Tools</li><li>In Firefox/Chrome right-click anywhere in the page and click Inspect:</li></ul><p><img src="api/images/zIQ1XGaUbB7i/error-logs-firefox-context-men.png" alt=""></p><p>Once you have Dev Tools open, click on "Console" tab:</p><figure class="image"><img style="aspect-ratio:537/629;" src="api/attachments/8b6d0LUU1aMl/image/image.png" width="537" height="629"></figure><p>Copy-paste (or screenshot) the logs. It's better to provide not just errors, but the whole log, which might provide context while analyzing the bug.</p><h2>Providing sensitive data</h2><p>If you don't feel comfortable attaching the logs or anything sensitive to the public GitHub issues, feel free to contact the devs in our Matrix <a href="https://github.com/TriliumNext/Notes#-discuss-with-us">support channel</a>.</p><p>Use this email to also provide anything which could assist in analysing the bug - e.g. files/images/ZIPs being imported or <a href="#root/x59R8J8KV5Bp">anonymized database</a>.</p><h3>Exporting note subtree for reproduction</h3><p>Often times, bugs manifest themselves in specific notes and having them would greatly ease reproduction and fixing.</p><p>In such case, please export the relevant note subtree by right-clicking it on the left tree, choosing Export - HTML as ZIP:</p><p><img src="api/images/v8H3fXMFPki0/error-logs-export-subtree.png" alt=""></p>


blobId: rZ2rkRYMhrprZeShhF3m
dateModified: 2025-03-10 14:48:33.913+0200
utcDateModified: 2025-03-10 12:48:33.914Z
content:
  <p>Data directory contains:</p><ul><li><code>document.db</code> - <a href="#root/wX4HbRucYSDD">database</a></li><li><code>config.ini</code> - instance level settings like port on which the Trilium application runs</li><li><code>backup</code> - contains automatically <a href="#root/ODY7qQn5m2FT">backup</a> of documents</li><li><code>log</code> - contains application log files</li></ul><h2>Location</h2><p>Easy way how to find out which data directory Trilium uses is to look at the "About Trilium Notes" dialog (from "Menu" in upper left corner):</p><figure class="image"><img style="aspect-ratio:794/521;" src="api/attachments/NONZTci1YkNe/image/image.png" width="794" height="521"></figure><p>Here's how the location is decided:</p><p>Data directory is normally named <code>trilium-data</code> and it is stored in:</p><ul><li><code>/home/[user]/.local/share</code> for Linux</li><li><code>C:\Users\[user]\AppData\Roaming</code> for Windows Vista and up</li><li><code>/Users/[user]/Library/Application Support</code> for Mac OS</li><li>user's home is a fallback if some of the paths above don't exist</li><li>user's home is also a default setup for [[docker|Docker server installation]]</li></ul><p>If you want to back up your Trilium data, just backup this single directory - it contains everything you need.</p><h3>Changing the location of data directory</h3><p>If you want to use some other location for the data directory than the default one, you may change it via TRILIUM_DATA_DIR environment variable to some other location:</p><h4>Linux</h4><pre><code class="language-text-x-trilium-auto">export TRILIUM_DATA_DIR=/home/myuser/data/my-trilium-data</code></pre><h4>Mac OS X</h4><p>You need to create a <code>.plist</code> file under <code>~/Library/LaunchAgents</code> to load it properly each login.</p><p>To load it manually, you need to use <code>launchctl setenv TRILIUM_DATA_DIR &lt;yourpath&gt;</code></p><p>Here is a pre-defined template, where you just need to add your path to:</p><pre><code class="language-text-x-trilium-auto">



      
          Label
          set.trilium.env
          RunAtLoad
          
          ProgramArguments
          
              launchctl
              setenv
              TRILIUM_DATA_DIR
              /Users/YourUserName/Library/Application Support/trilium-data
          
      
  </code></pre><h3>Create a script to run with specific data directory</h3><p>An alternative to globally setting environment variable is to run only the Trilium Notes with this environment variable. This then allows for different setup styles like two <a href="#root/wX4HbRucYSDD">database</a> instances or "portable" installation.</p><p>To do this in unix based systems simply run trilium like this:</p><pre><code class="language-text-x-trilium-auto">TRILIUM_DATA_DIR=/home/myuser/data/my-trilium-data trilium</code></pre><p>You can then save the above command as a shell script on your path for convenience.</p><h3>Fine-grained directory/path location</h3><p>It's possible to configure e.g. backup and log directories separately, with following environment variables:</p><ul><li><code>TRILIUM_DOCUMENT_PATH</code></li><li><code>TRILIUM_BACKUP_DIR</code></li><li><code>TRILIUM_LOG_DIR</code></li><li><code>TRILIUM_ANONYMIZED_DB_DIR</code></li><li><code>TRILIUM_CONFIG_INI_PATH</code></li></ul><p>If these are not set, default paths within the data directory will be used.</p>


blobId: raXsLrAVlXRj0W2cYc1w
dateModified: 2025-03-10 14:49:19.476+0200
utcDateModified: 2025-03-10 12:49:19.477Z
content:
  <h2>Default Themes</h2><p>Trilium comes with a couple pre-installed color themes, with the default being a light theme. To switch to a dark theme or any other available theme, navigate to the Options menu (accessible via the app icon in the top-left corner), select the Appearance tab, and choose your preferred theme.</p><p><img src="api/images/zaQnUsJTbvjr/dark-theme.png" alt="Dark Theme"></p><h2>Creating Custom CSS Themes</h2><p>Trilium supports custom user themes, allowing you to personalize the application's appearance. To create a custom theme, follow these steps:</p><ol><li><strong>Create a CSS Code Note</strong>: Start by creating a new <a href="#root/6f9hih2hXXZk">code note</a> with the <code>CSS</code> type.</li><li><strong>Annotate with </strong><code><strong>#appTheme</strong></code>: Add the <a href="#root/zEY4DaJG4YT5">attribute</a> <code>#appTheme=my-theme-name</code> to your note, where <code>my-theme-name</code> is the name of your custom theme.</li><li><strong>Define Your Styles</strong>: Write your custom CSS within the note. Below is an example of a custom theme:</li></ol><pre><code class="language-text-x-trilium-auto">@font-face {
    font-family: 'Raleway';
    font-style: normal;
    font-weight: 400;
    src: url('/custom/fonts/raleway.woff2') format('woff2');
  }

  :root {
      --main-font-family: 'Raleway' !important;
      --main-font-size: normal;
      --tree-font-family: inherit;
      --tree-font-size: normal;
      --detail-font-family: inherit;
      --detail-font-size: normal;
      --detail-text-font-family: 'Garamond' !important;

      --main-background-color: #404552;
      --main-text-color: #AFB8C6;
      --main-border-color: #AFB8C6;
      --accented-background-color: #383C4A;
      --more-accented-background-color: #2F343F;
      --header-background-color: #383C4A;
      --button-background-color: #2F343F;
      --button-disabled-background-color: #404552;
      --button-border-color: #333;
      --button-text-color: #AFB8C6;
      --button-border-radius: 2px;
      --primary-button-background-color: #6c757d;
      --primary-button-text-color: white;
      --primary-button-border-color: #6c757d;
      --muted-text-color: #86919F;
      --input-text-color: #AFB8C6;
      --input-background-color: #404552;
      --hover-item-text-color: white;
      --hover-item-background-color: #4877B1;
      --active-item-text-color: white;
      --active-item-background-color: #4877B1;
      --menu-text-color: #AFB8C6;
      --menu-background-color: #383C4A;
      --tooltip-background-color: #383C4A;
      --link-color: lightskyblue;
      --modal-background-color: #404552;
      --modal-backdrop-color: black;
      --scrollbar-border-color: rgba(175, 184, 198, 0.5);
  }

  body .note-detail-text {
      font-size: 120%;
  }

  body .CodeMirror {
      filter: invert(100%) hue-rotate(180deg);
  }</code></pre><h3>Activating Your Custom Theme</h3><p>Once you've created your custom theme:</p><ol><li>Go to "Menu" -&gt; "Options" -&gt; "Appearance."</li><li>In the theme selection dropdown, you should see your custom theme listed under the name you provided with the <code>#appTheme</code> <a href="#root/zEY4DaJG4YT5">label</a>.</li><li>Select your custom theme to activate it.</li></ol><p>If you make changes to your theme, press <code>CTRL-R</code> to reload the frontend and apply your updates.</p><h3>Sharing and Importing Themes</h3><p>Custom themes can be exported as <code>.tar</code> archives, which can be shared with other users. However, be cautious when importing themes from untrusted sources, as they may contain executable scripts that could pose security risks.</p><p>An example user theme, <i>Steel Blue</i>, is available in the <a href="#root/xjSsCcvVZf6H">demo document</a>.</p><p><img src="api/images/uVF9DAmAmEWC/steel-blue.png" alt="Steel Blue Theme"></p><h3>Using Custom CSS for Specific Purposes</h3><p>In addition to full themes, Trilium allows for custom CSS that isn't tied to a theme. This can be particularly useful in scripting contexts, where you might want to modify specific UI elements, such as changing the colors of notes in the tree view.</p><h3>Applying Custom CSS</h3><p>To use custom CSS:</p><ol><li><strong>Create a CSS Code Note</strong>: Create a new <a href="#root/6f9hih2hXXZk">code note</a> with the <code>CSS</code> type.</li><li><strong>Add the </strong><code><strong>appCss</strong></code><strong> Label</strong>: Annotate the note with the <code>#appCss</code> <a href="#root/zEY4DaJG4YT5">label</a>.</li><li><strong>Write Your CSS</strong>: Add your custom CSS rules to the note.</li></ol><p>For example:</p><pre><code class="language-text-x-trilium-auto">/* Custom CSS to style specific elements */
  .tree-item {
      color: #ff6347; /* Change tree item color */
  }</code></pre><p>When Trilium's frontend starts, all notes labeled with <code>appCss</code> are automatically included in the style element of the HTML page.</p><p>After making changes, press <code>CTRL-R</code> to reload the frontend and apply your new styles.</p><figure class="image"><img style="aspect-ratio:897/720;" src="api/attachments/rwK3vuBgh7sY/image/image.png" width="897" height="720"></figure><h3>Styling Specific Notes in the Tree</h3><p>To apply specific styles to certain notes in the tree:</p><ul><li><strong>Use the </strong><code><strong>cssClass</strong></code><strong> Attribute</strong>: Add the <code>cssClass</code> <a href="#root/zEY4DaJG4YT5">attribute</a> to a note, and assign it a value representing the desired CSS class.</li><li><strong>Define an </strong><code><strong>iconClass</strong></code>: You can also define a custom icon for a note using the <code>iconClass</code> attribute, selecting from <a href="https://boxicons.com">Box Icons</a> or your own custom classes.</li></ul><p>For example, if you want to style notes of a specific type, such as notes containing PNG images, you can target them with classes like <code>type-image mime-image-png</code>.</p><h3>User-Provided Themes</h3><p>A gallery of user-created themes is available, showcasing the variety of customizations that the Trilium community has developed. For more information, visit the <a href="#root/VbjZvtUek0Ln">Theme Gallery</a>.</p><h3>Asset Path Management</h3><p>When referencing built-in assets like images in your custom themes or CSS, you can avoid hardcoding version numbers by using the <code>vX</code> alias. For example, instead of specifying <code>/assets/v0.57.0-beta/images/icon-grey.png</code>, you can use <code>/assets/vX/images/icon-grey.png</code> to keep your theme compatible with future versions of Trilium.</p>


blobId: XiTgCFVcEsMWx2JY43CB
dateModified: 2025-03-10 14:50:12.372+0200
utcDateModified: 2025-03-10 12:50:12.372Z
content:
  <p>Promoted attributes are <a href="#root/zEY4DaJG4YT5">attributes</a> which are considered important and thus are "promoted" onto the main note UI. See example below:</p><p><img src="api/images/rxH2Dm1jn6YT/promoted-attributes.png" alt=""></p><p>You can see the note having kind of form with several fields. Each of these is just regular attribute, the only difference is that they appear on the note itself.</p><p>Attributes can be pretty useful since they allow for querying and script automation etc. but they are also inconveniently hidden. This allows you to select few of the important ones and push them to the front of the user.</p><p>Now, how do we make attribute to appear on the UI?</p><h2>Attribute definition</h2><p>Attribute is always name-value pair where both name and value are strings.</p><p><i>Attribute definition</i> specifies how should this value be interpreted - is it just string, or is it a date? Should we allow multiple values or note? And importantly, should we <i>promote</i> the attribute or not?</p><figure class="image"><img style="aspect-ratio:932/749;" src="api/attachments/4EcBRWF9iCk2/image/image.png" width="932" height="749"></figure><p>You can notice tag attribute definition. These "definition" attributes define how the "value" attributes should behave.</p><p>So there's one attribute for value and one for definition. But notice how definition attribute is <a href="#root/bwZpz2ajCEwO">Inheritable</a>, meaning that it's also applied to all descendant note. So in a way, this definition is used for the whole subtree while "value" attributes are applied only for this note.</p><h3>Inverse relation</h3><p>Some relations always occur in pairs - my favorite example is on the family. If you have a note representing husband and note representing wife, then there might be a relation between those two of <code>isPartnerOf</code>. This is bidirectional relationship - meaning that if a relation is pointing from husband to wife then there should be always another relation pointing from wife to husband.</p><p>Another example is with parent - child relationship. Again these always occur in pairs, but in this case it's not exact same relation - the one going from parent to child might be called <code>isParentOf</code> and the other one going from child to parent might be called <code>isChildOf</code>.</p><p>Relation definition allows you to specify such "inverse relation" - for the relation you just define you specify which is the inverse relation. Note that in the second example we should have two relation definitions - one for <code>isParentOf</code> which defines <code>isChildOf</code> as inverse relation and then second relation definition for <code>isChildOf</code> which defines <code>isParentOf</code> as inverse relation.</p><p>What this does internally is that whenever we save a relation which has defined inverse relation, we check that this inverse relation exists on the relation target note. Similarly, when we delete relation, we also delete inverse relation on the target note.</p>


blobId: MaMw9Xywc4kGIeHwPNXq
dateModified: 2025-03-10 14:50:59.694+0200
utcDateModified: 2025-03-10 12:50:59.695Z
content:
  <p>In Trilium, attributes are key-value pairs assigned to notes, providing additional metadata or functionality. There are two primary types of attributes:</p><ol><li><strong>Labels</strong>: Simple key-value text records</li><li><strong>Relations</strong>: Named links to other notes</li></ol><p>These attributes play a crucial role in organizing, categorising, and enhancing the functionality of notes.</p><figure class="image"><img style="aspect-ratio:669/266;" src="api/attachments/P4eRVtGFoHh2/image/image.png" width="669" height="266"></figure><h2>Labels</h2><p>Labels in Trilium can be used for a variety of purposes:</p><ul><li><strong>Metadata</strong>: Assign labels with optional values for categorization, such as <code>#year=1999</code>, <code>#genre="sci-fi"</code>, or <code>#author="Neal Stephenson"</code></li><li><strong>Configuration</strong>: Labels can configure advanced features or settings</li><li><strong>Scripts and Plugins</strong>: Used to tag notes with special metadata, such as the "weight" attribute in the <a href="#root/R7abl2fc6Mxi">Weight Tracker</a></li></ul><p>Labels are also searchable, enhancing note retrieval.</p><h3>Common Labels for Advanced Configuration</h3><ul><li><code><strong>disableVersioning</strong></code>: Disables automatic versioning, ideal for large, unimportant notes like script libraries</li><li><code><strong>versioningLimit</strong></code>: Used to limit the number of revisions for a single note</li><li><code><strong>calendarRoot</strong></code>: Marks the note as the root for <a href="#root/l0tKav7yLHGF">day notes</a>. Only one note should carry this label</li><li><code><strong>archived</strong></code>: Hides notes from default search results and dialogs</li><li><code><strong>excludeFromExport</strong></code>: Excludes notes and their subtrees from export operations</li><li><code><strong>run</strong></code>: Specifies events to trigger scripts (e.g., <code>frontendStartup</code>, <code>hourly</code>)</li><li><code><strong>runAtHour</strong></code>: Defines specific hours for scripts to run, used with <code>#run=hourly</code></li><li><code><strong>disableInclusion</strong></code>: Prevents a script from being included in parent script executions</li><li><code><strong>sorted</strong></code>: Automatically sorts child notes alphabetically by title</li><li><code><strong>top</strong></code>: Keeps the note at the top of its parent's list, useful with <code>sorted</code></li><li><code><strong>hidePromotedAttributes</strong></code>: Hides certain attributes in the note's display</li><li><code><strong>readOnly</strong></code>: Sets the note to read-only mode, applicable to text and code notes</li><li><code><strong>autoReadOnlyDisabled</strong></code>: Disables automatic read-only mode for large notes</li><li><code><strong>appCss</strong></code>: Marks CSS notes used to modify Trilium’s appearance</li><li><code><strong>appTheme</strong></code>: Marks full CSS themes available in Trilium's options</li><li><code><strong>cssClass</strong></code>: Adds a CSS class to the note's representation in the tree</li><li><code><strong>iconClass</strong></code>: Adds a CSS class to the note's icon, useful for distinguishing notes visually. See <a href="#root/p9kXRFAkwN4o">note icons</a></li><li><code><strong>pageSize</strong></code>: Specifies the number of items per page in note listings</li><li><code><strong>customRequestHandler</strong></code><strong> and </strong><code><strong>customResourceProvider</strong></code>: Refer to <a href="#root/J5Ex1ZrMbyJ6">Custom request handler</a></li><li><code><strong>widget</strong></code>: Marks a note as a custom widget, added to Trilium's component tree</li><li><code><strong>workspace</strong></code><strong> and related attributes</strong>: See <a href="#root/9sRHySam5fXb">Workspace</a> for more details</li><li><code><strong>searchHome</strong></code>: Specifies the parent for new search notes</li><li><code><strong>inbox</strong></code>: Designates a default location for new notes created via the sidebar</li><li><code><strong>sqlConsoleHome</strong></code>: Default location for SQL console notes</li><li><code><strong>bookmarked</strong></code><strong> and </strong><code><strong>bookmarkFolder</strong></code>: See <a href="#root/u3YFHC9tQlpm">Bookmarks</a></li><li><code><strong>shareXXX</strong></code>: See <a href="#root/R9pX4DGra2Vt">Sharing</a></li><li><code><strong>keyboardShortcut</strong></code>: Assigns a keyboard shortcut to open the note</li><li><code><strong>displayRelations</strong></code><strong> and </strong><code><strong>hideRelations</strong></code>: Manages the display of note relations</li><li><code><strong>titleTemplate</strong></code>: See <a href="#root/47ZrP6FNuoG8">Default note title</a></li><li><code><strong>template</strong></code>: Makes the note available as a template</li><li><code><strong>toc</strong></code>: Controls the visibility of the table of contents</li><li><code><strong>color</strong></code>: Defines the color of the note in the tree and links</li><li><code><strong>hideChildrenOverview</strong></code>: Hides child notes in the parent note's editor</li><li><code><strong>viewType</strong></code>: Sets the view of child notes (grid or list)</li></ul><h2>Relations</h2><p>Relations define connections between notes, similar to links.</p><h3>Uses</h3><ul><li><strong>Metadata Relationships</strong>: For example, linking a book note to an author note</li><li><strong>Scripting</strong>: Attaching scripts to events or conditions related to the note</li></ul><h3>Common Relations</h3><ul><li><strong>Event-based Relations</strong>: Such as <code>runOnNoteCreation</code> or <code>runOnNoteChange</code>, which trigger scripts on specific actions</li><li><strong>Other Relations</strong>: Include <code>template</code>, <code>renderNote</code>, <code>widget</code>, and sharing-related relations</li></ul><h2>Multiplicity</h2><p>Attributes in Trilium can be "multivalued", meaning multiple attributes with the same name can coexist.</p><h2>Attribute Definitions and Promoted Attributes</h2><p>Special labels create "label/attribute" definitions, enhancing the organization and management of attributes. For more details, see <a href="#root/OFXdgB2nNk1F">Promoted attributes</a>.</p><h2>Attribute Inheritance</h2><p>Trilium supports attribute inheritance, allowing child notes to inherit attributes from their parents. For more information, see <a href="#root/bwZpz2ajCEwO">Attribute inheritance</a>.</p>


blobId: FvXjf5c7PbWkOMwqFptX
dateModified: 2025-03-10 14:52:08.599+0200
utcDateModified: 2025-03-10 12:52:08.601Z
content:
  <p>Trilium utilizes the powerful <a href="https://ckeditor.com/ckeditor-5/">CKEditor 5</a> as its text editing component.</p><h2>Formatting Options</h2><p>The Trilium text note interface does not display toolbars or formatting options by default. These can be accessed by:</p><p><img src="api/images/FtmPLgGmgZVC/text-notes-formatting-inline.png" alt="inline note formatting"></p><ol><li>Selecting text to bring up an inline toolbar.</li></ol><p><img src="api/images/oRWfJLUbb7j7/text-notes-formatting-block.png" alt="formating note block"> 2. Clicking on the block toolbar.</p><h2>Read-Only vs. Editing Mode</h2><p>Text notes are usually opened in edit mode. However, they may open in read-only mode under the following circumstances:</p><ul><li>The note is long and would take time to load, so it is opened in read-only mode by default for quicker access.</li><li>The note has a <code>readOnly</code> <a href="#root/zEY4DaJG4YT5">label</a>.</li></ul><p>In both cases, it is possible to switch back to editable mode using the <img src="api/attachments/WHhkza9Ibfkf/image/bx-edit-alt.svg?2025-03-10%2010:16:45.755Z%22%3E" width="24" height="24"> button at top right of page.</p><p>For more information, see&nbsp;<a class="reference-link" href="#root/BFs8mudNFgCS/CoFPLs3dRlXc">Read-Only Notes</a>.</p><h2>General Formatting</h2><p>Since Trilium uses CKEditor, all of its formatting options are available here. You may use the graphical toolbar shown above, or enter formatting such as markdown markdown directly in the text. Examples include:</p><ul><li><strong>Bold</strong>: Type <code>**text**</code> or <code>__text__</code></li><li><i>Italic</i>: Type <code>*text*</code> or <code>_text_</code></li><li><code>Code</code>: Type `text`</li><li><s>Strikethrough</s>: Type <code>~~text~~</code></li></ul><h3>Lists</h3><p>See&nbsp;<a class="reference-link" href="#root/iPIMuisry3hd/S6Xx8QIWTV66">Lists</a>.</p><h3>Blocks</h3><ul><li>Block quote: Start a line with <code>&gt;</code> followed by a space</li></ul><h3>Multi-Line Code Blocks</h3><p>To create a multi-line code block, start a line with "```[lang]", for example:</p><pre><code class="language-text-x-trilium-auto">if (1 &gt; 2) {
      console.log("Error in the matrix");
  }</code></pre><h3>Headings</h3><p>Create headings by starting a line with <code>##</code> for heading 2, <code>###</code> for heading 3, and so on up to heading 6. Note that <code>#</code> is reserved for the title.</p><h3>Horizontal Line</h3><p>Insert a horizontal line by starting a line with <code>---</code>.</p><h2>Markdown &amp; Autoformat</h2><p>CKEditor supports a markdown-like editing experience, recognizing syntax and automatically converting it to rich text.</p><p>Complete documentation for this feature is available in the <a href="https://ckeditor.com/docs/ckeditor5/latest/features/autoformat.html">CKEditor documentation</a>.</p><p>If autoformatting is not desirable, press <code>CTRL-Z</code> to revert the text to its original form.</p><p>Note: The use of <code>#</code> for Heading 1 is not supported because it is reserved for the title. Start with <code>##</code> for Heading 2. More information is available <a href="https://ckeditor.com/docs/ckeditor5/latest/features/headings.html#heading-levels">here</a>.</p><h2>Math Support</h2><p>Trilium provides math support through <a href="https://katex.org/">KaTeX</a>.</p><h2>Cutting Selection to Sub-Note</h2><p>When editing a document that becomes too large, you can split it into sub-notes:</p><ol><li>Select the desired text and cut it to the clipboard.</li><li>Create a new sub-note and name it.</li><li>Paste the content from the clipboard into the sub-note.</li></ol><p>Trilium can automate this process. Select some text within the note, and in the selection toolbar, click the scissors icon for the "cut &amp; pasted selection to sub-note" action. The heading is automatically detected and the new sub-note is named accordingly. You can also assign a keyboard shortcut for this action. This functionality is available through the block toolbar icon.</p><h2>Including a Note</h2><p>Text notes can "include" another note as a read only widget. This can be useful for e.g. including a dynamically generated chart (from scripts &amp; "render HTML" note) or other more advanced use cases.</p><p>This functionality is available in the block toolbar icon.</p>


blobId: OMvWBctDJ3ZueobX6dZW
dateModified: 2025-03-10 14:52:13.507+0200
utcDateModified: 2025-03-10 12:52:13.508Z
content:
  <p>Trilium utilizes the powerful <a href="https://ckeditor.com/ckeditor-5/">CKEditor 5</a> as its text editing component.</p><h2>Formatting Options</h2><p>The Trilium text note interface does not display toolbars or formatting options by default. These can be accessed by:</p><p><img src="api/images/FtmPLgGmgZVC/text-notes-formatting-inline.png" alt="inline note formatting"></p><ol><li>Selecting text to bring up an inline toolbar.</li></ol><p><img src="api/images/oRWfJLUbb7j7/text-notes-formatting-block.png" alt="formating note block"> 2. Clicking on the block toolbar.</p><h2>Read-Only vs. Editing Mode</h2><p>Text notes are usually opened in edit mode. However, they may open in read-only mode under the following circumstances:</p><ul><li>The note is long and would take time to load, so it is opened in read-only mode by default for quicker access.</li><li>The note has a <code>readOnly</code> <a href="#root/zEY4DaJG4YT5">label</a>.</li></ul><p>In both cases, it is possible to switch back to editable mode using the <img src="api/attachments/yGknq3nsWpef/image/bx-edit-alt.svg?2025-03-10%2010:16:45.755Z%22%3E" width="24" height="24"> button at top right of page.</p><p>For more information, see&nbsp;<a class="reference-link" href="#root/BFs8mudNFgCS/CoFPLs3dRlXc">Read-Only Notes</a>.</p><h2>General Formatting</h2><p>Since Trilium uses CKEditor, all of its formatting options are available here. You may use the graphical toolbar shown above, or enter formatting such as markdown markdown directly in the text. Examples include:</p><ul><li><strong>Bold</strong>: Type <code>**text**</code> or <code>__text__</code></li><li><i>Italic</i>: Type <code>*text*</code> or <code>_text_</code></li><li><code>Code</code>: Type `text`</li><li><s>Strikethrough</s>: Type <code>~~text~~</code></li></ul><h3>Lists</h3><p>See&nbsp;<a class="reference-link" href="#root/iPIMuisry3hd/S6Xx8QIWTV66">Lists</a>.</p><h3>Blocks</h3><ul><li>Block quote: Start a line with <code>&gt;</code> followed by a space</li></ul><h3>Multi-Line Code Blocks</h3><p>To create a multi-line code block, start a line with "```[lang]", for example:</p><pre><code class="language-text-x-trilium-auto">if (1 &gt; 2) {
      console.log("Error in the matrix");
  }</code></pre><h3>Headings</h3><p>Create headings by starting a line with <code>##</code> for heading 2, <code>###</code> for heading 3, and so on up to heading 6. Note that <code>#</code> is reserved for the title.</p><h3>Horizontal Line</h3><p>Insert a horizontal line by starting a line with <code>---</code>.</p><h2>Markdown &amp; Autoformat</h2><p>CKEditor supports a markdown-like editing experience, recognising syntax and automatically converting it to rich text.</p><figure class="image"><img style="aspect-ratio:669/266;" src="api/attachments/lHWL7KkEhmM3/image/image.png" width="669" height="266"></figure><p>Complete documentation for this feature is available in the <a href="https://ckeditor.com/docs/ckeditor5/latest/features/autoformat.html">CKEditor documentation</a>.</p><p>If autoformatting is not desirable, press <code>CTRL-Z</code> to revert the text to its original form.</p><p>Note: The use of <code>#</code> for Heading 1 is not supported because it is reserved for the title. Start with <code>##</code> for Heading 2. More information is available <a href="https://ckeditor.com/docs/ckeditor5/latest/features/headings.html#heading-levels">here</a>.</p><h2>Math Support</h2><p>Trilium provides math support through <a href="https://katex.org/">KaTeX</a>.</p><h2>Cutting Selection to Sub-Note</h2><p>When editing a document that becomes too large, you can split it into sub-notes:</p><ol><li>Select the desired text and cut it to the clipboard.</li><li>Create a new sub-note and name it.</li><li>Paste the content from the clipboard into the sub-note.</li></ol><p>Trilium can automate this process. Select some text within the note, and in the selection toolbar, click the scissors icon for the "cut &amp; pasted selection to sub-note" action. The heading is automatically detected and the new sub-note is named accordingly. You can also assign a keyboard shortcut for this action. This functionality is available through the block toolbar icon.</p><h2>Including a Note</h2><p>Text notes can "include" another note as a read only widget. This can be useful for e.g. including a dynamically generated chart (from scripts &amp; "render HTML" note) or other more advanced use cases.</p><p>This functionality is available in the block toolbar icon.</p>


blobId: xNVcZZlJSVdzePByYogL
dateModified: 2025-03-10 14:53:00.405+0200
utcDateModified: 2025-03-10 12:53:00.406Z
content:
  <p>One of the Trilium's goals is to provide fast and comfortable navigation between notes.</p><h2>Backwards and forward</h2><p>You can use alt-left and alt-right to move back and forward in history of viewed pages.</p><p>This works identically to browser backwards / forwards, it's actually using built-in browser support for this.</p><figure class="image"><img style="aspect-ratio:669/266;" src="api/attachments/jDuwVaU8bNtG/image/image.png" width="669" height="266"></figure><h2>Jump to note</h2><p>This is useful to quickly find and view arbitrary note - click on <code>Jump to</code> button on the top or press <code>CTRL-J</code>. Then type part of the note name and autocomplete will help you pick the desired note.</p><p><img src="api/images/snfWRIih71MM/jump-to.gif" alt=""></p><h3>Recent notes</h3><p>Jump to note also has the ability to show the list of recently viewed / edited notes and quickly jump to it.</p><p>To access this functionality, click on <code>Jump to</code> button on the top. By default, (when nothing is entered into autocomplete), this dialog will show the list of recent notes.</p><p>Alternatively you can click on the "time" icon on the right.</p><p><img src="api/images/wpFu8PhUu7e7/recent-notes.gif" alt=""></p>


blobId: hCTgAGtlt4JkfOFb7bQS
dateModified: 2025-03-10 14:55:04.011+0200
utcDateModified: 2025-03-10 12:55:04.012Z
content:
  <p>A <strong>Book Note</strong> in Trilium is a special type of <a href="#root/BFs8mudNFgCS">note</a> designed to display the contents of its child notes sequentially, creating a linear, book-like reading experience. This format is particularly useful for viewing multiple smaller notes in a cohesive, continuous manner.</p><figure class="image"><img style="aspect-ratio:842/665;" src="api/attachments/lpq3QC1C5LWg/image/image.png" width="842" height="665"></figure><p>In the example above, the "node.js" note on the left panel contains several child notes. The right panel displays the content of these child notes as a single continuous document.</p><h2>Features</h2><h3>Linear Display</h3><p>The Book Note format compiles the contents of all child notes into one continuous view. This makes it ideal for reading extensive information broken into smaller, manageable segments.</p><h3>Grid View Option</h3><p>Trilium also offers a "Grid View" option within the Book Note properties. This view presents the child notes in a grid format, allowing for a more visual navigation experience.</p><figure class="image"><img style="aspect-ratio:1297/845;" src="api/attachments/BmpgL4ol4jJo/image/image.png" width="1297" height="845"></figure><p>Switching between these views can be easily managed through the Book Note's settings (or <code>viewType</code> attribute), allowing users to choose the format that best suits their reading or navigation preferences.</p>


blobId: fTfsmbKPVzj9yMos50J4
dateModified: 2025-03-10 14:56:53.013+0200
utcDateModified: 2025-03-10 12:56:53.018Z
content:
  <h2>Choose the setup</h2><p><strong>Local only desktop/laptop</strong> - Allows a single instance on a desktop and will save the notes locally on that desktop.</p><ol><li><a href="#root/poXkQfguuA0U">Desktop installation</a></li></ol><p><strong>Server with web only access</strong> - Installs the application on the server and allows access from any web browser on any device, including mobile.</p><ol><li><a href="#root/WOcw2SLH6tbX">Server installation</a></li><li><a href="#root/RDslemsQ6gCp">Mobile frontend</a> (optional)</li><li><a href="https://heroku.com/deploy?template=https://github.com/feilongfl/trilium-heroku"><img src="api/images/JXFeNgU8Xnp1/home-button.svg" alt="Deploy"></a> %%{WARNING}%%</li><li><a href="https://www.pikapods.com/pods?run=trilium-next">PikaPods managed hosting</a></li></ol><p><strong>Combination of server and desktop/laptop</strong> - Install the application on both a server, for web access and data synchronization, and desktop instance(s). This allows all the data to be stored on the server and either accessed from the web browser, or the desktop application. The desktop application will sync and store the data locally so that it can be used when offline.</p><ol><li><a href="#root/WOcw2SLH6tbX">Server installation</a></li><li><a href="#root/RDslemsQ6gCp">Mobile frontend</a> (optional)</li><li><a href="#root/poXkQfguuA0U">Desktop installation</a></li><li><a href="#root/cbkrhQjrkKrh">Synchronization</a></li></ol><h2>Basic concepts</h2><ol><li>Understand <a href="#root/BFs8mudNFgCS">Note</a></li></ol>


blobId: BJxKDRGiqDIICcdNcbD7
dateModified: 2025-03-10 14:57:30.399+0200
utcDateModified: 2025-03-10 12:57:30.400Z
content:
  <figure class="image"><img style="aspect-ratio:1003/683;" src="api/attachments/Ah5QpwUUEGf8/image/image.png" width="1003" height="683"></figure><p>The <code>Weight Tracker</code> is a <a href="#root/GLks18SNjxmC">Script API</a> showcase present in the <a href="#root/wX4HbRucYSDD">demo notes</a>.</p><p>By adding <code>weight</code> as a <a href="#root/OFXdgB2nNk1F">promoted attribute</a> in the <a href="#root/KC1HB96bqqHX">template</a> from which <a href="#root/l0tKav7yLHGF">day notes</a> are created, you can aggregate the data and plot weight change over time.</p><h2>Implementation</h2><p>The <code>Weight Tracker</code> note in the screenshot above is of the type <code>Render Note</code>. That type of note doesn't have any useful content itself. Instead it is a placeholder where a <a href="#root/CdNpE2pqjmI6">script</a> can render its output.</p><p>Scripts for <code>Render Notes</code> are defined in a <a href="#root/zEY4DaJG4YT5">relation</a> called <code>~renderNote</code>. In this example, it's the <code>Weight Tracker</code>'s child <code>Implementation</code>. The Implementation consists of two <a href="#root/6f9hih2hXXZk">code notes</a> that contain some HTML and JavaScript respectively, which load all the notes with a <code>weight</code> attribute and display their values in a chart.</p><p>To actually render the chart, we're using a third party library called <a href="https://www.chartjs.org/">chart.js</a> which is imported as an attachment, since it's not built into Trilium.</p><h3>Code</h3><p>Here's the content of the script which is placed in a <a href="#root/6f9hih2hXXZk">code note</a> of type <code>JS Frontend</code>:</p><pre><code class="language-text-x-trilium-auto">async function getChartData() {
      const days = await api.runOnBackend(async () =&gt; {
          const notes = api.getNotesWithLabel('weight');
          const days = [];

          for (const note of notes) {
              const date = note.getLabelValue('dateNote');
              const weight = parseFloat(note.getLabelValue('weight'));

              if (date &amp;&amp; weight) {
                  days.push({ date, weight });
              }
          }

          days.sort((a, b) =&gt; a.date &gt; b.date ? 1 : -1);

          return days;
      });

      const datasets = [
          {
              label: "Weight (kg)",
              backgroundColor: 'red',
              borderColor: 'red',
              data: days.map(day =&gt; day.weight),
              fill: false,
              spanGaps: true,
              datalabels: {
                  display: false
              }
          }
      ];

      return {
          datasets: datasets,
          labels: days.map(day =&gt; day.date)
      };
  }

  const ctx = $("#canvas")[0].getContext("2d");

  new chartjs.Chart(ctx, {
      type: 'line',
      data: await getChartData()
  });</code></pre><h2>How to remove the Weight Tracker button from the top bar</h2><p>In the link map of the <code>Weight Tracker</code>, there is a note called <code>Button</code>. Open it and delete or comment out its contents. The <code>Weight Tracker</code> button will disappear after you restart Trilium.</p>


blobId: xKV7bqU97DlXaYhY7BBF
dateModified: 2025-03-10 14:57:54.858+0200
utcDateModified: 2025-03-10 12:57:54.859Z
content:
  <p>Trilium supports storing and displaying images. Supported formats are JPEG, PNG and GIF.</p><p>An image can be uploaded in the form of note's <a href="#root/0vhv7lsOLy82">attachment</a> or as a standalone <a href="#root/kBrnXNG3Hplm">note</a> placed into the <a href="#root/kBrnXNG3Hplm">note tree</a>. Its reference can be copied into a text note, in order to display it in the text itself.</p><h2>Uploading images</h2><p>To add an image to the note, simply drag it from file explorer onto the note editor inside Trilium and the image will be uploaded.</p><figure class="image"><img style="aspect-ratio:1003/683;" src="api/attachments/PUjxzv10IJkx/image/image.png" width="1003" height="683"></figure><p>Alternatively you can click on block toolbar and then on "Insert image":</p><figure class="image"><img style="aspect-ratio:443/144;" src="api/attachments/MTsRB4C0yvKX/image/image.png" width="443" height="144"></figure><p>You can also copy and paste an image from web - the image will be (asynchronously) downloaded and embedded.</p><h2>Compression</h2><p>Since Trilium isn't really meant to be primary storage for image data, it attempts to compress and resize (with pretty aggressive settings) uploaded images before storing them to the database. You may then notice some quality degradation. Basic quality settings is available in Options -&gt; Other.</p><p>If you want to save images in their original resolution, it is recommended to save them as attachment to note (top-right "Note actions -&gt; Import files").</p>


blobId: QMHsVsikfIY7JZDhnbnW
dateModified: 2025-03-10 14:59:44.476+0200
utcDateModified: 2025-03-10 12:59:44.477Z
content:
  <p>Note map is a visualisation of connections between notes.</p><p>This provides an insight into a structure ("web") of notes.</p><p>There are two types of note map:</p><h2>Link Map</h2><p>Shows <a href="#root/zEY4DaJG4YT5">relations</a> between notes:</p><figure class="image"><img style="aspect-ratio:1059/757;" src="api/attachments/scmGuoLQPj8C/image/image.png" width="1059" height="757"></figure><h2>Tree Map</h2><p>Shows hierarchical map of notes:</p><figure class="image"><img style="aspect-ratio:1068/814;" src="api/attachments/F48iB3BbITHb/image/image.png" width="1068" height="814"></figure><h2>See also</h2><p><a href="#root/iRwzGnHPzonm">Relation map</a> is a similar concept, with some differences:</p><ul><li>note map is automatically generated while relation map must be created manually</li><li>relation map is a type of note while a link map is just virtual visualization</li></ul>


blobId: OyYOYBxgU9LpYd6nera8
dateModified: 2025-03-10 15:00:09.614+0200
utcDateModified: 2025-03-10 13:00:09.615Z
content:
  <p>Trilium is an offline-first note-taking application that stores all data locally on the desktop client. However, it also offers the option to set up synchronization with a server instance, allowing multiple desktop clients to sync with a central server. This creates a star-shaped topology:</p><figure class="image"><img style="aspect-ratio:150/150;" src="api/attachments/s3fKDqHslToK/image/image.png" width="150" height="150"></figure><p>In this setup, a central server (referred to as the <i>sync server</i>) and multiple <i>client</i> (or <i>desktop</i>) instances synchronize with the sync server. Once configured, synchronization is automatic and ongoing, requiring no manual intervention.</p><h2>Setting Up Synchronization</h2><h3>Security Considerations</h3><p>Setting up the server securely is critical and can be complex. It is crucial to use a valid <a href="#root/l2VkvOwUNfZj">TLS certificate</a> (HTTPS) rather than an unencrypted HTTP connection to ensure security and avoid potential vulnerabilities.</p><h3>Synchronizing a Desktop Instance with a Sync Server</h3><p>This method is used when you already have a desktop instance of Trilium and want to set up a sync server on your web host.</p><ol><li><strong>Server Deployment</strong>: Ensure your server instance is deployed but uninitialized.</li><li><strong>Desktop Configuration</strong>: Open your desktop instance, navigate to Options -&gt; Sync tab -&gt; Sync configuration, and set the "Server instance address" to your sync server's address. Click Save.</li></ol><p><img src="api/images/676Ekdv73T7I/sync-config.png" alt="screenshot of the sync settings options modal"></p><ol><li><strong>Testing Sync</strong>: Click the "Test sync" button to verify the connection to the sync server. If successful, the client will start pushing all data to the server instance. This process may take some time, but you can continue using Trilium. Periodically check the server instance to confirm when the sync is complete. Once finished, you should see the login screen on the server.</li></ol><h3>Synchronizing a Desktop Instance from a Sync Server</h3><p>This method is used when you already have a sync server and want to configure a new desktop instance to sync with it.</p><ol><li><strong>Desktop Setup</strong>: Follow the <a href="#root/poXkQfguuA0U">desktop installation page</a>.</li><li><strong>Initial Configuration</strong>: When prompted, choose the option to set up sync with a sync server.</li></ol><p><img src="api/images/SDHWNDsB68aJ/sync-init.png" alt="screenshot of the sync from server setup page"></p><ol><li><strong>Server Details</strong>: Configure the Trilium server address and enter the correct username and password for authentication.</li><li><strong>Finish Setup</strong>: Click the "Finish setup" button. If successful, you will see the following screen:</li></ol><p><img src="api/images/qGTyyKX4TceE/sync-in-progress.png" alt="screenshot of the sync page"></p><p>Once synchronization is complete, you will be automatically redirected to the Trilium application.</p><h2>Proxy Configuration</h2><p>Two proxy setups are supported:</p><ul><li><strong>Explicit Proxy Configuration</strong>: Set the proxy server in Options / Sync. Only unauthenticated proxy servers are supported.</li><li><strong>System Proxy Settings</strong>: If no proxy server is explicitly configured, Trilium will use the system proxy settings.</li></ul><h2>Troubleshooting</h2><h3>Date/Time Synchronization</h3><p>For successful synchronization, both client and server must have the same date and time, with a tolerance of up to five minutes.</p><h3>Certificate Issues</h3><p>When using TLS, Trilium will verify the server certificate. If verification fails (e.g., due to self-signed certificates or certain corporate proxies), you can run the Trilium client with the <code>NODE_TLS_REJECT_UNAUTHORIZED</code> environment variable set to <code>0</code>:</p><pre><code class="language-text-x-trilium-auto">export NODE_TLS_REJECT_UNAUTHORIZED=0</code></pre><p>This will disable TLS certificate verification, significantly reducing security and exposing the setup to MITM attacks. It is strongly recommended to use a valid signed server certificate. Newer Trilium versions include a script called <code>trilium-no-cert-check.sh</code> for this purpose.</p><h3>Conflict Resolution</h3><p>If you edit the same note on multiple instances before synchronization, Trilium resolves conflicts by retaining the newer change and discarding the older one. The older version remains accessible in <a href="#root/vZWERwf8U3nx">note revisions</a>, allowing data recovery if needed.</p><h3>Hash Check</h3><p>After each synchronization, Trilium computes a hash of all synced data on both the client and the sync server. If there is a discrepancy, Trilium will automatically initiate a recovery mechanism to resolve the issue.</p>


