docs(wiki): bring every page up to the next release; admin settings, user defaults and notifications get pages of their own

This commit is contained in:
Maurice
2026-10-01 19:40:22 +02:00
parent cf3818cb66
commit 05b53d024e
87 changed files with 1078 additions and 394 deletions
+1 -1
View File
@@ -63,7 +63,7 @@ When an admin leaves the instance configuration blank, each user can set up thei
There you pick a **Provider** (only **OpenAI** or **Anthropic**), a **Model** id and an **API key**, which is stored encrypted; leave the key blank to keep the current one. There is no personal Base URL. The address the server calls is instance configuration, so a local Ollama model can only be set up by an admin on the addon. The server refuses a personal base URL or a personal `local` provider from anyone, admins included.
**Model reads images** decides whether photos are offered and sent to your model. PDFs are not affected: only Anthropic gets the raw PDF, every other provider the extracted text.
The **Model reads images** switch decides whether photos are offered and sent to your model, both for the booking import and for [Scan receipt](Budget-Tracking#scanning-a-receipt) in Costs. PDFs are not affected: only Anthropic gets the raw PDF, every other provider the extracted text.
> **Precedence:** a model set by the admin for the whole instance always wins. Personal settings only count when there is none.
+6 -4
View File
@@ -47,8 +47,8 @@ On every day from the check-in day to the check-out day, the **Accommodation** s
![The day details panel with the weather, the day's bookings and the stay card](assets/DayDetails.png)
- **The head** of the card shows the place's photo or a hotel icon, its name and address. On the check-in day it is tinted green and says **CHECK-IN**, on the check-out day red with **CHECK-OUT**; a stay that starts and ends on the same day says both. The nights in between are untinted.
- **The fields** under it: **Check-in** (a single time, or the window from the earliest to the latest time), **Check-out** and **Confirmation**. The code is blurred when **Blur Booking Codes** is on in your [settings](Display-Settings); hovering or clicking it reveals it.
- **Reservation**: the linked booking with its title, status and code. Click it to open the booking's detail.
- **The fields** under it show only the time that matters on that day: **Check-in** (a single time, or the window from the earliest to the latest time) on the check-in day, **Check-out** on the check-out day, and neither on the nights in between. **Confirmation** shows on every day. The code is blurred when **Blur Booking Codes** is on in your [settings](Display-Settings); hovering or clicking it reveals it.
- **Reservation**: the linked booking with its title, its status (**Confirmed** or **Pending**) and code. Click it to open the booking's detail.
- For members who can edit days: the pencil (**Edit accommodation**) opens the stay editor, and the **X** (**Remove**) deletes the stay straight away, together with its booking and the expenses linked to that booking.
**Add accommodation** at the foot of the section adds another stay, for example a second hotel on a transfer day.
@@ -61,13 +61,15 @@ Stays appear as pills in the head band of each day card in the days column, with
- **Red icon**: the check-out day.
- **Grey icon**: the nights in between.
Rest the pointer on a pill for *Check-in: Hotel Adler* or *Check-out: Hotel Adler*. Clicking it opens the place in the [place inspector](Places-and-Search#the-place-inspector). Stays never appear as rows in the day's timeline; the pill and the day details are where they show.
Rest the pointer on a pill for *Check-in: Hotel Adler* or *Check-out: Hotel Adler*. Clicking the name opens the place in the [place inspector](Places-and-Search#the-place-inspector). A stay with a booking has a second button at the end of the pill, the ticket (*Open booking*), which opens that booking's detail. The place inspector of the hotel lists its stays under **Bookings** as well, so the booking is one click away from the map too. Stays never appear as rows in the day's timeline; the pill and the day details are where they show.
A stay whose booking is still **Pending** gets a dashed, tinted pill, and its tooltip ends in *(Pending)*. On the map, the hotel's marker is drawn with a dashed ring and a lighter face until the booking is **Confirmed**, see [Map Features](Map-Features#place-markers).
![A day card with the stay pill in its head band](assets/PlanDayCard.png)
## In the Reservations panel
On the Bookings tab, the card of an Accommodation booking shows the check-in and check-out times among its fields, and its address. Its detail shows the check-in day, the check-out day and the number of nights as tiles at the top, with the times beside the days, and names the linked stay under **Accommodation**. See [Reservations and Bookings](Reservations-and-Bookings).
On the Bookings tab, an Accommodation booking shows up in all three views (**Cards**, **List** and **Timeline**) like any other booking. Its card shows the check-in and check-out times among its fields, and its address. Its detail shows the check-in day, the check-out day and the number of nights as tiles at the top, with the times beside the days, and names the linked stay under **Accommodation**. See [Reservations and Bookings](Reservations-and-Bookings).
## On the route
+1 -1
View File
@@ -26,7 +26,7 @@ The following addons are registered in the system (defined in `server/src/db/see
| `collections` | global | A personal, server-wide library of saved places in named lists, with idea/want/visited status, categories, and fusion sharing with per-member roles. See [Collections](Collections). |
| `airtrail` | integration | Sync flights from your self-hosted AirTrail instance into trips. |
| `dawarich` | integration | Read the stays and recorded routes of each user's own Dawarich instance, offered as suggestions to confirm. Read-only, nothing is written back. See [Dawarich](Dawarich). |
| `llm_parsing` | integration | **AI Parsing**: an LLM fallback that extracts bookings from confirmation files KDE Itinerary can't read. See [AI-Booking-Import](AI-Booking-Import). |
| `llm_parsing` | integration | **AI Parsing**: an LLM fallback that extracts bookings from confirmation files KDE Itinerary can't read. With a model that reads images it also takes photos and scanned PDFs, and Costs gets **Scan receipt**. See [AI-Booking-Import](AI-Booking-Import) and [Budget-Tracking](Budget-Tracking#scanning-a-receipt). |
| `naver_list_import` | integration | Import places from shared Naver Maps lists directly into a trip. |
+4 -4
View File
@@ -1,6 +1,6 @@
# Admin: Addons
The **Addons** tab lets you enable or disable optional features for the entire TREK instance. Toggling an addon affects all users immediately: disabling one hides its UI elements and blocks its API routes instance-wide.
The **Addons** tab (in the **Configuration** group of the admin side navigation) lets you enable or disable optional features for the entire TREK instance. Toggling an addon affects all users immediately: disabling one hides its UI elements and blocks its API routes instance-wide.
![Addon overview](assets/Addons-Overview.png)
@@ -10,13 +10,13 @@ Each addon toggle controls a feature set. When you disable an addon, users lose
## Addon categories
Addons are grouped into three categories, shown as labeled sections.
Addons are grouped into three columns side by side: **Trip**, **Global** and **Integration**. Each column's head names the type with a short hint and counts how many of its addons are on, and the head of the **Addons** card shows the total as a pill (for example `9/14`; hover it for **{enabled} of {total} enabled**). Each addon is a tile with its icon, name, description and switch; its sub-toggles or settings open underneath the tile while it is on.
### Trip addons
Trip addons add per-trip feature panels. They appear in every trip where the addon is enabled.
The default trip addons are: **Lists**, **Costs**, **Documents** and **Collab** (all enabled by default), and **Road trip** (disabled by default). The exact list is determined by what is registered in your TREK database.
The trip addons are: **Lists**, **Costs**, **Documents** and **Collab** (all enabled by default), and **Road trip** (disabled by default). The exact list is determined by what is registered in your TREK database.
**Sub-toggles on trip addons:**
@@ -58,7 +58,7 @@ Integration addons connect TREK to external services. Most of them need addition
## Enabling or disabling an addon
Click the toggle switch on any addon row. The change is applied immediately; no save button is needed. A brief success toast confirms the update.
Click the switch on any addon tile. The change is applied immediately; no save button is needed. A brief success toast confirms the update.
If a toggle fails (e.g., network error), it rolls back to its previous state.
+13 -9
View File
@@ -1,6 +1,6 @@
# Admin — Categories
# Admin: Categories
The **Personalization** tab → **Categories** section lets you manage global place categories. Categories are shared across all trips and all users on the instance.
The **Categories** card on **Admin > Personalization** lets you manage global place categories. Categories are shared across all trips and all users on the instance.
![Category Manager](assets/CategoryManager.png)
@@ -15,25 +15,29 @@ A category is a label consisting of a name, a color, and an icon. Users assign c
## Creating a category
Click **New Category** (top-right of the category section). A form appears inline:
Click **New Category** (top right of the card). A dialog opens:
1. **Name** — required. Free-text label for the category.
2. **Icon** — a scrollable grid of ~47 curated Lucide icons (Pin, Hotel, Restaurant, Transport, Nature, etc.). Click any icon to select it. The default icon is `MapPin`.
3. **Color** — 12 preset color swatches plus a custom color picker (pipette button). The default color is `#6366f1` (indigo). The 12 presets are:
1. **Category name**: required. Type it into the dialog's head; **Enter** saves.
2. **Icon**: a grid of 47 curated Lucide icons (Pin, Hotel, Restaurant, Transport, Nature and so on). Click an icon to select it. The default icon is `MapPin`.
3. **Color**: 12 preset swatches plus **Choose custom color** (pipette button). The default color is `#6366f1` (indigo). The 12 presets are:
`#6366f1` · `#8b5cf6` · `#ec4899` · `#ef4444` · `#f97316` · `#f59e0b` · `#10b981` · `#06b6d4` · `#3b82f6` · `#84cc16` · `#6b7280` · `#1f2937`
4. A **live preview** chip shows how the category will appear to users as you make selections.
4. **Preview**: a chip shows how the category will look to users as you make selections.
Click **Create** to save.
## Editing a category
Click the pencil icon on any category row. The same form appears in-place with the existing values pre-filled. Change any field and click **Update**.
Click the pencil icon on any category row. The same dialog opens with the existing values filled in. Change any field and click **Update**.
## Deleting a category
Click the trash icon on a category row and confirm. Deletion sets `category_id` to `NULL` on any places that had the category assigned — the places themselves are not affected, they become uncategorized.
Click the trash icon on a category row and confirm in the dialog (**Delete category? Places in this category will not be deleted.**). Deletion sets `category_id` to `NULL` on any places that had the category assigned: the places themselves are not affected, they become uncategorized.
## Category picked automatically
When a user adds a place from the search or from a map POI, TREK picks the matching category for them. It reads what the result says it is (Google types, the OpenStreetMap tag or the TREK Places category), such as hotel, restaurant, cafe or bar, museum, shop, station, beach, park or sports, and looks for a category of that kind. Because categories are named freely, a category is recognised by words in its name first (for example "Hotel", "Accommodation", "Restaurant", "Cafe", "Museum", "Shopping", "Transport", "Beach", "Nature", "Activity") and then by its icon. When nothing matches, the field stays empty. Naming categories plainly, or giving them the obvious icon, makes the guess work.
## List ordering
+6 -6
View File
@@ -1,12 +1,12 @@
# Admin — GitHub Releases
# Admin: GitHub Releases
The **GitHub** tab shows the TREK release history fetched from GitHub and provides links to community resources and support options.
The **GitHub** tab (in the **Integrations** group of the admin side navigation) shows the TREK release history fetched from GitHub and provides links to community resources and support options.
![GitHub tab](assets/GithubReleases.png)
## Support and resources
Six cards at the top of the tab link to external resources:
The **About** card at the top of the tab holds six tiles that link to external resources:
| Card | Link |
|------|------|
@@ -19,10 +19,10 @@ Six cards at the top of the tab link to external resources:
## Release timeline
Below the support cards, a chronological timeline lists GitHub releases for the `liketrek/TREK` repository. Each entry shows:
Below it, the **Release History** card holds a chronological timeline lists GitHub releases for the `liketrek/TREK` repository. Each entry shows:
- **Version tag** (e.g., `v2.9.14`)
- A **Latest** badge on the first (most recent) entry in the displayed list
- A **Latest** badge on the first (most recent) entry in the displayed list, and a **Pre-release** badge on pre-releases
- **Release date** and author
- A **Show details / Hide details** toggle that expands the release notes (a small Markdown subset rendered inline: `##` and `###` headings, `-` or `*` list items, **bold**, `code` and http(s) links; anything else is shown as plain text)
@@ -30,7 +30,7 @@ Pre-release entries are hidden unless the server has both found a newer version
Releases load 10 at a time. Click **Load more** at the bottom of the timeline to fetch additional pages.
If the admin API request fails, the timeline section shows an error message. If the server cannot reach the GitHub API, the timeline displays no releases (the server returns an empty list rather than an error).
If the admin API request fails, the card shows **Failed to load releases**. If the server cannot reach the GitHub API, the timeline displays no releases (the server returns an empty list rather than an error).
## Version check
+15 -19
View File
@@ -1,6 +1,6 @@
# Admin — MCP Tokens
# Admin: MCP Tokens
The **MCP Access** panel shows all active MCP OAuth sessions and API tokens across every user on the instance. As an admin you can revoke sessions and delete tokens.
The **MCP Access** tab (in the **Integrations** group of the admin side navigation) shows all active MCP OAuth sessions and API tokens across every user on the instance. As an admin you can revoke sessions and delete tokens.
This panel is only visible when the **MCP addon** is enabled in the [Admin-Addons](Admin-Addons) panel.
@@ -10,16 +10,14 @@ This panel is only visible when the **MCP addon** is enabled in the [Admin-Addon
OAuth sessions are created when a user authorizes an MCP client via the OAuth 2.1 flow. These are the recommended way to connect MCP clients to TREK.
**Columns:**
Each row of the **OAuth Sessions** card (the count sits beside its title) shows:
| Column | Description |
|--------|-------------|
| Client | The name of the registered OAuth client. Granted scopes are shown as badges below the name (up to 6 are shown; click "+N more" to expand) |
| Owner | The username of the user who authorized the session |
| Created | Date the session was established |
| (actions) | Trash icon button to revoke |
- **Client**: the name of the registered OAuth client, with the granted scopes as badges below it (up to 6 are shown; click **+N more** to expand, **show less** to collapse)
- **Owner**: the user who authorized the session
- **Created**: the date the session was established
- a trash button to revoke it
**Revoking a session:** Click the trash icon on the row and confirm. The session is invalidated immediately and the revocation is recorded in the audit log. The user's MCP client will need to re-authorize before it can make further requests.
**Revoking a session:** Click the trash icon on the row and confirm in the **Revoke Session** dialog. The session is invalidated immediately and the revocation is recorded in the audit log. The user's MCP client will need to re-authorize before it can make further requests.
OAuth access tokens use the prefix `trekoa_`.
@@ -27,17 +25,15 @@ OAuth access tokens use the prefix `trekoa_`.
API tokens are long-lived tokens that users create in their personal settings. They are identified by the `trek_` prefix.
**Columns:**
Each row of the **API Tokens** card shows:
| Column | Description |
|--------|-------------|
| Token name | The label the user gave the token, with its truncated prefix shown below |
| Owner | The username of the user who created it |
| Created | Date the token was created |
| Last used | Date of the most recent API call using this token, or "Never" if unused |
| (actions) | Trash icon button to delete |
- the name the user gave the token, with its prefix below it
- **Owner**: the user who created it
- **Created**: the date the token was created
- **Last Used**: the date of the most recent API call with this token, or **Never**
- a trash button to delete it
**Deleting a token:** Click the trash icon and confirm. The token is invalidated immediately. The user must create a new token in their settings if they still need access.
**Deleting a token:** Click the trash icon and confirm in the **Delete Token** dialog. The token is invalidated immediately. The user must create a new token in their settings if they still need access.
## Related pages
+91
View File
@@ -0,0 +1,91 @@
# Admin: Notifications
The **Notifications** tab (in the **Integrations** group of the admin side navigation, `/admin?tab=notifications`) decides which delivery channels users can pick, where admin alerts go, and how every user's notification settings start. What a user then chooses for themselves, and what each channel delivers, is described in [Notifications](Notifications).
On a wide screen the cards sit in two columns: the channels users receive on the left, the admin's own targets and alerts on the right. **Defaults for users** runs across the full width below both. On a narrow screen everything stacks in that order.
## Channels for users
Each channel card has a switch in its head. A channel that is switched on appears as a column in every user's notification settings; one that is off does not. The switches save at once. **All four are off on a fresh install**, so users only have in-app notifications until you switch a channel on.
### Email (SMTP)
SMTP configuration for sending email notifications. The fields stay visible while the switch is off, but greyed out and out of reach.
| Field | Example |
|-------|---------|
| **SMTP Host** | `mail.example.com` |
| **SMTP Port** | `587` |
| **SMTP User** | `trek@example.com` |
| **SMTP Password** | shown as `••••••••` once saved |
| **From Address** | `trek@example.com` |
**Skip TLS certificate check** allows self-signed certificates on local mail servers. Off by default.
**Save** stores the fields and the TLS switch. **Send test email** saves them as well and then sends a test message to your own account's email address; it stays disabled until **SMTP Host** is filled in. A toast reports success or the mail server's error.
The `SMTP_HOST`, `SMTP_PORT`, `SMTP_USER`, `SMTP_PASS`, `SMTP_FROM` and `SMTP_SKIP_TLS_VERIFY` environment variables take priority over the matching field, one by one, when they are set. The fields are not locked, so a value typed there is simply not used while its variable is set. See [Environment-Variables](Environment-Variables).
### Webhook
Allow users to configure their own webhook URLs for notifications (Discord, Slack and others). There is nothing to set here beyond the switch: each user enters their own URL.
### Ntfy
Allow users to configure their own ntfy topics for push notifications. The default server users start from is the **Ntfy Server URL** of the **Admin Ntfy** card below.
### Web Push
Lets users receive notifications on their phones and computers through the browser, even while TREK is closed. It needs HTTPS, and on iPhone and iPad TREK has to be added to the Home Screen. No setup beyond the switch: TREK creates its signing keys on first start. See [Notifications](Notifications#web-push) for the requirements and the server keys.
### In-App
In-app notifications are always active and cannot be switched off for the whole instance. The card shows its switch on and greyed out.
### Trip Reminders
Sends a reminder notification before a trip starts, to trips that have reminder days set. **On by default.** The check runs once a day and picks trips that start exactly that many days later. When it is off, the reminder section of a trip is greyed out with a note that reminders are disabled. See [Creating-a-Trip](Creating-a-Trip).
## Admin alerts
Admin-only notifications, such as a new TREK version or a failed write to a storage replica, go to the admin's own targets. These are separate from the users' webhooks and topics.
### Admin Webhook
A webhook used only for admin notifications. It always fires when a URL is set. Enter the URL (for example `https://discord.com/api/webhooks/...`) and press **Save**; after that it shows as `••••••••`. **Send test webhook** sends a test message to the URL in the field, or to the stored one while the field shows the mask.
### Admin Ntfy
An ntfy topic used only for admin notifications. It always fires when a topic is set.
- **Ntfy Server URL**: also the default server for users' ntfy notifications. Leave it blank for `https://ntfy.sh`. Users can override it in their own settings.
- **Admin Topic**: for example `trek-admin-alerts`.
- **Access Token (optional)**: for a protected topic. Once saved it shows as `••••••••`, and a **Clear** button removes it.
**Save** stores the three fields. **Send test ntfy** sends a test message to the topic; it is disabled while **Admin Topic** is empty.
### Notifications
The matrix under the admin targets sets which channels deliver each admin-only event: **New version available** and **Storage replica failure**. Columns appear only for channels that can reach the admin: **In-App** always, **Email** once SMTP is configured, **Webhook** once an admin webhook URL is saved, **Ntfy** once an admin topic is saved. Every cell is a switch, on by default, and saves at once. A dash means that event cannot go out on that channel. Admin alerts are never sent as Web Push.
## Defaults for users
How every user's notifications start. The card shows one row per user event and one column per channel: **In-App**, **Email**, **Webhook**, **Ntfy**, **Push**, and any channel a plugin adds. A column is shown even while its channel is switched off above, so the defaults can be set before the channel goes live. A dash marks an event that channel cannot deliver.
Each cell is a pill that cycles through three states when clicked, and saves at once; its tooltip names the next state (**Click for: Off**).
| State | Meaning |
|-------|---------|
| **On** | Switched on until the user turns it off. The default for every cell. |
| **Off** | Switched off until the user turns it on. |
| **Blocked** | Switched off for everyone. In each user's settings the cell shows a lock instead of a switch, and nothing is sent there. |
A default applies to every user who has not changed that cell themselves, including users who joined before you set it, so a later change reaches them too. A cell a user switched keeps the user's choice, unless you block it. The events themselves are listed in [Notifications](Notifications#notification-events).
## See also
- [Notifications](Notifications) - the per-user side: channels, events, webhook and ntfy setup, Web Push
- [Admin-Panel-Overview](Admin-Panel-Overview) - all admin tabs
- [Environment-Variables](Environment-Variables) - SMTP and Web Push variables
- [Creating-a-Trip](Creating-a-Trip) - setting a trip's reminder
- [Admin-Storage](Admin-Storage) - storage replicas and their failure alerts
+17 -13
View File
@@ -1,6 +1,6 @@
# Admin — Packing Templates
# Admin: Packing Templates
The **Personalization** tab → **Packing Templates** section lets you create reusable packing list templates that users can apply to any trip.
The **Packing Templates** card on **Admin > Personalization** lets you create reusable packing list templates that users can apply to any trip.
![Packing Template Manager](assets/PackingTemplate.png)
@@ -14,7 +14,9 @@ Template
└── Item
```
When a user applies a template to a trip, all categories and items from that template are copied into the trip's packing list.
When a user applies a template to a trip, all categories and items from that template are copied into the trip's packing list. Each item carries its **weight**, **quantity** and **bag** along: a bag the trip does not have yet is created.
Templates are instance-wide. Besides the ones you build here, the list also shows the templates users saved from a trip's packing list (the Common list plus their own items), and you can rename, edit or delete those as well.
## Template list
@@ -22,11 +24,13 @@ The template list shows each template as a collapsible row displaying:
- Template name
- Category count and item count (e.g., `3 categories · 12 items`)
- Edit (rename) and delete buttons
- Rename and delete buttons
Inside an expanded template, an item shows its quantity, weight and bag next to its name when it has them (for example `2× · 300 g · Backpack`). These values come from the trip list the template was saved from; items you add here start with none of them.
## Creating a template
1. Click **New Template** (top-right of the panel).
1. Click **New Template** (top right of the card).
2. Type a name and press **Enter** or click the confirm button.
3. The new template is added to the list and automatically expanded.
@@ -36,25 +40,25 @@ With a template expanded, click **Add category** (dashed border button at the bo
## Adding items to a category
Click the `+` button inside any category header. An inline input appears below the last item. Type an item name and press **Enter** to add it. You can add multiple items in sequence without closing the input — press **Enter** after each one.
Click the `+` button inside any category header. An **Item name** field appears below the last item. Type a name and press **Enter** to add it. You can add several items in a row without closing the field: press **Enter** after each one.
## Editing inline
All editing is inline:
- **Rename a template** — click the pencil icon on the template row. The name becomes an input; press **Enter** or click away to save.
- **Rename a category** — click the pencil icon in the category header. Press **Enter** or click away to save.
- **Rename an item** — hover the item row to reveal the pencil icon, then click it. Press **Enter** or click the confirm button to save (clicking away does not save).
- **Rename a template**: click the pencil icon on the template row. The name becomes an input; press **Enter** or click away to save.
- **Rename a category**: click the pencil icon in the category header. Press **Enter** or click away to save.
- **Rename an item**: hover the item row to reveal the pencil icon, then click it. Press **Enter** or click the confirm button to save (clicking away does not save).
## Deleting
- **Delete a template** — click the trash icon on the template row. The template is removed. This does not affect trips that already had items from this template applied.
- **Delete a category** — click the trash icon in the category header. All items in that category are also deleted from the template.
- **Delete an item** — hover the item row to reveal the trash icon.
- **Delete a template**: click the trash icon on the template row. The template is removed at once, without a confirmation. This does not affect trips that already had items from this template applied.
- **Delete a category**: click the trash icon in the category header. All items in that category are also deleted from the template.
- **Delete an item**: hover the item row to reveal the trash icon.
## Applying templates to a trip
Users apply templates through the **Packing** panel inside the trip planner. See [Packing-Templates](Packing-Templates) for user-facing documentation.
Users apply templates (**Apply template**) and save a list as a new one (**Save as template**) in the trip's **Lists** tab. See [Packing-Templates](Packing-Templates) for user-facing documentation.
## Related pages
+39 -18
View File
@@ -8,25 +8,41 @@ Open the user menu in the top navigation bar (your avatar), then select **Admin*
![Admin Panel](assets/AdminPanel.png)
## Layout
On desktop the page opens with a header (**Administration**, *User management and system settings*) whose right side shows four counters: **Users**, **Trips**, **Places** and **Files**. When a newer TREK release exists, an update banner sits below it. Under that, a side navigation on the left lists the tabs in four groups, and the selected tab fills the right side. Every tab is built from cards with toggle rows, and anything that needs confirming (deleting a user, restoring a backup, revoking a token) asks in TREK's own dialog rather than the browser's.
## Tabs
The Admin Panel is divided into tabs. Most tabs are always visible; a few appear only under specific conditions.
Most tabs are always visible; a few appear only under specific conditions.
| Tab | Purpose | Conditional? |
|-----|---------|--------------|
| **Users** | Manage users, invite links, and permissions | No |
| **Personalization** | Packing templates, place categories and the manually maintained school holiday catalog (see [Vacay](Vacay#manually-maintained-school-holidays)) | No |
| **User Defaults** | Default settings applied to new users | No |
| **Addons** | Enable or disable optional features instance-wide | No |
| **Plugins** | Install, update, and manage plugins; rescan the plugins folder; view each plugin's error log. See [Admin-Plugins](Admin-Plugins) | No |
| **Storage** | Storage backends, category assignment, replication, health | No |
| **Settings** | Authentication methods, MFA, allowed file types, API keys, OIDC/SSO configuration, and JWT secret rotation | No |
| **Notifications** | SMTP, webhook, ntfy and Web Push channel configuration; trip reminder toggle; admin notification preferences | No |
| **Backup** | Manual and scheduled full-instance backups: database, uploads, plugin data and plugin code. See [Backups](Backups) | No |
| **Audit** | Chronological activity log | No |
| **MCP Access** | OAuth sessions and static API tokens | Only when the MCP addon is enabled |
| **GitHub** | Release timeline and support links | No |
| **Dev: Notifications** | Test notification dispatch | Only in development mode (`NODE_ENV=development`) |
| Group | Tab | Purpose | Conditional? |
|-------|-----|---------|--------------|
| Users | **Users** | Manage users and invite links; the permission settings sit at the bottom. See [Admin-Users-and-Invites](Admin-Users-and-Invites) and [Admin-Permissions](Admin-Permissions) | No |
| Users | **User Defaults** | Default settings applied to users who have not picked their own: colour mode, units, time format, currency, week start, blurred booking codes, map engine and the routing services. See [Admin-User-Defaults](Admin-User-Defaults) | No |
| Configuration | **Personalization** | Packing templates, place categories and the manually maintained school holiday catalog (see [Vacay](Vacay#manually-maintained-school-holidays)) | No |
| Configuration | **Settings** | Authentication methods (password and SSO login and registration), passkeys, required MFA, OIDC/SSO configuration, allowed file types, API keys and place providers (Google, Unsplash, Amap, public transit backend, place search provider, the **Daily limit for Google calls**), and **Rotate JWT Secret**. See [Admin-Settings](Admin-Settings) | No |
| Configuration | **Addons** | Enable or disable optional features instance-wide. See [Admin-Addons](Admin-Addons) | No |
| Configuration | **Plugins** | Install, update, and manage plugins; rescan the plugins folder; view each plugin's error log. See [Admin-Plugins](Admin-Plugins) | No |
| Configuration | **Storage** | Storage backends, category assignment, replication, health. See [Admin-Storage](Admin-Storage) | No |
| Integrations | **Notifications** | Email (SMTP), webhook, ntfy and Web Push channels; trip reminders; the admin's own webhook and ntfy; **Defaults for users** (see below). See [Admin-Notifications](Admin-Notifications) | No |
| Integrations | **MCP Access** | OAuth sessions and static API tokens. See [Admin-MCP-Tokens](Admin-MCP-Tokens) | Only when the MCP addon is enabled |
| Integrations | **GitHub** | Release timeline and support links. See [Admin-GitHub-Releases](Admin-GitHub-Releases) | No |
| Maintenance | **Backup** | Manual and scheduled full-instance backups: database, uploads, plugin data and plugin code. See [Backups](Backups) | No |
| Maintenance | **Audit** | Chronological activity log. See [Audit-Log](Audit-Log) | No |
| Maintenance | **Dev: Notifications** | Test notification dispatch | Only in development mode (`NODE_ENV=development`) |
### API keys set through the environment
A Google Maps, Unsplash or Amap key that comes from an environment variable shows in **Settings > API Keys** as a disabled field that reads **Set via** and the variable's name: the variable wins, so a key typed into the panel would have no effect. **Test** still checks the key from the environment. For the Google key the variable is `PLACES_API_KEY`. See [Environment-Variables](Environment-Variables).
### Daily limit for Google calls
In **Settings > API Keys**, the **Google Maps API Key** block has a collapsible section, **What the key may be used for**, whose last row is **Daily limit for Google calls**. Once the limit is reached, TREK stops calling Google until the next day (UTC) and searches with OpenStreetMap instead. Leave the field empty for no limit. A pill beside the name shows today's usage (**Today: 120** or **Today: 120 of 500**) and turns amber (**Limit reached (120), Google paused until tomorrow**) once the day is used up. **Save** appears only while the number has changed.
### Notification defaults
At the bottom of **Notifications**, **Defaults for users** is a matrix of every notification event against every channel. Each cell cycles through **On**, **Off** and **Blocked** when clicked and is saved right away; an event a channel cannot deliver shows a dash. **On** and **Off** are only where a user's settings start: each user may still change them. **Blocked** turns that event off on that channel for everyone, and it shows as locked in their settings. The defaults apply to every user who has not changed that cell themselves. See [Notifications](Notifications).
![Admin panel on the User Defaults tab, setting instance-wide defaults for colour mode, temperature unit, distance unit, time format, currency and blurred booking codes](assets/AdminUserDefaults.png)
@@ -48,7 +64,7 @@ Counting is **on by default** and has no switch in the admin panel. To turn it o
### Linking to a tab directly
Every panel is reachable by URL, so a bookmark, an onboarding mail or a support reply can point at the one tab it is about instead of at the top of a page with thirteen of them:
Every panel is reachable by URL, so a bookmark, an onboarding mail or a support reply can point at the one tab it is about instead of at the top of the page:
```
/admin?tab=audit
@@ -86,10 +102,15 @@ See [Audit-Log](Audit-Log) for details on the hash chain and how the two logs di
## Related pages
- [Admin-Users-and-Invites](Admin-Users-and-Invites)
- [Admin-User-Defaults](Admin-User-Defaults)
- [Admin-Settings](Admin-Settings)
- [Admin-Addons](Admin-Addons)
- [Admin-Categories](Admin-Categories)
- [Admin-Packing-Templates](Admin-Packing-Templates)
- [Admin-Permissions](Admin-Permissions)
- [[Admin: Storage|Admin-Storage]]
- [Admin-Storage](Admin-Storage)
- [Admin-Notifications](Admin-Notifications)
- [Admin-MCP-Tokens](Admin-MCP-Tokens)
- [Admin-GitHub-Releases](Admin-GitHub-Releases)
- [Backups](Backups)
- [Audit-Log](Audit-Log)
+41 -41
View File
@@ -1,72 +1,72 @@
# Admin — Permissions
# Admin: Permissions
The Permissions panel, located at the bottom of the **Users** tab, controls which role level is required to perform each action. Changes apply immediately across the entire instance.
The **Permission Settings** card, at the bottom of the **Users** tab, controls which role level is required to perform each action. Saved changes apply immediately across the entire instance.
![Permissions panel](assets/PermissionSettings.png)
## Role model
TREK uses four permission levels, ordered from most to least privileged:
TREK uses four permission levels, ordered from most to least privileged. The dropdowns show them by the label in brackets:
| Level | Who it includes |
|-------|----------------|
| `admin` | Instance administrators only |
| `trip_owner` | The user who created the trip |
| `trip_member` | Any user who is a member of the trip |
| `everybody` | Any authenticated user (for `trip_create`: no trip context required; for all other actions: any authenticated user with trip access) |
| Level | Label | Who it includes |
|-------|-------|----------------|
| `admin` | **Admin only** | Instance administrators only |
| `trip_owner` | **Trip owner** | The user who created the trip |
| `trip_member` | **Trip members** | Any user who is a member of the trip |
| `everybody` | **Everyone** | Any authenticated user (for `trip_create`: no trip context required; for all other actions: any authenticated user with trip access) |
Each action is assigned a minimum required level. A user whose role is at or above that level can perform the action. Not every level is available for every action — each action exposes only the levels that make sense for it. For example, `trip_create` only allows `everybody` or `admin`, while `trip_edit` only allows `trip_owner` or `trip_member`.
Each action is assigned a minimum required level. A user whose role is at or above that level can perform the action. Not every level is available for every action: each action offers only the levels that make sense for it. For example, `trip_create` only allows **Everyone** or **Admin only**, while `trip_edit` only allows **Trip owner** or **Trip members**.
## Action categories
Actions are grouped into five categories:
Actions are grouped into five sections. Each row shows the action's name, a hint below it and the dropdown.
### Trip
### Trip Management
| Action key | What it controls |
|------------|-----------------|
| `trip_create` | Create a new trip |
| `trip_edit` | Edit trip name, dates, description, and currency |
| `trip_delete` | Permanently delete a trip |
| `trip_archive` | Archive or unarchive a trip |
| `trip_cover_upload` | Upload or change the cover image for a trip |
| Action key | Row label | What it controls | Default | Choices |
|------------|-----------|-----------------|---------|---------|
| `trip_create` | **Create trips** | Create a new trip | Everyone | Admin only, Everyone |
| `trip_edit` | **Edit trip details** | Edit trip name, dates, description, and currency | Trip owner | Trip owner, Trip members |
| `trip_delete` | **Delete trips** | Permanently delete a trip | Trip owner | Admin only, Trip owner |
| `trip_archive` | **Archive / unarchive trips** | Archive or unarchive a trip | Trip owner | Trip owner, Trip members |
| `trip_cover_upload` | **Upload cover image** | Upload or change the cover image for a trip | Trip owner | Trip owner, Trip members |
### Members
### Member Management
| Action key | What it controls |
|------------|-----------------|
| `member_manage` | Invite or remove trip members |
| Action key | Row label | What it controls | Default | Choices |
|------------|-----------|-----------------|---------|---------|
| `member_manage` | **Add / remove members** | Invite or remove trip members | Trip owner | Admin only, Trip owner, Trip members |
### Files
| Action key | What it controls |
|------------|-----------------|
| `file_upload` | Upload files to a trip |
| `file_edit` | Edit file descriptions and links |
| `file_delete` | Move files to trash or permanently delete them |
| Action key | Row label | What it controls | Default | Choices |
|------------|-----------|-----------------|---------|---------|
| `file_upload` | **Upload files** | Upload files to a trip | Trip members | Admin only, Trip owner, Trip members |
| `file_edit` | **Edit file metadata** | Edit file descriptions and links | Trip members | Trip owner, Trip members |
| `file_delete` | **Delete files** | Move files to trash or permanently delete them | Trip members | Trip owner, Trip members |
### Content & Schedule
| Action key | What it controls |
|------------|-----------------|
| `place_edit` | Add, edit, or delete places |
| `day_edit` | Edit days, day notes, and place assignments |
| `reservation_edit` | Create, edit, or delete reservations |
| Action key | Row label | What it controls | Default | Choices |
|------------|-----------|-----------------|---------|---------|
| `place_edit` | **Add / edit / delete places** | Add, edit, or delete places | Trip members | Trip owner, Trip members |
| `day_edit` | **Edit days, notes & assignments** | Edit days, day notes, and place assignments | Trip members | Trip owner, Trip members |
| `reservation_edit` | **Manage reservations** | Create, edit, or delete reservations | Trip members | Trip owner, Trip members |
### Budget, Packing & Collaboration
| Action key | What it controls |
|------------|-----------------|
| `budget_edit` | Create, edit, or delete budget items |
| `packing_edit` | Manage packing items and bags |
| `collab_edit` | Create notes, polls, and send messages |
| `share_manage` | Read, create or delete public share links and calendar feed links |
| Action key | Row label | What it controls | Default | Choices |
|------------|-----------|-----------------|---------|---------|
| `budget_edit` | **Manage budget** | Create, edit, or delete expenses in Costs | Trip members | Trip owner, Trip members |
| `packing_edit` | **Manage packing lists** | Manage packing items and bags | Trip members | Trip owner, Trip members |
| `collab_edit` | **Collaboration (notes, polls, chat)** | Create notes, polls, and send messages | Trip members | Trip owner, Trip members |
| `share_manage` | **Manage share links** | Read, create or delete public share links and calendar feed links | Trip owner | Trip owner, Trip members |
## Changing permissions
Each action row has a dropdown. Select the minimum role level required. A **customized** badge appears next to any action that has been changed from its default.
Each action row has a dropdown. Select the minimum role level required. A **customized** badge appears next to any action that differs from its default.
Click **Save** (top-right of the panel) to persist your changes. Use the **Reset to defaults** button (circular arrow icon) to revert all actions to their shipped defaults without saving — you still need to click **Save** after resetting if you want to persist the reset state.
Click **Save** (top right of the card) to persist your changes; it stays disabled until something has changed. **Reset to defaults** (circular arrow icon) puts every action back to its shipped default in the form without saving: click **Save** afterwards if you want to keep the reset.
## Related pages
+2 -1
View File
@@ -6,7 +6,7 @@ Install, review, enable, update, and remove third-party plugins on your instance
## Where to find it
Open the **Admin Panel** and select the **Plugins** tab. *Install and manage third-party plugins on your instance.*
Open the **Admin Panel** and select the **Plugins** tab (in the **Configuration** group of the side navigation). *Install and manage third-party plugins on your instance.*
> **Admin:** This whole panel is admin-only. It also needs the plugin runtime turned on — otherwise you get *Plugins are disabled*: **The plugin runtime is turned off (`TREK_PLUGINS_ENABLED`). No plugin can run until an admin enables it in the server configuration.** When the runtime is on, a green **Runtime on** pill appears in the header.
@@ -39,6 +39,7 @@ Before installing, read these sections:
- **What it can access** — a plain-language summary of what the plugin's permissions let it do ("Reads your trips", "Edits places", "Provides photos"), plus a line for its own isolated database. It is a summary, not the raw permission list: permissions TREK has no summary line for — `notify:send`, `ai:invoke`, `jobs:run`, `db:write:members` and others — do not appear here at all, and a plugin that asks only for those still reads *Needs no special access.* For the complete list, read the manifest in the plugin's source repository. Only the consent dialog for an update renders permissions code by code, unknown codes verbatim.
- **Map categories it adds**: for a plugin that asks for `hook:poi-category-provider`, each button it would add to the category row on the trip map (see [Places and Search](Places-and-Search#categories-from-plugins)), with its icon on its colour and its name in your language. The access list above reads *Adds map categories* for the same permission, and so does a chip on the plugin's row once it is installed. A plugin that declares categories without asking for the permission shows no list, because its buttons would never appear. The consent dialog of an update that adds the permission spells out what it shares: *Add its own place categories to Explore places on the map; picking one sends the plugin the map area you are viewing.*
- A plugin that asks for `hook:search-provider` reads **Answers searches** in the access list: its own index answers place searches beside TREK's results, and a plugin built for it also answers while the search is still being typed, with its places marked with the plugin's name (see [Places and Search](Places-and-Search#suggestions-while-you-type)).
- **Connects to** — every host the manifest declares it may reach, as monospace chips.
- **Setup** — settings the plugin will ask you (or each user) to fill in, tagged **Instance-wide** or **Per user**, and **Required** where applicable.
- **Details** — version, size, the TREK version range it requires, when it was reviewed, and total downloads.
+153
View File
@@ -0,0 +1,153 @@
# Admin: Settings
The **Settings** tab (in the **Configuration** group of the admin side navigation, `/admin?tab=settings`) holds the instance-wide switches for signing in, uploads and place data. On a wide screen the cards sit in two columns: access and identity on the left (**Authentication Methods**, **Passkey login**, **Require two-factor authentication (2FA)**, **Single Sign-On (OIDC)**), files and place data on the right (**Allowed File Types**, **API Keys**). The **Danger Zone** runs across the full width at the bottom. On a narrow screen the same cards stack in that order.
Switches save as soon as you flip them. Text fields save with the card's own **Save** button.
## Authentication Methods
Decides which ways in are offered on the login page.
| Row | What it does | Default |
|-----|--------------|---------|
| **Password Login** | Allow users to sign in with email and password. | On |
| **Password Registration** | Allow new users to register with email and password. | On |
| **SSO Login** | Allow users to sign in with SSO. | On |
| **SSO Auto-Provisioning** | Automatically create accounts for new SSO users. | On |
The two SSO rows only appear once OIDC is configured, that is, once an issuer and a client ID are known (from the **Single Sign-On (OIDC)** card or from the environment).
At least one login method must stay enabled. The switch that would remove the last way in is greyed out, and hovering it shows **At least one login method must remain enabled**. The server enforces the same rule: password login can only be switched off while SSO login is on and OIDC is configured.
When the `OIDC_ONLY` environment variable is set, a warning at the top of the card says that the password settings are controlled by it, and **Password Login** and **Password Registration** are read-only. See [OIDC-SSO](OIDC-SSO) and [Login-and-Registration](Login-and-Registration).
## Passkey login
Lets users sign in with passkeys (WebAuthn). **Off by default.**
- **Enable passkey login**: shows a **Sign in with a passkey** option on the login page and lets users enrol passkeys in their own settings.
- **Relying Party ID (domain)**: the bare domain passkeys are bound to, for example `trek.example.org`. Leave it empty to derive it from `APP_URL`. Changing it later invalidates every passkey already enrolled.
- **Allowed origins**: comma-separated full origins, for example `https://trek.example.org`. Leave it empty to use `APP_URL`.
The two fields save with **Save** under them. `WEBAUTHN_RP_ID` and `WEBAUTHN_ORIGINS` take priority over the fields when they are set; the fields stay editable, but what you type there has no effect while the variable holds a value.
If the switch is on but no domain can be resolved (no `APP_URL`, no Relying Party ID, or an `APP_URL` that is a bare IP address), a warning says so and passkeys stay hidden until one is set. See [Passkeys](Passkeys).
## Require two-factor authentication (2FA)
One switch, **off by default**. When it is on, users without 2FA must complete the setup in their settings before they can use the app.
You can only switch it on once your own account is protected, by two-factor authentication or by a passkey. Otherwise the server refuses and asks you to secure your own account first. See [Two-Factor-Authentication](Two-Factor-Authentication).
## Single Sign-On (OIDC)
Allow login via external providers like Google, Apple, Authentik or Keycloak.
| Field | Notes |
|-------|-------|
| **Display Name** | The name on the SSO button. Without one, the button reads **SSO**. |
| **Issuer URL** | The OpenID Connect issuer URL of the provider, for example `https://accounts.google.com`. |
| **Discovery URL** (optional) | Overrides the discovery URL TREK builds from the issuer (`<issuer>/.well-known/openid-configuration`). Needed for providers like Authentik, where the endpoint lives elsewhere. |
| **Client ID** | From your provider. |
| **Client Secret** | From your provider. Once saved it shows as `••••••••`; leaving the field empty on a later save keeps the stored secret. |
**Save** stores all five at once. The environment variables `OIDC_ISSUER`, `OIDC_CLIENT_ID`, `OIDC_CLIENT_SECRET`, `OIDC_DISPLAY_NAME` and `OIDC_DISCOVERY_URL` take priority over the matching field when they are set. The fields are not locked, so a value typed there is simply not used while its variable is set. See [OIDC-SSO](OIDC-SSO) for the provider setup, claims and admin role mapping.
## Allowed File Types
Configure which file types users can upload. Enter comma-separated extensions without dots, for example `jpg,png,pdf,doc`, and press **Save**. A single `*` allows every type.
The default list is `jpg,jpeg,png,gif,webp,heic,pdf,doc,docx,xls,xlsx,txt,csv,pkpass,pkpasses,md,markdown`.
Two rules apply whatever the field says:
- Some extensions are always refused, even with `*`: SVG, HTML and XML documents, scripts (`.js`, `.ts`, `.php`, `.py` and similar) and executables (`.exe`, `.bat`, `.sh`, `.msi`, `.dll` and similar).
- In a trip's files, videos are accepted even when their extension is not on the list.
See [Documents-and-Files](Documents-and-Files).
## API Keys
Where place data comes from. The TREK index needs no key; the providers below it are optional. The card is a column of blocks, in the order TREK recommends them.
### TREK Places API
The first block, marked **Recommended default**. It is TREK's own place index: search without a Google key, without a quota and without anyone counting your lookups. There is nothing to configure here. The fold **What is in it** lists the fields a result carries (**Included**), what it does not have (**Not included**: ratings and photos of ordinary businesses) and its **Sources** (Overture Maps Foundation, OpenStreetMap, Wikivoyage, Wikimedia). See [TREK-Places-API](TREK-Places-API).
### Google Maps API Key
Optional. Without a Google key the TREK API is used. With one, photos, ratings and opening hours can be loaded on top, and every such lookup goes to Google. Create a key at console.cloud.google.com.
Next to the field, **Test** checks the key and shows **Connected** or **Invalid** under it. The eye icon shows or hides the key.
Below the field, the fold **What the key may be used for** shows how many of its five switches are on (for example **4 of 5 on**) and holds:
| Row | What it does | Default |
|-----|--------------|---------|
| **Place Photos** | Fetch photos from the Google Places API. Wikimedia photos are unaffected. | On |
| **Place Autocomplete** | Use Google for search suggestions. | On |
| **Place Details** | Fetch hours, rating and website from Google. | On |
| **Place Enrichment** | Show pictures and a description while adding a place. Wikipedia and OpenStreetMap are always used; Google is added on top when **Place Photos** or **Place Details** is on. | On |
| **Search with Google only** | Every search and every suggestion goes to Google Places. Off, TREK's own index and OpenStreetMap answer first and Google is only asked when they find nothing. | Off |
| **Daily limit for Google calls** | See below. | No limit |
Switch the first four off to save API quota. **Search with Google only** needs a Google key and Google as the place search provider; when either is missing, its subtitle says that search will not go to Google whatever the switch says.
**Daily limit for Google calls**: once the limit is reached, TREK stops calling Google until the next day (UTC) and searches with OpenStreetMap instead. Leave the field empty for no limit. A pill beside the name shows today's usage, **Today: 120** or **Today: 120 of 500**, and turns amber with **Limit reached (120), Google paused until tomorrow** once the day is used up. A **Save** button appears only while the number differs from the stored one; **Enter** saves as well.
### Unsplash API Key
For image search. Free at unsplash.com/developers.
### Amap (高德地图) API Key
For place search inside mainland China, where Google is unreachable and OpenStreetMap coverage is thin. It needs a "Web 服务" (web service) key, not a JS API key. Get one at console.amap.com. There is no **Test** button for this key.
### Keys set through the environment
A key that comes from an environment variable makes its field read-only. The field stays empty and reads **Set via** and the variable's name: `PLACES_API_KEY` for Google, `UNSPLASH_ACCESS_KEY` for Unsplash, `AMAP_API_KEY` for Amap. **Save** leaves those keys alone, and **Test** still checks the Google key from the environment. See [Environment-Variables](Environment-Variables).
### Transit Provider
Which service answers public transit search. It saves as soon as you pick.
- **Transitous (free)**, the default: community GTFS feeds, free and keyless, with the best coverage in Europe.
- **Google**: uses the Google API key above, for regions Transitous has no data for. Google bills each search.
With **Google** picked but no Google key configured, a warning says transit search is still using Transitous. When only your own personal Google key is set, a warning says that other members still fall back to Transitous until the key is saved here as the instance key. See [Transport-Flights-Trains-Cars](Transport-Flights-Trains-Cars).
### Place search provider
TREK's own index and OpenStreetMap answer every search. This picks who else is asked when they find nothing:
- **Automatic** (default): prefers Google where a key exists, then Amap.
- **Google Places**
- **Amap (高德地图)**
- **OpenStreetMap**
The choice saves at once. If the selected provider has no API key, a warning says that place search is answered by the TREK index and OpenStreetMap alone. See [Places-and-Search](Places-and-Search).
### Place Search Log
One switch, **off by default**. When it is on, TREK records which search result was picked, so a different place index can be measured against real searches later: the search text, the picked place's name and rounded coordinates, and where it stood in the result list. No user is stored with it, and nothing leaves the instance. Rows are deleted after 180 days, also while the switch is off. An admin can read the log through `GET /api/place-shadow/summary` and `GET /api/place-shadow/export`, and delete it with `DELETE /api/place-shadow`.
### Saving the keys
The **Save** button at the bottom of the card stores the Google, Unsplash and Amap keys. Everything else on the card (the switches, the daily limit, the two provider choices) saves on its own.
## Danger Zone
**Rotate JWT Secret** generates a new signing secret for login sessions. **Rotate** opens a confirmation; **Rotate & Log out** writes the new secret to `data/.jwt_secret` and invalidates every active session at once, yours included, so you land on the login page. Everyone has to sign in again. The action is recorded in the [Audit-Log](Audit-Log).
Rotating the JWT secret does not touch the encryption key that protects stored API keys and passwords; see [Encryption-Key-Rotation](Encryption-Key-Rotation) for that one.
## See also
- [Admin-Panel-Overview](Admin-Panel-Overview) - all admin tabs
- [OIDC-SSO](OIDC-SSO) - single sign-on setup
- [Passkeys](Passkeys) - passkeys from the user's side
- [Two-Factor-Authentication](Two-Factor-Authentication) - 2FA and the enforced setup
- [TREK-Places-API](TREK-Places-API) - TREK's own place index
- [Places-and-Search](Places-and-Search) - how place search uses these providers
- [Environment-Variables](Environment-Variables) - variables that override these fields
- [Encryption-Key-Rotation](Encryption-Key-Rotation) - rotating the encryption key
+1 -1
View File
@@ -1,6 +1,6 @@
# Admin: Storage
The **Storage** tab (Admin Panel → Storage) controls where TREK stores each
The **Storage** tab (Admin Panel > Configuration > Storage) controls where TREK stores each
kind of content: which storage backends exist, which content category writes
to which backend, and whether writes are replicated to additional backends.
+85
View File
@@ -0,0 +1,85 @@
# Admin: User Defaults
The **User Defaults** tab (in the **Users** group of the admin side navigation, `/admin?tab=defaults`) sets instance-wide defaults for user settings. Users who have not changed a setting see these values; their own changes always take priority. The defaults are merged in every time a user's settings load, so a default you change later reaches everyone who never picked their own value.
![Admin panel on the User Defaults tab, setting instance-wide defaults for colour mode, temperature unit, distance unit, time format, currency and blurred booking codes](assets/AdminUserDefaults.png)
On a wide screen the tab has two cards side by side: **Default User Settings** on the left, **Map** on the right. On a narrow screen the map card follows below.
## Saving and resetting
Every choice saves the moment you pick it, and a toast confirms **Default saved**. Text fields save when you leave the field.
Once a default is set, a small **reset** link appears next to its name. It removes the default, so users without their own value fall back to TREK's built-in one. While no default is set, none of the choices in a row is highlighted.
## Default User Settings
| Row | Choices | Built-in value when no default is set |
|-----|---------|------------------------------|
| **Color Mode** | **Light**, **Dark**, **Auto** | Light |
| **Temperature Unit** | **°C Celsius**, **°F Fahrenheit** | Celsius |
| **Distance Unit** | **km Metric**, **mi Imperial** | Metric |
| **Time Format** | **24h (14:30)**, **12h (2:30 PM)** | 24h |
| **Week starts on** | Monday, Sunday, Saturday (named in your language) | Monday |
| **Display currency** | A searchable list of currencies | None (Costs shows each trip's own currency) |
| **Blur Booking Codes** | **On**, **Off** | Off |
**Week starts on** decides which day opens each row of every date picker. Vacay keeps its own week start per plan.
**Display currency**: amounts in Costs are shown converted to this currency for display only; the original amounts are unchanged. A user without a display currency of their own gets this one. See [Display-Settings](Display-Settings) and [Currencies](Currencies).
**Blur Booking Codes** blurs confirmation codes and reference numbers until the user hovers or taps them. See [Display-Settings](Display-Settings#blur-booking-codes).
## Map
The map card configures the map users see and the routing services behind it, from top to bottom:
### Map Template
The tile source for the standard map. Pick a preset from **Select template...** or type any XYZ tile URL or MapLibre style URL into the field below it. The presets are **OpenStreetMap**, **OpenStreetMap DE**, **OpenFreeMap Positron**, **OpenFreeMap Bright**, **CartoDB Light**, **CartoDB Dark** and **Stadia Smooth**. Leave the field empty to keep TREK's built-in default. See [Map-Settings](Map-Settings) for what each preset looks like.
### Shared CARTO key
Used for every user who has not entered their own key, so the whole instance gets CARTO tiles without a watermark. The two CartoDB presets need it. Stored encrypted. See [Map-Settings](Map-Settings#carto-api-key).
### Own routing engine
The address of an OSRM instance of your own, for example `https://osrm.example.org`. Empty uses the public servers, which allow about one request a second: enough for a day plan, tight for a road trip.
### Own Valhalla instance
The address of a Valhalla instance of your own, for example `https://valhalla.example.org`. TREK uses the public FOSSGIS Valhalla by default to avoid toll roads, motorways and ferries. If only **Own routing engine** is set, the public Valhalla is not used.
Both routing fields save when you leave them (or press **Enter**), and only an admin can set them. After changing either one, **restart the server and reload the page**: the browser only talks to routing hosts the server names in its security policy, and that policy is built once at start. There is no environment variable for either engine. See [Road-Trip](Road-Trip#routing-engines) for what each combination does and what your own instances need.
### Preview
A small map centred on Paris shows the current **Map Template** (with the CARTO key applied), so you can check a tile source before users see it.
### Map engine
The default map for everyone on this instance; each user can still override it in their own settings.
- **Standard (free)**: the Leaflet map, using the **Map Template** above. This is the built-in default.
- **Mapbox (3D)**: Mapbox GL with 3D buildings and terrain. Needs a Mapbox token.
- **MapLibre (OpenFreeMap)**: MapLibre GL with OpenFreeMap vector tiles. No token needed.
Depending on the engine, more rows appear below it:
| Row | Shown for | Notes |
|-----|-----------|-------|
| **Shared Mapbox token** | Mapbox (3D) | Used for every user who has not entered their own token, so the whole instance gets Mapbox without sharing the key one by one. Stored encrypted. |
| **Map style** | Mapbox (3D), MapLibre (OpenFreeMap) | Pick a style from **Choose a style…** or type a style URL. Each engine keeps its own style, so switching engines does not overwrite the other one. |
| **3D buildings & terrain** | Mapbox (3D) | **On** or **Off**. On unless set otherwise. |
| **High-quality mode** | Mapbox (3D) | **On** or **Off**. Off unless set otherwise. |
See [Map-Settings](Map-Settings) for the styles and what the two Mapbox switches do.
## See also
- [Admin-Panel-Overview](Admin-Panel-Overview) - all admin tabs
- [Display-Settings](Display-Settings) - the same settings from the user's side
- [Appearance-Settings](Appearance-Settings) - colour mode and the rest of the look
- [Map-Settings](Map-Settings) - map engines, tile sources, styles and keys
- [Road-Trip](Road-Trip#routing-engines) - routing engines in detail
- [Currencies](Currencies) - display and trip currencies
+22 -22
View File
@@ -1,12 +1,12 @@
# Admin — Users and Invites
# Admin: Users and Invites
The **Users** tab in the Admin Panel lets you view all registered users, manage their accounts, and create invite links so new people can register without open registration.
The **Users** tab in the Admin Panel (first in the **Users** group of the side navigation) lets you view all registered users, manage their accounts, and create invite links so new people can register without open registration.
![Users tab](assets/UsersAndInvites.png)
## User list
The user table shows every registered account with the following columns:
The **Users** card shows the number of accounts in its head and a table of every registered account with the following columns:
| Column | Description |
|--------|-------------|
@@ -17,32 +17,32 @@ The user table shows every registered account with the following columns:
| **Last Login** | Date and time of most recent login |
| **Actions** | Edit and delete buttons |
Your own account row is highlighted. You cannot delete your own account.
Your own row is highlighted and marked **(You)**. Its delete button is disabled: you cannot delete your own account.
## User actions
### Edit a user
Click the pencil icon on any row to open the edit form. You can change:
Click the pencil icon (**Edit User**) on any row to open the edit dialog. You can change:
- **Username**
- **Email address**
- **Role** — a dropdown with **User** and **Administrator**
- **Password** — set a new password. It must be at least 8 characters and contain an uppercase letter, a lowercase letter, a number and a special character; commonly used passwords and strings made of a single repeated character are rejected. The same rules apply to the password you set under [Creating a user directly](#creating-a-user-directly). See [Login and Registration](Login-and-Registration#password-requirements).
- **Role**: **User** or **Administrator**
- **New Password**: leave it empty to keep the current password, or set a new one. It must be at least 8 characters and contain an uppercase letter, a lowercase letter, a number and a special character; commonly used passwords and strings made of a single repeated character are rejected. The same rules apply to the password you set under [Creating a user directly](#creating-a-user-directly). While you type, a checklist under the field ticks off each rule as it is met. See [Login and Registration](Login-and-Registration#password-requirements).
Click **Save** to apply changes.
Below the fields sits **Reset passkeys**, which removes every passkey that user has registered — the recovery path when someone loses their authenticator. It asks for confirmation, reports how many passkeys it removed, and takes effect immediately rather than on **Save**. The user can still sign in with their password. See [Passkeys](Passkeys).
Below the fields sits **Reset passkeys**, which removes every passkey that user has registered: the recovery path when someone loses their authenticator. It asks for confirmation in a dialog, reports how many passkeys it removed, and takes effect immediately rather than on **Save**. The user can still sign in with their password. See [Passkeys](Passkeys).
### Delete a user
Click the trash icon and confirm. Deletion is permanent. The user's account is removed from the database along with their data (cascade behavior is enforced at the database level).
Click the trash icon and confirm in the **Delete user** dialog (**Delete user "name"? All trips will be permanently deleted.**). Deletion is permanent. The user's account is removed from the database along with their data, including the trips they own (cascade behavior is enforced at the database level).
You cannot delete your own account while logged in as that user.
## Creating a user directly
Click **Create User** (top-right of the Users tab) to create an account without an invite link. You set the username, email, password, and role at creation time.
Click **Create User** (top right of the **Users** card) to create an account without an invite link. The dialog asks for **Username**, **Email** and **Password** (all required, with the same password checklist as above) and the **Role**.
## Invite links
@@ -52,13 +52,13 @@ Invite links let a specific number of people register themselves. This is useful
### Creating an invite
Click **Create Link** (invite links section, below the user table). Configure:
Click **Create Link** on the **Invite Links** card, below the user table. A dialog opens:
- **Max uses** — how many times the link can be used before it expires: `1×`, `2×`, `3×`, `4×`, `5×`, or `∞` (unlimited). Defaults to `1×`.
- **Expiry** — how long the link remains valid: `1d`, `3d`, `7d`, `14d`, or `∞` (no expiry). Defaults to `7d`.
- **Add to trip** (optional) — bind the invite to a trip. Anyone who registers through the link is automatically added to that trip as a member. Defaults to **No trip** (a plain registration invite). The selector only appears when at least one trip exists.
- **Max. Uses**: how many times the link can be used before it expires: `1×`, `2×`, `3×`, `4×`, `5×`, or `∞` (unlimited). Defaults to `1×`.
- **Expires after**: how long the link remains valid: `1d`, `3d`, `7d`, `14d`, or `∞` (no expiry). Defaults to `7d`.
- **Add to trip (optional)**: bind the invite to a trip. Anyone who registers through the link is automatically added to that trip as a member. Defaults to **No trip** (a plain registration invite). The selector only appears when at least one trip exists.
After creation the link is copied to your clipboard automatically. Share it with the intended recipient. The URL format is:
Click **Create & Copy**: the link is created and copied to your clipboard. Share it with the intended recipient. The URL format is:
```
<APP_URL>/register?invite=<token>
@@ -69,13 +69,13 @@ After creation the link is copied to your clipboard automatically. Share it with
Existing invites are listed below the creation button. Each row shows:
- The invite token (truncated, monospace)
- A status badge — `active`, `used up`, or `expired`
- **Usage** — `used / max` (or `used / ∞` for unlimited)
- **Expiry** date, if set
- **Adds to** — the bound trip, if the invite is trip-bound
- **Created by** — the admin who generated the link
- A **copy link** button (only shown for active invites)
- A **delete** (revoke) button
- A status badge: **Active**, **Used up** or **Expired** (used up and expired rows are dimmed)
- Usage as `used/max used` (or `used/∞` for unlimited)
- The expiry date, if set
- **adds to** the bound trip, if the invite is trip-bound
- **by** the admin who generated the link
- A **Copy link** button (only on active invites)
- A delete (revoke) button
Revoking an invite immediately invalidates it; anyone following the link after revocation will receive an error.
+8 -1
View File
@@ -40,9 +40,15 @@ Visits detected automatically from your trips are shown in addition to any count
At zoom level 5 and above, the map switches to a sub-national region view (states, provinces, etc.). You can mark individual regions as visited or add them to your bucket list. Marking a region also counts the parent country as visited if it was not already.
A region on your bucket list is drawn with the same diagonal hatch as a wished-for country, so a state or province you want to see stands out on the region view too.
### A country's places
Clicking a visited country opens its card, with the flag, the number of trips and, once you have been to any, the number of regions. The **Places** badge (*Show the places in this country*) opens every place counted for that country as a list grouped by trip, with a **Search places** box to narrow it. Clicking a place opens the trip it belongs to, so a place imported into the wrong country can be found and fixed.
## Bucket list
The bucket list is separate from "visited". Use it to track countries or places you want to visit in the future. Each bucket list item can have a name, coordinates, country code, optional notes, and a target date.
The bucket list is separate from "visited". Use it to track countries or places you want to visit in the future. Each bucket list item can have a name, coordinates, country code, optional notes, and a target date. An entry can also be a region rather than a whole country.
## Dawarich
@@ -58,6 +64,7 @@ Nothing reaches your Atlas until you confirm it. See [Dawarich](Dawarich) for th
Your Atlas statistics panel shows:
- **Countries visited** — total number of distinct countries you have actually been to. Countries from upcoming trips are counted separately and shown next to this number.
- **Regions**: the number of sub-national regions (states, provinces) you have visited.
- **Trips** — total number of trips across all time.
- **Places** — total number of individual places logged in trips.
- **Cities** — total number of distinct cities visited, derived from the addresses of your places. TREK drops the last comma-separated part (the country), then walks back through the remaining parts and takes the first one that is still non-empty once digits, hyphens and postal marks are stripped, lower-cased so spelling variants collapse into a single entry. This is a heuristic over a formatted address string rather than a lookup, so the figure is approximate: a short address such as `Osteria Francescana, Italy` leaves nothing but the place's own name, and an address whose administrative tail ends on a state or prefecture (`…, Shibuya, Tokyo, 150-0002, Japan`) counts that region rather than the city.
+9 -2
View File
@@ -4,7 +4,7 @@ The audit log records significant actions taken on your TREK instance. Use it to
## Where to find it
**Admin Panel → Audit** tab.
**Admin Panel > Audit** tab, in the **Maintenance** group of the side navigation.
![Audit log](assets/Audit.png)
@@ -42,6 +42,12 @@ A request for an account that can actually be reset writes **two** rows: one wit
| `user.passkey_delete` | Passkey removed (resource = the passkey's numeric ID) |
| `user.passkey_clone_suspected` | A passkey presented a signature counter that did not advance — a possible cloned authenticator. That assertion is rejected, the credential stays enabled |
### SSO
| Action key | Description |
|---|---|
| `oidc.role_change` | An SSO login changed a user's role through the OIDC claim mapping (`from`, `to` and the claim **name** in details, never the claim's value) |
### Trips
| Action key | Description |
@@ -80,6 +86,7 @@ A request for an account that can actually be reset writes **two** rows: one wit
| `admin.place_shadow` | Place Search Log toggled (`enabled` in details) |
| `admin.places_google_only` | Search with Google only toggled (`enabled` in details) |
| `admin.collab_features` | Collaboration features updated |
| `admin.google_daily_limit` | Daily limit for Google calls saved (`daily_limit` in details, `null` for no limit) |
| `admin.transit_provider` | Public transit backend changed (`provider` in details: `transitous` or `google`) |
| `admin.packing_template_create` | Packing template created |
| `admin.packing_template_delete` | Packing template deleted |
@@ -154,7 +161,7 @@ A request for an account that can actually be reset writes **two** rows: one wit
## Pagination
The panel loads 100 entries at a time by default. Click **Load more** at the bottom to fetch the next page. The total count is shown above the table.
The panel loads 100 entries at a time. Click **Load more** at the bottom to fetch the next page, or **Refresh** to reload from the newest entry. The count is shown above the table as `{loaded} loaded · {total} total`.
## IP addresses
+11 -9
View File
@@ -4,7 +4,7 @@ TREK stores all data in a single SQLite database (`travel.db`) plus an `uploads/
## Where to find it
**Admin Panel → Backup** tab.
**Admin Panel > Backup** tab, in the **Maintenance** group of the side navigation. The tab has two cards: **Data Backup** (the list of backups with **Refresh**, **Upload Backup** and **Create Backup**) and **Auto-Backup**.
![Backup tab](assets/Backup.png)
@@ -25,14 +25,14 @@ A backup is a ZIP archive with these entries:
Click **Create Backup** in the Backup tab. The server creates the ZIP and makes it available for download. Up to 3 manual backups can be created per hour per IP address (rate-limit window: 1 hour).
You can also download or delete any existing backup from the list.
You can also **Download** or delete any existing backup from the list. Deleting asks first in TREK's own dialog (**Delete backup "name"?**).
## Restoring a backup
You can restore from:
- **A stored backup** — click **Restore** next to any backup in the list.
- **An uploaded ZIP** — click **Upload Backup** and select a backup file from your computer (maximum upload size: 500 MB by default, configurable with the `BACKUP_UPLOAD_LIMIT_MB` environment variable — see [Environment-Variables](Environment-Variables)).
- **A stored backup**: click **Restore** next to any backup in the list.
- **An uploaded ZIP**: click **Upload Backup** and select a backup file from your computer (maximum upload size: 500 MB by default, configurable with the `BACKUP_UPLOAD_LIMIT_MB` environment variable; see [Environment-Variables](Environment-Variables)).
A second limit caps the **decompressed** size of a restore archive at 5 GB by default (`BACKUP_MAX_DECOMPRESSED_MB`). It applies to both routes — a stored backup as well as an uploaded ZIP — and a restore that exceeds it is refused with `Backup exceeds the maximum decompressed size.` Raise it if your own backups legitimately grow past the default, otherwise they become unrestorable.
@@ -41,6 +41,8 @@ Before restoring, TREK runs integrity checks on the uploaded database:
1. **SQLite `PRAGMA integrity_check`** — verifies the database file is not corrupt.
2. **Required tables present** — confirms the file contains `users`, `trips`, `trip_members`, `places`, and `days`. Files missing any of these are rejected as not being a valid TREK backup.
Either way, TREK asks first in a **Restore Backup?** dialog that names the file, warns that all current data (trips, places, users, uploads) will be permanently replaced, and suggests creating a backup of the current state first. **Yes, restore** starts it; when it is done the page reloads.
> **Warning:** Restoring replaces all current data. Back up your current state first if you want to keep it.
> **Plugins & restart:** `travel.db` and `uploads/` are swapped in immediately. Plugin data and code are **staged** beside the live trees and applied right away: the running plugins hold their databases open, so the restore asks the plugin runtime to shut them down and swaps the trees in the moment the handles are closed. If the runtime isn't up (plugins switched off, or a restore that happens during startup), the staged trees are applied at the next boot instead. Restart the server after restoring an instance that uses plugins — the plugins are stopped for the swap and stay down until the process restarts, and the bundled encryption key is only read at startup.
@@ -62,7 +64,7 @@ The variable only acts while there is no database yet. Once the instance has one
## Auto-backup
Enable scheduled backups in the **Auto-Backup** section of the Backup tab.
Turn on **Enable auto-backup** in the **Auto-Backup** card of the Backup tab, pick the schedule and click **Save**. A new install starts with auto-backup off, set to daily at 02:00 and 7 days of retention.
**Interval** options:
@@ -71,13 +73,13 @@ Enable scheduled backups in the **Auto-Backup** section of the Backup tab.
- Weekly
- Monthly
**Retention** (`Delete old backups after`) — pick one of the preset windows: 1 day, 3 days, 7 days, 14 days, 30 days, or **Keep forever**. Auto-backups older than the chosen window are pruned after each auto-backup run; **Keep forever** (stored as `keep_days = 0`) keeps all backups indefinitely.
**Retention** (**Delete old backups after**): pick one of the preset windows: 1 day, 3 days, 7 days, 14 days, 30 days, or **Keep forever**. Auto-backups older than the chosen window are pruned after each auto-backup run; **Keep forever** (stored as `keep_days = 0`) keeps all backups indefinitely.
**Schedule** options (depend on interval):
- **Hour** — time of day for daily, weekly, and monthly backups (0–23).
- **Day of week** — Sunday through Saturday (for weekly backups).
- **Day of month** — 1–28 (for monthly backups). Day 29–31 is excluded to avoid months with fewer days.
- **Run at hour**: time of day for daily, weekly, and monthly backups (0 to 23, server local time).
- **Day of week**: Sunday through Saturday (for weekly backups).
- **Day of month**: 1 to 28 (for monthly backups). Days 29 to 31 are excluded to avoid months with fewer days.
Auto-backup files are named `auto-backup-<timestamp>.zip` (manual backups use `backup-<timestamp>.zip`).
+9 -4
View File
@@ -29,7 +29,7 @@ Costs is **multi-currency** (#551). Three settings are involved, and they do dif
- The **trip currency** (Trip → Edit trip) is the trip's accounting base. Every balance and settle-up is calculated in it.
- Each **expense** carries **its own currency**. Pick it in the expense dialog and enter what the receipt says (a $100 dinner on a rouble trip is `100 USD`). It is converted into the trip currency at a rate **frozen when you save it**, so a settled debt does not reopen when the market moves.
- Your **display currency** (Settings → General) converts what you *read* (totals, balances, the ledger) into one currency. It changes nothing that is stored. Left on **Trip currency** (the default), each trip is shown in its own currency.
- Your **display currency** (Settings → General → Language & region → **Display currency**) converts what you *read* (totals, balances, the ledger) into one currency. It changes nothing that is stored. Left on **Trip currency** (the default), each trip is shown in its own currency.
165 currencies are supported, with rates from [Frankfurter](https://frankfurter.dev) (no API key needed). When an expense's currency differs from the one you read in, the dialog shows the original beside the converted amount (`$100.00 ≈ 7 668,71 ₽`, marked *live rate* until the expense is saved and its rate frozen), and the ledger row shows both (`$100.00 → 7 668,71 ₽`).
@@ -53,6 +53,7 @@ An expense row shows:
- the **name**, with an amber **Unfinished** chip when nobody has paid it yet (see [Who paid](#who-paid)) and a **Receipts** chip when files are attached,
- the original and the converted amount under the name, when it was entered in another currency,
- the **payers** as chips with what each of them put in (the name is in the tooltip),
- a **Split** line under the payers with every member the expense is shared between, each as an avatar with their share and a tick once their share is marked paid. The tooltip names the person; past six members the rest fold into a **+N** chip whose tooltip lists them,
- the **note** as a pill; click it to read the whole note, click again to fold it,
- the **total**, and under it a green **you lent** or red **you borrowed** chip when the split leaves you up or down on it.
@@ -132,7 +133,7 @@ An expense with no payer is flagged **Unfinished** on its row and counted into t
**Split** decides who owes for the expense. The switch beside the heading has three modes, and a line under it says what the current one does. Every member is listed with a box to tick; an unticked member owes nothing.
- **Equally**: everyone ticked pays the same share, shown beside each name, with the head count and *{amount} per person* under the list. Remainder cents from rounding are handed out deterministically and rotated by the expense, so over a trip nobody is always the one who pays the extra cent.
- **Custom**: type each person's share. Together they have to make the total: under the list, a green *Split matches total* or a red *Sum of splits: … (under by …)* / *(over by …)* says where you stand, and the dialog will not save until it matches.
- **Custom**: type each person's share. Together they have to make the total: under the list, a green *Split matches total* or a red *Sum of splits: … (under by …)* / *(over by …)* says where you stand, and the dialog will not save until it matches. A small switch next to the hint (**Enter shares as**) picks between the currency symbol and **%**. In percent, each person gets a percentage instead, they have to add up to 100 % (a red *… % of 100 % assigned* says when they do not), and TREK turns them into amounts that add up to the total exactly.
- **Ticket**: list what was on the receipt. Each line has an **Item name**, a price and, under *Splitting:*, a chip per member to tick who had it. **Add item** adds a line, the bin removes one. The total is summed from the lines, **Individual shares** shows what each person comes to, cent-exact, and the lines are kept, so the list is still there the next time you open the expense.
## Settlement calculator
@@ -150,9 +151,9 @@ The final budget comes to each member's share of the paid expenses (exact in the
![The Add payment dialog with From and To, the amount, its currency and the day](assets/CostsSettleUp.png)
The **Add payment** dialog has **From** and **To** (the head band reads *You → Anna* as you pick), **Amount**, **Currency** and **Day**. A payment carries **its own currency**: settling a rouble debt with a euro transfer is normal, and its rate is frozen when you record it. A payment made in another currency shows both amounts in the ledger (`$30.00 → 27,00 €`). The day is the day it happened, so a transfer you only get round to recording three days later still lands on the right day; payments recorded before this field existed stay on the day they were recorded.
The **Add payment** dialog has **From** and **To** (the head band reads *You → Anna* as you pick), **Amount**, **Currency**, **Day** and **Note**. The note is free text, such as *Paid in cash, by bank transfer…*; in the ledger it sits on the payment's row as a pill that opens on a click, like an expense's note. A payment carries **its own currency**: settling a rouble debt with a euro transfer is normal, and its rate is frozen when you record it. A payment made in another currency shows both amounts in the ledger (`$30.00 → 27,00 €`). The day is the day it happened, so a transfer you only get round to recording three days later still lands on the right day; payments recorded before this field existed stay on the day they were recorded.
Balances are always netted in the **trip currency** and converted to your display currency once, at the end, so they stay stable even when the trip mixes currencies.
Balances are always netted in the **trip currency** and converted to your display currency once, at the end, so they stay stable even when the trip mixes currencies. An expense or payment in a foreign currency for which no exchange rate is known yet is left out of the balances and totals rather than counted 1:1; see [Currencies](Currencies#expense-currency).
## Costs summary
@@ -165,6 +166,10 @@ Four cards sit above the ledger:
The right-hand column ends with **By category**: spending per category as a ranked list of bars in the category colours. Only categories with spend on them appear, sorted by amount, and the bars are scaled against the biggest category rather than the trip total, so the ranking stays readable.
### Costs in the day plan
With Costs on, the cost pills on the days of the plan and **Total Cost** at its foot (and the same figures in the trip PDF) add up the expenses from Costs, each one once: on the day its booking starts, otherwise the first day its place is planned, otherwise its own date; one without any day still counts in the total. A foreign expense counts at its frozen rate and a refund nets against its day, so **Total Cost** matches **Total trip spend**, and deleting an expense lowers both. With Costs off, a place's own price counts instead, once per place.
## Table view
The table is a second way to read and plan the same expenses, close to the categorized budget sheet TREK had before Costs was rebuilt. Switch to it with the **Table** icon in the bar; **List** brings the ledger back. Search and filters apply to the table as well.
+1 -1
View File
@@ -63,7 +63,7 @@ The feed carries the same events as the `.ics` download:
- **Timed stops**: one event per place in the day plan that has a time, titled with the place name, with its address as the location and its notes as the description. Times follow the place's own time zone.
- **A summary per day**: an all-day event for every day with untimed places or notes, titled with the day's title (or *Day N*), listing those places and notes.
- **Bookings** of every type, transport included. Flights and other rides take their start and end from the departure and arrival points, each in its own time zone. A booking with no date that can be placed is left out.
- **Connections**: a flight or train with several legs becomes one event per leg, titled *{title}: FRA → BER*, with each leg's own departure, arrival and segment reference, so the layover shows as the gap between them. This needs a departure time on every leg; otherwise the booking stays one event.
- **Connections**: a flight, train or cruise with several legs becomes one event per leg, titled *{title}: FRA → BER*, with each leg's own departure, arrival and segment reference, each in the time zone of its own stops, so the layover (or the stay in a port of call) shows as the gap between them. This needs a departure date and time on every leg; otherwise the booking stays one event.
- **Accommodations**: an all-day event covering every night of the stay, from the arrival day to the departure day, so the hotel sits above those days rather than showing up once on the day you check in. The dates come from the trip days the stay is attached to, so reordering days moves the event with them.
- **Check-in and check-out**: separate timed events on the arrival and departure days whenever the stay has those times. If you entered a check-in window, its end becomes the event's end time.
- **Car pickup and drop-off**: a booking of type *Car* also gets two timed events of its own, *Pickup: {title}* and *Drop-off: {title}*, next to the rental's own event, both with the booking's location. Each side prefers its own endpoint (the pickup point for the pickup, the return point for the drop-off) and takes that endpoint's local time and time zone. Otherwise it falls back to the booking's own times and to the time zone of the linked place. A side with no usable date and time from either source is left out, so a rental imported with only one located endpoint can end up with a single event.
+2 -2
View File
@@ -58,7 +58,7 @@ The dialog closes only with its cross or **Cancel**: a stray click beside it or
| Content | No | Markdown. |
| Category | No | One of the trip's categories. |
| Website | No | An address shown as the link button on the card. |
| Attach files | No | Files up to 50 MB each, see [Attachments](#attachments). Needs `file_upload`. |
| Attach files | No | Files up to the upload limit (50 MB by default), see [Attachments](#attachments). Needs `file_upload`. |
## Markdown support
@@ -74,7 +74,7 @@ The text of a note is rendered as GitHub Flavored Markdown with soft line breaks
## Attachments
A note can carry images, PDFs and other files (with the `file_upload` permission), up to **50 MB** each.
A note can carry images, PDFs and other files (with the `file_upload` permission), up to **50 MB** each. An admin can change that limit with the `FILE_UPLOAD_LIMIT_MB` environment variable, which also sets it for the Files tab (see [Environment-Variables](Environment-Variables)).
These file types are refused:
+1 -1
View File
@@ -63,7 +63,7 @@ Members with `collab_edit` can click the lock on an open poll to close it at onc
## Deleting a poll
Members with `collab_edit` can delete a poll with the bin on its card. It goes at once, without asking, for every member.
Members with `collab_edit` can delete a poll with the bin on its card. On the desktop it goes at once, without asking; on the phone TREK asks *Delete poll?* first. Either way it is gone for every member.
## Active and closed sections
+20 -20
View File
@@ -1,6 +1,6 @@
# Collections
Collections is a personal, server-wide library of saved places that lives outside of any single trip. Keep multiple named lists of places you have discovered — a "Norway road trip" wishlist, "Best coffee in Lisbon", "Someday" — each place carrying an idea / want-to-go / visited status, and share a list with other users.
Collections is a personal, server-wide library of saved places that lives outside of any single trip. Keep multiple named lists of places you have discovered (a "Norway road trip" wishlist, "Best coffee in Lisbon", "Someday"), each place carrying an idea, want-to-go or visited status, and share a list with other users.
> **Admin:** enable Collections in [Admin-Addons](Admin-Addons).
@@ -12,7 +12,7 @@ A place you save to a trip only exists inside that trip. Collections is the oppo
## Accessing Collections
When the admin has enabled the addon, a **Collections** entry appears in the main navigation (and a bottom-tab on mobile). Opening it shows your lists on the left, the active list's places in the middle, and a map on the right.
When the admin has enabled the addon, a **Collections** entry appears in the main navigation (and a bottom-tab on mobile). Opening it shows your lists on the left, the active list's places in the middle, and a map on the right. **Expand map** above the map gives it the whole width, and **Show list** brings the places back.
The dashboard also gains a **Collections widget** that surfaces your lists as compact badges. Each user can hide that widget from their own dashboard under **Dashboard widgets** on the Appearance tab (see [Appearance-Settings](Appearance-Settings)) without affecting anyone else.
@@ -28,9 +28,9 @@ The dashboard also gains a **Collections widget** that surfaces your lists as co
Every saved place carries a status you can cycle with one tap:
- **Idea** — something you noted but haven't committed to.
- **Want to go** — on the shortlist.
- **Visited** — been there.
- **Idea**: something you noted but haven't committed to.
- **Want to go**: on the shortlist.
- **Visited**: been there.
Status is a Collections concept and is not carried into a trip when you copy a place.
@@ -39,7 +39,7 @@ Status is a Collections concept and is not carried into a trip when you copy a p
You usually find out you have been somewhere while looking at the trip, not while browsing the library, so the status can be set from there too:
- The **Save to list** dialog on a trip place shows every list that already holds it, each with its own status pill. Tap a pill to cycle that list's status, or use **Visited everywhere** to mark all of them at once.
- The places panel has a **mark visited** action in its selection bar (and in the bulk toolbar on phones). Select the places — *Select all* covers the whole trip — and every saved copy of them is marked visited.
- The places panel has **Mark visited in your lists** in its selection bar (and in the bulk toolbar on phones). Select the places (**Select all** covers the whole trip) and every saved copy of them is marked visited.
![The Save to list dialog: the place's name in the head band, the lists below with a tick for the ones holding it, and View at its foot](assets/SaveToList.png)
@@ -51,34 +51,34 @@ Places can be assigned a **category** from the same admin-defined set used acros
## Adding places
- **Search and add** — the "+" action opens a search; pick a result and set the name, category, status, a markdown description and links before saving, all in one step.
- **Save from a trip** — the place inspector and the trip place context menu both offer **Save to collection**, which toggles that place in or out of each of your lists.
- **Bulk-add from a trip** — in the trip place list, enter select mode, tick several places, and use the **Save to collection** action in the selection bar to copy them all into a chosen list at once. Duplicates (by name or coordinates) are skipped automatically.
- **Import a whole trip** — the download button in the list's filter row (and the second button on an empty list) opens **Import from a trip**: pick one of your trips, then tick the places you want. Places you already saved are greyed out and cannot be picked twice, and the ones no day of that trip holds start out selected, since those are the plans a trip left behind. **Only new** hides everything already on the list, and the counter on the import button always shows what is about to be added.
- **Search and add**: the **+** (*Add a place*) at the start of the filter row opens a search; pick a result and set the name, category, status, a markdown description and links before saving, all in one step.
- **Save from a trip**: the place inspector and the trip place context menu both offer **Save to collection**, which toggles that place in or out of each of your lists.
- **Bulk-add from a trip**: in the trip place list, enter select mode, tick several places, and use the **Save to collection** action in the selection bar to copy them all into a chosen list at once. Duplicates (by name or coordinates) are skipped automatically.
- **Import a whole trip**: the download button in the list's filter row (and the second button on an empty list) opens **Import from a trip**: pick one of your trips, then tick the places you want. Places you already saved are greyed out and cannot be picked twice, and the ones no day of that trip holds start out selected, since those are the plans a trip left behind. **Only new** hides everything already on the list, and the counter on the import button always shows what is about to be added.
## Place detail
Clicking a saved place opens a detail sheet showing a cover photo (fetched automatically when the place has none of its own), its category, its [labels](#custom-labels), a live status control, a markdown description, and links. Editing the place also lets you assign its labels. From there you can edit the place, **copy it into a trip**, or remove it from the list.
Clicking a saved place opens a detail sheet showing a cover photo (fetched automatically when the place has none of its own), its category, its [labels](#custom-labels), a live status control, a markdown description, and links. Editing the place also lets you assign its labels. From there you can **Edit** the place, **Copy to trip**, open it in a map app with **Navigation** (see [Opening a place in a map app](Places-and-Search#opening-a-place-in-a-map-app)), or **Remove from list**, which asks first. On the phone, the saved place's sheet has the same **Navigation** button.
To set your own cover instead of the auto-fetched one, use the camera button on the detail sheet's cover to upload an image (JPG, PNG, GIF or WebP, up to 20 MB); the remove button next to it clears the custom image and restores the automatic default.
## Filtering and bulk actions
Above the places sit compact filters — by **status**, by **category**, and by [**label**](#custom-labels) — plus a **Select** toggle. In select mode you can:
Above the places sit compact filters: by **status**, by **category**, by average star rating (**All**, or a floor from **5+** down to **1+**) and by [**label**](#custom-labels), an order (**Default**, the saved order, or by name), plus a **Select** toggle. In select mode you can:
- **Select all** the currently filtered places.
- **Assign label** — add one or more of the list's labels to every selected place at once.
- **Copy to trip** — copies the selected places into any of your trips (carrying their name, description, category, notes, price, coordinates, photo and tags).
- **Move** or **Duplicate** the selection into another of your lists.
- **Assign label**: add one or more of the list's labels to every selected place at once.
- **Copy to trip**: copies the selected places into any of your trips (carrying their name, description, category, notes, price, coordinates, photo and tags).
- **Move to list** or **Duplicate to list**: the selection goes into another of your lists.
- **Delete** the selection.
## Custom labels
Each list can define its own **labels** — for example *Berlin*, *Hamburg* and *Ostsee* inside a "Germany 2026" list — to group its saved places beyond the shared category set. Labels belong to the one list they're created in and are shared with everyone on it.
Each list can define its own **labels**, for example *Berlin*, *Hamburg* and *Ostsee* inside a "Germany 2026" list, to group its saved places beyond the shared category set. Labels belong to the one list they're created in and are shared with everyone on it.
- **Manage** — a label manager (reachable from the filter bar) lets you create, rename, recolour and delete labels.
- **Assign** — set a place's labels from its detail sheet, or add labels to many places at once with **Assign label** in the selection bar.
- **Filter** — pick one or more labels in the filter bar to narrow **both the place list and the map** to places carrying any of them.
- **Manage**: **Manage labels**, reachable from the filter bar, lets you create, rename, recolour and delete labels.
- **Assign**: set a place's labels from its detail sheet, or add labels to many places at once with **Assign label** in the selection bar.
- **Filter**: pick one or more labels in the filter bar to narrow **both the place list and the map** to places carrying any of them.
Managing and assigning labels needs edit rights (Editor or Admin); **filtering by label is available to every member, including Viewers**. Moving a place to another list drops its labels, since labels belong to the source list.
@@ -92,7 +92,7 @@ When sharing, the owner assigns each member a permission role, and can change it
| Role | Can do |
|---|---|
| **Viewer** | View the list, cast their own star rating on its places, copy its places into their own trips, and filter by label — no other changes to the list. |
| **Viewer** | View the list, cast their own star rating on its places, copy its places into their own trips, and filter by label; no other changes to the list. |
| **Editor** *(default)* | Add new places and edit existing ones, and manage + assign the list's labels. |
| **Admin** | Everything an editor can, plus delete places. |
+3 -1
View File
@@ -58,8 +58,10 @@ See the [[Development Environment|Development-environment]] page for the full se
| Backend | NestJS 11 (Express 4 adapter), TypeScript, better-sqlite3, Zod (@trek/shared) |
| Real-time | WebSocket (ws) |
| Database | SQLite with WAL mode |
| Auth | JWT (HS256), bcrypt, TOTP MFA, OIDC |
| Auth | JWT (HS256), bcrypt, TOTP MFA, passkeys (WebAuthn), OIDC |
| Maps | Leaflet + react-leaflet (default, OpenFreeMap vector basemap via maplibre-gl-leaflet), MapLibre GL, Mapbox GL, OSRM, Nominatim |
| i18n | 27 languages, EN canonical (locale directories live in shared/src/i18n/) |
Documentation changes go to `wiki/`. The same pages ship inside the app: the in-app help reads them (served under `/api/help`) and links into them, and the MCP help tools search them, so a wiki edit reaches users with the next release as well as the GitHub wiki.
Every translation key must exist in all 27 locales — the `i18n Key Parity` CI job fails on drift, so run `npm run i18n:parity:strict --workspace=shared` before pushing. Two directory names differ from the language they hold: Brazilian Portuguese is `br`, Greek is `gr`.
+15 -15
View File
@@ -12,7 +12,7 @@ You can also open it directly via a deep link: navigate to `/dashboard?create=1`
### Title (required)
The trip name. Cannot be empty — saving is blocked until a title is entered.
The trip name. It cannot be empty: saving is blocked with *Title is required* until a title is entered.
### Description (optional)
@@ -20,9 +20,9 @@ A short free-text description. It is not shown on the trip card or on the Spotli
### Dates
Set a **Start date** and **End date** using the date picker. The day count is calculated automatically when both are set. A trip can span up to **999 days**.
Set a **Start Date** and **End Date** using the date picker. The picker starts its week on the day chosen under Settings > General > Language & region > **Week starts on**. The day count is calculated automatically when both are set. A trip can span up to **999 days**.
On desktop, if you leave **both** dates empty, a separate **Day count** field appears. Enter a number between **1 and 999** to create a date-less itinerary with a fixed number of days. The mobile sheet has no such field: a date-less trip created there always starts with 7 days.
On desktop, if you leave **both** dates empty, a separate **Number of Days** field appears. Enter a number between **1 and 999** to create a date-less itinerary with a fixed number of days. The mobile sheet has no such field: a date-less trip created there always starts with 7 days.
Only the **start** date is linked to the other one. Picking a start date fills the end date to match it, and moving the start date of an already-dated trip shifts the end date so the previous duration is kept. Nothing links them the other way round: you can pick an end date on its own, and the picker's **✕** button clears either field afterwards. A trip can therefore be saved with both dates, with only a start date, with only an end date, or with neither. A trip left with exactly one date gets an undated day grid (7 days by default), just like a date-less one.
@@ -30,26 +30,26 @@ The same dialog changes the dates of an existing trip later. The day plans follo
### Currency
The trip's currency — its **accounting base**. Every expense in the Costs tab is converted into it, and every balance and settle-up suggestion is calculated in it. The dialog pre-fills your own display currency (Settings → General → *Display currency*); if you left that on **Trip currency**, it falls back to **EUR**. An administrator can preset the instance-wide value under Admin → **User Defaults**, which new users inherit until they pick their own. 165 currencies are available.
The trip's currency, its **accounting base**. Every expense in the Costs tab is converted into it, and every balance and settle-up suggestion is calculated in it. The dialog pre-fills your own display currency (Settings > General > Language & region > *Display currency*); if you left that on **Trip currency**, it falls back to **EUR**. An administrator can preset the instance-wide value under Admin → **User Defaults**, which new users inherit until they pick their own. 165 currencies are available.
Pick the currency you will actually settle up in. It is not a cosmetic label, but it is not a one-way door either: you can change it later from the same dialog (with the `trip_edit` permission), and TREK re-bases the existing expenses so no money moves — see [Currencies → Changing the trip currency](Currencies#changing-the-trip-currency).
Pick the currency you will actually settle up in. It is not a cosmetic label, but it is not a one-way door either: you can change it later from the same dialog (with the `trip_edit` permission), and TREK re-bases the existing expenses so no money moves; see [Currencies → Changing the trip currency](Currencies#changing-the-trip-currency).
> This is **not** the same as the display currency in Settings → General, which changes what *you* read on trips that already exist. See [Currencies](Currencies).
> This is **not** the same as the display currency in Settings > General, which changes what *you* read on trips that already exist. See [Currencies](Currencies).
### Cover Image
The cover image is displayed on the trip card and as the background of the Spotlight card. You can add one in four ways:
- **Drag and drop** an image file onto the dashed upload area.
- **Paste from clipboard** — if you have an image in your clipboard, paste it anywhere in the dialog.
- **File picker** — click the upload area to browse for a file.
- **Search Unsplash** — type a query to pick a stock photo. If this returns *"Unsplash search unavailable"* (common on VPS/datacenter IPs), configure a free Unsplash Access Key — see [Environment-Variables → Image Search (Unsplash)](Environment-Variables#image-search-unsplash).
- **Paste from clipboard**: if you have an image in your clipboard, paste it anywhere in the dialog.
- **File picker**: click the upload area to browse for a file.
- **Search Unsplash**: type a query to pick a stock photo. If this returns *"Unsplash search unavailable"* (common on VPS/datacenter IPs), configure a free Unsplash Access Key; see [Environment-Variables → Image Search (Unsplash)](Environment-Variables#image-search-unsplash).
When **creating** a new trip the cover image field is always visible. When **editing** an existing trip it is only shown if you have the `trip_cover_upload` permission. For a new trip, the image is uploaded immediately after the trip is created.
### Reminder
A push notification sent before the trip departs. The field shows a set of preset options:
A notification sent before the trip departs, on the channels you receive notifications on. The **Reminder** field shows a set of preset options:
| Option | Days before departure |
|---|---|
@@ -57,21 +57,21 @@ A push notification sent before the trip departs. The field shows a set of prese
| 1 day | 1 |
| 3 days | 3 |
| 9 days | 9 |
| Custom | 1–30 (you enter the number) |
| Custom | 1 to 30 (you enter the number) |
When **creating** a new trip the reminder field is always visible. When **editing** an existing trip it is only shown to the **trip owner** or **admin** users.
If reminders are disabled on your instance (`trip_reminders_enabled = false`), the reminder section is shown at reduced opacity with an informational message in place of the preset buttons.
A new trip starts on **3 days**. If reminders are switched off on your instance, the reminder section is shown at reduced opacity with the message *Trip reminders are disabled. Enable them in Admin > Settings > Notifications.* in place of the preset buttons, and a new trip gets no reminder.
> **Admin:** Trip reminders are controlled by a server-side feature flag (`trip_reminders_enabled`). Contact your administrator to enable them.
> **Admin:** Trip reminders are switched on and off under Admin > **Notifications** > **Trip Reminders**. They are on by default. See [Notifications](Notifications).
### Members
Add initial trip members from the members selector. On a **new** trip, selected members are queued locally and added to the trip immediately after it is saved. The selector shows all registered users on your instance except yourself.
Add initial trip members under **Travel buddies**. On a **new** trip, selected members are queued locally and added to the trip immediately after it is saved. The selector shows all registered users on your instance except yourself.
## Saving
Click **Create New Trip**. The trip is saved, the dialog closes and a *"Trip created successfully!"* toast confirms it — you stay on the dashboard. The new trip is sorted into the trip list by its dates; click its card (or the Spotlight card, if it is the trip that earns that spot) to open the [Trip-Planner-Overview](Trip-Planner-Overview).
Click **Create New Trip** (when editing, the button reads **Update**). The trip is saved, the dialog closes and a *"Trip created successfully!"* toast confirms it, and you stay on the dashboard. The new trip is sorted into the trip list by its dates; click its card (or the Spotlight card, if it is the trip that earns that spot) to open the [Trip-Planner-Overview](Trip-Planner-Overview).
## Related Pages
+20 -13
View File
@@ -4,9 +4,9 @@ TREK has **three** currency settings, and they answer three different questions.
| Setting | Where | Question it answers | Affects |
|---|---|---|---|
| **Trip currency** | Trip → Edit trip | *What is this trip's money?* | Stored data — the base every balance is calculated in |
| **Expense currency** | Costs → expense modal | *What currency did I actually pay in?* | Stored data — that one expense |
| **Display currency** | Settings → General | *What currency do I want to read?* | Presentation only — never the stored data |
| **Trip currency** | Trip → Edit trip | *What is this trip's money?* | Stored data: the base every balance is calculated in |
| **Expense currency** | Costs → expense modal | *What currency did I actually pay in?* | Stored data: that one expense |
| **Display currency** | Settings → General → Language & region | *What currency do I want to read?* | Presentation only, never the stored data |
The short version: **the trip currency is the accounting base, the expense currency is the receipt, and the display currency is your reading glasses.**
@@ -24,13 +24,13 @@ Pick the currency of the place you are travelling to (or the one you will actual
### Changing the trip currency
Changing it is **not** a relabelling — it is a re-basing, and TREK does the work for you so that no money moves:
Changing it is **not** a relabelling: it is a re-basing, and TREK does the work for you so that no money moves:
- Expenses that had no currency of their own (they simply inherited the trip's) are **pinned to the old currency** first. A 9 000 ₽ expense on a trip switching from RUB to EUR stays *9 000 ₽*; it does not silently become 9 000 €.
- Every frozen exchange rate is **re-anchored** to the new base, because a frozen rate is stored relative to the trip currency (see below).
- **Place prices** are pinned the same way. A place price also inherits the trip's currency unless you gave it one of its own, so a €15 museum on a trip switching to JPY is stamped EUR rather than starting to read as ¥15.
The numbers you typed are never rewritten. Each expense keeps its original amount, in its original currency, and its real-world value survives the switch — only the base the balances are expressed in changes.
The numbers you typed are never rewritten. Each expense keeps its original amount, in its original currency, and its real-world value survives the switch. Only the base the balances are expressed in changes.
## Expense currency
@@ -40,7 +40,9 @@ When an expense's currency differs from the trip currency, TREK looks up the liv
> **Why freeze it?** Because a debt settled today shouldn't reopen tomorrow. If balances were recomputed at live rates, a settled-up trip would drift back into a few cents of debt every time the FX market moved. The rate you booked at is the rate you owe at.
Rates come from [Frankfurter](https://frankfurter.dev) (European Central Bank data, no API key needed). **165 currencies** are supported. If the rate lookup fails (the instance is offline, or the upstream is down), the expense is stored without a frozen rate and falls back to live conversion when it is next read — TREK never invents a rate.
Rates come from [Frankfurter](https://frankfurter.dev) (European Central Bank data, no API key needed). **165 currencies** are supported. If the server cannot look the rate up (the instance is offline, or the upstream is down), your browser lends the rate it already holds when you save, and the server freezes that one. When no rate is known at all, the expense is stored without a frozen rate, and TREK never invents one: until a rate is pinned, the expense is **left out** of the balances, the settle-up suggestions, the final budgets and the totals instead of being counted 1:1 in the trip currency. As soon as someone who may edit costs opens the Costs tab, TREK pins the missing rates for those rows, and they count from then on.
> **AI / MCP:** `get_settlement_summary` lists such rows under `unconverted`, and `freeze_budget_rates` pins the server's current rate on them. See [MCP-Tools-and-Resources](MCP-Tools-and-Resources).
### Settle-up payments
@@ -48,7 +50,7 @@ A payment recorded in **Settle Up** also carries its own currency, for the same
## Display currency
**Settings → General → Currency** is a **per-user, presentation-only** preference. It converts what you *read* in the Costs tab — totals, the category chart, balances, the settle-up amounts — into a single currency, so a trip with dollars, yen and roubles in it still adds up to one number you understand.
**Settings → General → Language & region → Display currency** is a **per-user, presentation-only** preference. It converts what you *read* in the Costs tab (totals, the category chart, balances, the settle-up amounts) into a single currency, so a trip with dollars, yen and roubles in it still adds up to one number you understand.
It never changes what is stored. Two people looking at the same trip can read it in different currencies and both see correct, consistent balances.
@@ -61,9 +63,11 @@ It has two modes:
Leave it on **Trip currency** unless you specifically want everything in your home currency regardless of where you are going.
An administrator can set an instance-wide default (Admin → User Defaults), and it interacts with **Trip currency**: picking **Trip currency** stores an *empty* value, and an empty value on a defaultable setting counts as "not set", so the admin's currency is applied again (#1634). While an instance-wide default currency is configured, there is no way back to per-trip currencies from the Settings page — the admin has to clear it.
An administrator can set an instance-wide default (Admin → User Defaults), and it interacts with **Trip currency**: picking **Trip currency** stores an *empty* value, and an empty value on a defaultable setting counts as "not set", so the admin's currency is applied again (#1634). While an instance-wide default currency is configured, there is no way back to per-trip currencies from the Settings page; the admin has to clear it.
> Display conversion uses **live** rates, not the frozen ones — it is a view, and a view should reflect today. This is why a converted total can shift slightly day to day while the underlying balances stay rock steady.
> Display conversion uses **live** rates, not the frozen ones: it is a view, and a view should reflect today. This is why a converted total can shift slightly day to day while the underlying balances stay rock steady.
An expense you enter in your display currency reads back exactly as you typed it on the day you enter it, on its row, in the totals and in the final budget, and paying the amount settle-up offers for it leaves both balances at zero. When the rate has moved since, the row shows the value the totals count, with what was entered and the trip-currency amount it was booked at underneath (`$801.76 → 685,26 €`).
## How they fit together
@@ -80,15 +84,15 @@ An expense flows through all three:
live here a display currency
```
Balances are always netted in the **trip currency** and converted to your display currency **once, at the end** — never per-expense. That ordering is deliberate: netting in a moving display currency would let rounding drift shuffle a settled trip into phantom one-cent debts.
Balances are always netted in the **trip currency** and converted to your display currency **once, at the end**, never per expense. That ordering is deliberate: netting in a moving display currency would let rounding drift shuffle a settled trip into phantom one-cent debts.
## The public share link
A public share page has no logged-in viewer, so it cannot use "your" display currency. It uses **the sharer's display currency, falling back to the trip's own currency** — i.e. a guest sees the trip the way the person who shared it sees it. If the sharer left their display currency on **Trip currency**, guests read the trip in the trip's currency.
A public share page has no logged-in viewer, so it cannot use "your" display currency. It uses **the sharer's display currency, falling back to the trip's own currency**, so a guest sees the trip the way the person who shared it sees it. If the sharer left their display currency on **Trip currency**, guests read the trip in the trip's currency.
## Relationship with the Costs addon
The **trip currency lives on the trip itself**, not in the Costs addon — it is set in the trip dialog and remains set even if Costs is disabled. Expense currencies, frozen rates and settle-up all belong to **Costs** (addon id `budget`), which an admin can toggle in [Admin-Addons](Admin-Addons). Turning Costs off hides the money features; it does not clear the trip's currency.
The **trip currency lives on the trip itself**, not in the Costs addon. It is set in the trip dialog and remains set even if Costs is disabled. Expense currencies, frozen rates and settle-up all belong to **Costs** (addon id `budget`), which an admin can toggle in [Admin-Addons](Admin-Addons). Turning Costs off hides the money features; it does not clear the trip's currency.
Changing the trip currency requires `trip_edit`. Adding or editing expenses (and their currencies) requires `budget_edit`. See [Admin-Permissions](Admin-Permissions).
@@ -100,8 +104,11 @@ Fixed in v3.4.0 (#1543). The settlement was reading the trip currency incorrectl
**"The totals move slightly from day to day."**
Expected, if your display currency differs from the trip currency: the *display* conversion uses live rates. The underlying balances and debts do not move.
**"A foreign expense does not count in the balances or the total."**
No exchange rate was known for its currency when it was saved, so TREK leaves it out rather than guess. Open the Costs tab as a member who may edit costs while the instance can reach the rate service; the missing rate is pinned and the expense counts again.
**"An expense shows an odd converted value."**
Its rate was frozen when it was entered, and the market has moved since. That is by design — see the note above.
Its rate was frozen when it was entered, and the market has moved since. That is by design; see the note above.
## See also
+7 -1
View File
@@ -1,6 +1,6 @@
# Dashboard Widgets
The My Trips dashboard has a widget sidebar holding a currency converter, a timezone clock and a list of upcoming reservations, plus a Collections shortcut when the [Collections](Collections) addon is enabled (it ships disabled). Installed plugins can contribute further widgets to the same sidebar. This page covers the currency converter and the timezone clock.
The My Trips dashboard has a widget sidebar holding a currency converter, a timezone clock and a list of upcoming reservations, plus a Collections shortcut when the [Collections](Collections) addon is enabled (it ships disabled). Installed plugins can contribute further widgets to the same sidebar. This page covers the currency converter, the timezone clock and the upcoming reservations list.
![Dashboard Widgets](assets/DashboardWidgets.png)
@@ -56,6 +56,12 @@ Clocks refresh every 30 seconds and are always shown in 24-hour time — the 12-
---
## Upcoming reservations
**Upcoming reservations** lists the next six bookings across all your trips that are not archived, soonest first. A booking counts when its time is still ahead, or, without a time, when its day is today or later; cancelled bookings are left out. A hotel stay is not listed as a whole: its **Check-in** and **Check-out** appear as two entries of their own. Each row shows the date, the time in your 12 or 24 hour format, the title with a **Pending** tag while the booking is not confirmed, and the booking's type as an icon. Click a row to open its trip. With nothing ahead the widget reads *Nothing booked yet.*
---
## See also
- [My-Trips-Dashboard](My-Trips-Dashboard)
+18 -9
View File
@@ -15,15 +15,16 @@ Which days are expanded is saved per trip in `localStorage` (key `day-expanded-{
From left to right, the head band of a day shows:
- **The day tile:** the day's number, and under it the forecast temperature when the day has a date and a place to take the weather from. A reading that starts with **Ø** is a climate estimate, not a forecast. Rest the pointer on it for the weather and the place it is for. See [Weather Forecasts](Weather-Forecasts).
- **The title and the date.** A day without a title of its own reads **Day 1**, **Day 2** and so on. Rename a day in the [Day details panel](#day-detail-panel).
- **The title and the date.** A day without a title of its own reads **Day 1**, **Day 2** and so on. Rename a day in the [Day details panel](#day-detail-panel). With **Date first in day headings** on (Settings > General > Travel & map), the date leads and the day's title or number follows it, here and in the day details.
- **Pills** for what the day holds:
- the stay, with a hotel icon: green on the check-in day, red on the check-out day, grey for the nights in between. Rest the pointer on it for *Check-in: Hotel Adler* or *Check-out: Hotel Adler*, and click it to open the place. See [Accommodations](Accommodations).
- the stay, with a hotel icon: green on the check-in day, red on the check-out day, grey for the nights in between. Rest the pointer on it for *Check-in: Hotel Adler* or *Check-out: Hotel Adler*, and click the name to open the place. A stay with a booking has a ticket at the end of the pill (*Open booking*) that opens the booking's detail. A stay whose booking is not confirmed yet has a dashed pill, and its tooltip adds *(Pending)*. See [Accommodations](Accommodations).
- a rental car that runs across the day, with a car icon. Click it to open the booking.
- the day's cost: with the [Costs](Budget-Tracking) addon on, the expenses of the day, added up. An expense counts on the day its booking starts, else on the first day its place is planned, else on its date. With Costs off, the prices of the day's places.
- a label a plugin gives the day, for example the leg of the trip it belongs to.
- **+** (*Add to day*): the menu of everything a day can be given, see below. Shown to members who can edit days.
- **The chevron** expands or collapses the day.
Right click the head band for the same entries as **+**, and, on a day with places on it, **Clear day**. See [Clearing a day](#clearing-a-day).
### Adding to a day
![A day card with its + menu open: Add place to this day, Add accommodation, Add transport, Public transit and Add Note](assets/PlanDayAddMenu.png)
@@ -47,7 +48,7 @@ An expanded day lists its places, bookings, transports and notes in one merged o
A place row shows:
- **The photo** of the place, or its category tile. Click it to lock the place (*Keep position during route optimization*): a lock covers the picture and the row takes a faint red tint. Click again to unlock. See [Route Optimization](Route-Optimization#optimize-route).
- **The category icon and the name.** Under them the time as a white badge (a start, or a start and an end) and the description or the address.
- **The category icon and the name.** A stop left out of the route carries an **Off route** pill next to its name, see [Leaving a stop out of the route](#leaving-a-stop-out-of-the-route). Under them the time as a white badge (a start, or a start and an end) and the description or the address.
- **Notes for this day**, when the stop has a note of its own, after a small note icon.
- **Bookings pinned to this stop** as white badges: the type icon with the status (*Reservation confirmed* or *Reservation pending*), the time, and the carrier such as the airline and flight number. A booking with a start and an end point has a route button that draws it on the map (*Show booking routes*), and members who can edit days get a pencil that opens the editor. The place inspector shows the same bookings as cards that open their detail.
- **Participants**, as small avatars, when not everybody joins this stop.
@@ -59,7 +60,7 @@ On hover the row shows a ticket button, **Add booking**, which opens a new reser
A booking with a day that is not pinned to a stop gets a row of its own, tinted in the colour of its type: flights, trains, buses, cars, ferries, restaurants, events and the rest. The row shows the type tile, the title and a second line with:
- the phase of a booking that runs over several days, in capitals: **START**, **ONGOING**, **END**, and for the types with their own words **DEPARTURE**, **IN TRANSIT**, **ARRIVAL**, **PICKUP**, **RETURN** and **DROP-OFF**. See [Multi-day reservations](#multi-day-reservations).
- the time as a white badge, with the time zone on the departure or arrival day when one is set.
- the time as a white badge. On the departure or arrival day of a booking with a time zone, a small globe follows it; rest the pointer on the globe for the time zone.
- the airline and flight number, the train number, platform and seat, or the route.
A public transit journey shows its lines as coloured chips, and its chevron unfolds the itinerary stop by stop. The route button on the right switches the booking's route on the map on and off.
@@ -74,7 +75,7 @@ A note row shows its icon in the note's colour, the title and, under it, the tex
Every place and note row has a **…** button (*More options*) at its right end, which offers the same actions as a right-click on the row:
- **For a place:** **Edit**, **Remove from day**, **Open Website**, one entry per map app (see [Opening a place in a map app](Places-and-Search#opening-a-place-in-a-map-app)), **Save to Collection** with the [Collections](Collections) addon, and **Delete**.
- **For a place:** **Edit**, **Remove from day**, **Leave out of route** (or **Add back to route**) for a place with coordinates, **Open Website**, **Save to Collection** with the [Collections](Collections) addon, and **Delete**. Map apps are not in this menu: navigation goes through the **Navigation** button in the place inspector, see [Opening a place in a map app](Places-and-Search#opening-a-place-in-a-map-app).
- **For a note:** **Edit** and **Delete**.
Which entries appear depends on your permissions and on what the place has, such as a website or coordinates.
@@ -93,6 +94,14 @@ A place with a time keeps the day in time order. Dragging it to a spot that brea
To take a place off a day, choose **Remove from day** in the row's **…** menu, or **Remove from Day** in the footer of the place inspector. On mobile, switch the plan screen to **Plan** and tap the **X** next to the place. **Delete** in the same menu deletes the place itself, from every day.
### Clearing a day
To take every place off a day at once, right click the day's head band and choose **Clear day**. On a phone, **Clear day** sits in the day's sheet. TREK asks first (*Clear Day 3?*): every place comes off the day and stays in the trip, and the day keeps its notes and bookings. **Undo** brings the places back (*Day cleared*). The entry is only there on a day with places on it, for members who can edit days.
### Leaving a stop out of the route
**Leave out of route** in a place's **…** menu keeps the place on the day and on the map, but the day's route skips it and runs from the stop before it straight to the one after. Use it for a place you only visit on foot from somewhere nearby, or one that is just a point of interest. The row then carries an **Off route** pill, and **Add back to route** in the same menu undoes it. On a phone, the route icon on the day's chip in the place sheet does the same. The setting belongs to that one visit, so the same place on another day is still routed.
## Multi-day reservations
A booking that spans several days shows on each of them with its phase:
@@ -127,14 +136,14 @@ Click a day's head band to open its details. The panel floats over the map, betw
- **The head band** carries the day's title and date. Members who can edit days rename the day with the pencil next to the title. The chevron folds the panel to a slim bar (clicking the band does the same), and **X** closes it.
- **The weather** for the day, with the hourly forecast. See [Weather Forecasts](Weather-Forecasts).
- **Reservations**: the day's bookings apart from stays, each with its type tile, title, the place it is pinned to, the time and a status dot. Click one to open its detail.
- **Accommodation**: the stay of the night, with check-in, check-out, the confirmation code and its booking, and **Add accommodation**. See [Accommodations](Accommodations#in-the-day-detail-panel).
- **Accommodation**: the stay of the night, with the confirmation code, its booking and **Add accommodation**. It shows only the time that matters on this day: the check-in on the arrival day, the check-out on the departure day, both for a stay that starts and ends on the same day, and neither on the nights in between. See [Accommodations](Accommodations#in-the-day-detail-panel).
- Cards and panels that [plugins](Plugins) add to a day.
## Toolbar actions
The head band of the days column holds, from left to right:
- **Export**: one dialog with every way a trip leaves TREK, in three groups. **Document** is the PDF of the whole plan (see [PDF-Export](PDF-Export)). **Calendar** offers **Download .ics** and, for members who can manage share links, **Subscribe to calendar** (see [Calendar Feeds](Calendar-Feeds)). **Maps & GPS** offers GPX files: **Whole trip**, **Places only** and **Days as routes** (see [Exporting a trip as GPX](Map-Features#exporting-a-trip-as-gpx)).
- **Export**: one dialog with every way a trip leaves TREK, in three groups. **Document** is the **PDF** of the whole plan and, once some stop has participants or some booking has travelers, **My plan as PDF**: the plan you go on, without the stops and bookings that name only other people (see [PDF-Export](PDF-Export)). **Calendar** offers **Download .ics** and, for members who can manage share links, **Subscribe to calendar** (see [Calendar Feeds](Calendar-Feeds)). **Maps & GPS** offers GPX files: **Whole trip**, **Places only** and **Days as routes** (see [Exporting a trip as GPX](Map-Features#exporting-a-trip-as-gpx)).
- **Undo**: reverses the last action. See [Undo](Trip-Planner-Overview#undo).
- **Expand all days** / **Collapse all days**.
- **Reorder days**: move, add and delete days. Shown to members who can edit days. See [Adding a day](#adding-a-day) and [Deleting a day](#deleting-a-day).
@@ -151,7 +160,7 @@ The selected day ends in its route bar, as long as the day can be routed: two or
![The route bar of the selected day: the Route toggle, the travel mode, Optimize, and the buttons for Google Maps and CoMaps](assets/PlanRouteBar.png)
- **Route** draws the day's route on the map and puts the travel time between each pair of stops into the timeline.
- **The travel mode**: Driving, Walking, and any mode a plugin adds.
- **The travel mode**: Driving, Walking, Cycling, and any mode a plugin adds.
- **Optimize** reorders the day's free places into a shorter route.
- **Open in Google Maps** and **Open in CoMaps** hand the day to a map app.
+1 -1
View File
@@ -52,7 +52,7 @@ The baseline is the snapshot the hourly reset restores to. The admin can update
**Endpoint:** `POST /api/admin/save-demo-baseline`
This is available in the admin panel. The baseline captures the current state of the database — including trip data, settings, and encrypted API keys — so demo features (maps, photos, weather) continue to work after each reset.
In the admin panel, a **Demo Baseline** card sits above the tabs while demo mode is on; its **Save Baseline** button calls this endpoint. The baseline captures the current state of the database, trip data, settings and encrypted API keys included, so demo features (maps, photos, weather) continue to work after each reset.
On first start with demo mode active, TREK seeds three example trips (Tokyo & Kyoto, Barcelona Long Weekend, New York City) owned by the admin and shared with the demo user, then saves the initial baseline automatically.
+8 -1
View File
@@ -190,7 +190,14 @@ The `@trek/shared` package is the single source of truth for code shared between
| `npm run lint` | Lint source |
| `npm run lint:check` | Same command as `npm run lint` — the name CI uses |
| `npm run lint:pages` | Enforce the Page pattern (CI gate) |
| `npm run theme:lint` | Flag styling that bypasses the appearance tokens |
| `npm run theme:lint` | Flag styling that bypasses the appearance tokens (not run in CI) |
| `npm run check:gl-split` | Fail when one built chunk carries both map engines (MapLibre and Mapbox); run after a build |
| `npm run build:analyze` | Production build with the bundle analyzer |
| `npm run e2e` | Playwright end-to-end tests (local only, not in CI) |
| `npm run shots` | Capture the wiki screenshots with Playwright |
| `npm run shots:promote` | Downscale the captured screenshots and move them into `wiki/assets/` |
| `npm run help:media` | Record the help-center pictures against the real app on its own ports, so `npm run dev` can keep running |
| `npm run help:media:promote` | Convert the recorded help pictures to WebP and move them into `public/help-media/` |
| `npm run format` | Format source |
---
+21 -9
View File
@@ -1,6 +1,6 @@
# General Settings
The General tab (Settings → General) controls your locale preferences and a few map-related display options. All changes save immediately to your account and persist across devices.
The General tab (Settings → General) controls your locale preferences and a few planner and map display options. Each setting is a row in a card: a switch, a segmented control or a dropdown on the right. All changes save immediately to your account and persist across devices.
![General Settings](assets/UsrSettings.png)
@@ -8,7 +8,7 @@ The General tab (Settings → General) controls your locale preferences and a fe
Open the user menu in the top navigation bar, select **Settings**, and stay on the **General** tab — it is the tab the page opens on.
The tab is split into three sections: **Startup** (where opening TREK lands), **Language & region** (currency, language, place names, temperature, distance, time format, week start) and **Travel & map** (booking route labels, always show booking routes, explore places on the map, blur booking codes, optimize route from accommodation).
The tab is split into three sections: **Startup** (where opening TREK lands), **Language & region** (currency, language, place names, temperature, distance, time format, week start) and **Travel & map** (open places in, date first in day headings, booking route labels, always show booking routes, compact markers for unplanned places, explore places on the map, blur booking codes, optimize route from accommodation).
> Color mode (Light / Dark / Auto) is **not** here — it lives on the **Appearance** tab. See [Appearance-Settings](Appearance-Settings).
@@ -68,11 +68,11 @@ Your **display currency** — the currency you want to *read* amounts in on the
> This is **not** the trip's currency, which is set on the trip itself and is the base its balances are calculated in. The distinction matters — see [Currencies](Currencies).
An administrator can set an instance-wide default in Admin → Default User Settings. It is not only a starting value for new accounts: it is merged in every time your settings are loaded, so it applies to anyone whose own display currency is empty. Picking a specific currency of your own overrides it. **Trip currency** does not, because it stores an empty value that counts as "not set", so the admin default takes effect again on your next reload.
An administrator can set an instance-wide default in **Admin → User Defaults**. It is not only a starting value for new accounts: it is merged in every time your settings are loaded, so it applies to anyone whose own display currency is empty. Picking a specific currency of your own overrides it. **Trip currency** does not, because it stores an empty value that counts as "not set", so the admin default takes effect again on your next reload.
## Language
Select your preferred language from the button grid (desktop) or dropdown (mobile). The change takes effect immediately without a page reload. See [Languages](Languages) for the full list of supported languages.
Select your preferred language from the row of buttons (a narrow window shows a dropdown instead). The change takes effect immediately without a page reload. See [Languages](Languages) for the full list of supported languages.
## Place names
@@ -111,27 +111,39 @@ An administrator can set the default for everyone under **Admin → User Default
The poll deadline on the phone uses the browser's own date field, which follows the device's region rather than this setting.
## Open places in
Which map app the navigate buttons open. **Ask every time** (the default) keeps the list of every map app a place can be opened in. Pick **Google Maps**, **Waze**, **Apple Maps**, **OpenStreetMap**, **CoMaps**, **高德地图** or, on Android, **Other map app** (a `geo:` link your phone hands to the map app of your choice), and the button opens that app straight away. Apple Maps is not offered on Android. When a place cannot be opened in the app you picked (Amap outside China, Waze for a place without coordinates), the full list appears as before. See [Opening a place in a map app](Places-and-Search#opening-a-place-in-a-map-app).
## Date first in day headings
When on, every day in the day plan leads with its calendar date and shows "Day 1" or the day's own title next to it. Off by default, which keeps the day's name first and the date second.
## Booking route labels
Shows or hides station / airport names on the endpoint markers of booking routes on the map. When off, only the icon is shown. Set to **On** or **Off**.
Shows or hides station / airport names on the endpoint markers of booking routes on the map. When off, only the icon is shown. A switch, on or off.
## Explore places on the map
Shows a row of category buttons on the trip map for finding nearby restaurants, accommodation, sights and more. TREK's own place index answers first and OpenStreetMap fills in, and installed plugins can add buttons of their own; see [Exploring the map by category](Places-and-Search#exploring-the-map-by-category). Set to **On** or **Off**.
Shows a row of category buttons on the trip map for finding nearby restaurants, accommodation, sights and more. TREK's own place index answers first and OpenStreetMap fills in, and installed plugins can add buttons of their own; see [Exploring the map by category](Places-and-Search#exploring-the-map-by-category). A switch, on by default.
## Always show booking routes
When **On**, every booking that has a route (flight, train, car leg, etc.) shows its route line on the map automatically, on every trip, without needing the per-booking toggle. Set to **On** or **Off** — off by default.
When **On**, every booking that has a route (flight, train, car leg, etc.) shows its route line on the map automatically, on every trip, without needing the per-booking toggle. A switch, off by default.
This only sets the *default* for a trip you haven't touched before. If you've already used the per-booking toggle or the trip's "show all / hide all" button (in the day-plan toolbar) on a given trip, that choice is remembered for that trip and isn't overridden by changing this setting afterwards.
## Compact markers for unplanned places
When on, places not planned into any day show on the trip map as small markers without their photo, so the planned stops stand out. Off by default.
## Blur booking codes
When enabled, confirmation codes and reference numbers are blurred until you hover or tap. Set to **On** or **Off**.
When enabled, confirmation codes and reference numbers are blurred until you hover or tap. A switch, off by default.
## Optimize route from accommodation
When **On** (the default), the **Optimize** button in the day's route tools anchors the route on that day's accommodation instead of only reordering the places among themselves: an ordinary day becomes a loop out from the hotel and back to it, a transfer day a run from the hotel you check out of to the one you check into that evening. Set to **On** or **Off**.
When **On** (the default), the **Optimize** button in the day's route tools anchors the route on that day's accommodation instead of only reordering the places among themselves: an ordinary day becomes a loop out from the hotel and back to it, a transfer day a run from the hotel you check out of to the one you check into that evening. A switch.
A day without an accommodation, or one whose hotel has no coordinates, is optimized from its first place as before. Locked and timed places keep their slots either way. See [Route-Optimization](Route-Optimization).
+1 -1
View File
@@ -231,7 +231,7 @@ The dialog lists what a person has to decide about under **Needs a look**, with
**Into TREK**, a document from the store goes through the same checks as an upload in the file manager:
- **The size limit** of 50 MB per file. A larger document is listed as *Too large*.
- **The upload limit**, 50 MB per file unless the server sets another with `FILE_UPLOAD_LIMIT_MB`. A larger document is listed as *Too large*.
- **The blocked types**, which are always refused (HTML, SVG, XML, scripts and executables; the full list is in [Documents-and-Files](Documents-and-Files)).
- **The allowed types** an admin sets under **Admin → Settings → Allowed File Types**. A file without an extension is refused too.
+7 -1
View File
@@ -20,14 +20,20 @@ Drop files onto the dashed upload area under the bar, click it to open the file
When the upload is done and the trip has places or bookings, the **Assign File** dialog opens for the last file you uploaded, so you can tie it to a place or a booking right away (see [Linking files](#linking-files-to-places-reservations-or-assignments)). Close it if the file belongs nowhere in particular.
- **Maximum file size:** 50 MB per file.
- **Maximum file size:** 50 MB per file by default. Videos (mp4, m4v, webm, mov) have their own cap of 500 MB.
- **Blocked file types:** renderable documents (`.svg`, `.svgz`, `.html`, `.htm`, `.shtml`, `.shtm`, `.xml`, `.xhtml`, `.xht`), scripts (`.js`, `.jsx`, `.ts`, `.tsx`, `.mjs`, `.cjs`, `.php`, `.py`, `.rb`, `.pl`) and executables (`.exe`, `.bat`, `.sh`, `.cmd`, `.msi`, `.dll`, `.com`, `.vbs`, `.ps1`, `.app`). These are always refused, as is any file whose MIME type contains `svg`.
- **Allowed types by default:** jpg, jpeg, png, gif, webp, heic, pdf, doc, docx, xls, xlsx, txt, csv, pkpass, pkpasses, md, markdown. The upload area lists the types your instance allows. An admin can change the list under **Admin → Settings → Allowed File Types**: comma-separated extensions, or `*` to allow everything except the blocked types above.
- **Videos:** mp4, m4v, webm and mov files are accepted even when they are not on the allowed list.
> **Admin:** The 50 MB limit is set with the `FILE_UPLOAD_LIMIT_MB` environment variable (see [Environment-Variables](Environment-Variables)); it also applies to booking attachments and collab note attachments, and the upload dialogs refuse a larger file before it is sent. Behind a reverse proxy, raise the proxy's upload limit as well.
Uploading needs the `file_upload` permission; without it the upload area is not shown.
Files also reach this tab from elsewhere: **Attach file** in a booking or transport editor, **Upload** in the Files section of the place inspector, **Attach** in the place dialog, receipts on an expense (see [Budget-Tracking](Budget-Tracking#receipts-and-invoices)) and attachments on a collab note. They all land here.
An AI assistant connected through MCP can add files too: the `upload_trip_file` tool uploads a document to a trip (and can attach it to a booking or a place in the same call) under the same type rules and the `file_upload` permission as the upload area, up to 10 MB per file (or the upload limit, if that is lower). See [MCP-Tools-and-Resources](MCP-Tools-and-Resources).
## Browsing and filtering
The filter tabs in the bar are, in this order: **All**, a star for **Starred** (only once a file is starred), **PDFs**, **Images**, **Documents** (Word, Excel and text files) and **Collab Notes** (only once a note has an attachment). Each tab carries its count.
+7 -5
View File
@@ -33,10 +33,10 @@ The encryption derives a key from `ENCRYPTION_KEY` using SHA-256 (with a domain
On startup, TREK resolves the encryption key in this order:
1. **`ENCRYPTION_KEY` environment variable** — explicit, always takes priority. When set, the value is also written to `./data/.encryption_key` so it survives container restarts if the env var is later removed.
2. **`./data/.encryption_key` file** — present on any install that has started at least once.
3. **`./data/.jwt_secret` file** — one-time fallback for older installs that pre-date the dedicated encryption key. The value is immediately persisted to `./data/.encryption_key` so future JWT rotations cannot break decryption.
4. **Auto-generated** — fresh install with none of the above. A random 32-byte hex key is generated and written to `./data/.encryption_key`.
1. **`ENCRYPTION_KEY` environment variable**: explicit, always takes priority. When set, the value is also written to `./data/.encryption_key` so it survives container restarts if the env var is later removed.
2. **`./data/.encryption_key` file**: present on any install that has started at least once.
3. **`./data/.jwt_secret` file**: one-time fallback for older installs that pre-date the dedicated encryption key. The value is immediately persisted to `./data/.encryption_key` so future JWT rotations cannot break decryption.
4. **Auto-generated**: fresh install with none of the above. A random 32-byte hex key is generated and written to `./data/.encryption_key`.
## What happens if the key is lost
@@ -83,9 +83,11 @@ The script:
- `plugins.config` and `plugin_user_config.config`: every settings field a plugin's manifest marks `secret`, resolved per plugin and scope from `plugin_settings_fields`
- `trip_album_links`: `passphrase`
- `trek_photos`: `passphrase`
- `document_connections`: `secrets` (the one encrypted blob per store and trip, including tokens the store handed out itself, such as Synology's device token)
- `trip_document_links`: `webhook_secret`
5. Reports counts of migrated, already-migrated, skipped (empty), and errored values.
**Not covered by the script:** the document sync credentials (`document_connections.secrets` and `trip_document_links.webhook_secret`) and the instance-wide API key of the AI Parsing addon (`addons.config`). They stay encrypted under the old key and read back as empty afterwards. The AI Parsing key has to be entered again under **Admin → Addons**. A document sync binding fails with *The credentials were refused.* and cannot be repaired from the trip: the connection form only opens for a store the trip has not been connected to yet, and **Disconnect** removes the binding but keeps the stored connection. Removing the trip's row from `document_connections` takes its bindings with it and lets the trip owner connect the store again; the documents themselves stay in TREK and at the store. Rotate before trips are bound to a store where you can. See [Document-Sync](Document-Sync).
**Not covered by the script:** the instance-wide API key of the AI Parsing addon (`addons.config`). It stays encrypted under the old key and reads back as empty afterwards, so enter it again under **Admin > Addons** (the fields under **AI Parsing**).
After a successful migration:
+3 -3
View File
@@ -7,8 +7,8 @@ Complete reference for all environment variables TREK reads.
- **Docker Compose** — use the `environment:` block or a `.env` file alongside `docker-compose.yml`
- **Docker run** — pass each variable with `-e VARIABLE=value`
- **Helm** — use `env:` for plain values and `secretEnv:` for sensitive values in `values.yaml`. The chart only
passes through the keys it declares (33 in `templates/configmap.yaml`, the credentials in `templates/secret.yaml`), so a variable
that is not one of them is dropped silently — patch it onto the Deployment or add it to the chart
passes through the keys it declares (37 in `templates/configmap.yaml`, the credentials in `templates/secret.yaml`), so a variable
that is not one of them (`DEFAULT_LANGUAGE`, `FILE_UPLOAD_LIMIT_MB`, `RESTORE_FROM_BACKUP` and `MCP_MAX_SESSION_PER_USER` among them) is dropped silently. Patch it onto the Deployment or add it to the chart
- **Unraid** — set in the container template editor
- **Proxmox Community Script** — set in `/opt/trek/server/.env`
@@ -455,7 +455,7 @@ through environment variables. `TREK_PLACE_PHOTO_DIR` below is unaffected.
| Variable | Description | Default |
|------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------|
| `TREK_PLACE_PHOTO_DIR` | Directory where cached Google place photos are stored. Created recursively on boot. Set this to point photo storage at a dedicated mounted volume. | `uploads/photos/google` |
| `FILE_UPLOAD_LIMIT_MB` | Maximum size (in MB) of a file uploaded to a trip, a booking or a collab note. The upload dialogs use the same limit. Videos in Journey keep their own 500 MB cap. If you sit behind a reverse proxy, raise its upload limit as well. | `50` |
| `FILE_UPLOAD_LIMIT_MB` | Maximum size (in MB) of a file uploaded to a trip, a booking or a collab note, and of a file Document Sync brings in. The upload dialogs use the same limit and refuse a larger file before the upload starts. Videos keep their own 500 MB cap, and trip covers and place images their 20 MB. The MCP tool `upload_trip_file` takes at most 10 MB, or this limit when it is lower. If you sit behind a reverse proxy, raise its upload limit as well. | `50` |
| `BACKUP_UPLOAD_LIMIT_MB` | Maximum **compressed** size (in MB) of a restore-backup archive that may be uploaded. Raise it if your backups (which include the `uploads/` directory) exceed the default. Non-positive or invalid values abort startup. | `500` |
| `RESTORE_FROM_BACKUP` | Path to a backup ZIP to restore on the **first** start, before any setup. Only acts while no database exists; afterwards it is ignored with a warning. A backup that fails the restore checks stops the start. See [Backups](Backups#restoring-on-a-new-install-before-setup). | none |
| `BACKUP_MAX_DECOMPRESSED_MB` | Maximum **decompressed** size (in MB) of a restore-backup archive — the zip-bomb guard. Independent of `BACKUP_UPLOAD_LIMIT_MB` and enforced on both restore paths, so a restore that fits the upload cap can still be refused with `Backup exceeds the maximum decompressed size.` Raise both when restoring a very large instance. | `5120` (5 GB) |
+3 -1
View File
@@ -2,7 +2,9 @@
## Do I need a Google Maps API key?
No. Place search runs on TREK's own place index, the [TREK Places API](TREK-Places-API), asked together with OpenStreetMap, with no API key, no quota and no account. A Google Maps key only answers where both come up empty, and adds ratings and photos for the places Google finds, which no open dataset has. An admin can add one in **Admin → Settings → API Keys**, see [Places and Search](Places-and-Search#with-a-google-maps-api-key). A key saved there applies instance-wide to every member; there is no per-user field for it in the UI.
No. Place search runs on TREK's own place index, the [TREK Places API](TREK-Places-API), asked together with OpenStreetMap, with no API key, no quota and no account. A Google Maps key only answers where both come up empty, and adds ratings and photos for the places Google finds, which no open dataset has. An admin can add one in **Admin → Settings → API Keys**, see [Places and Search](Places-and-Search#with-a-google-maps-api-key). A key saved there applies instance-wide to every member; there is no per-user field for it in the UI. A key can also come from the `PLACES_API_KEY` environment variable, which then wins over the field, see [Environment-Variables](Environment-Variables#place-search-google-places).
To keep the Google bill in check, the same card has **Daily limit for Google calls**: once today's calls reach it, TREK stops calling Google until the next day (UTC) and searches with OpenStreetMap instead. Today's count sits next to the field. Leave it empty for no limit.
## Can I use TREK offline?
+14 -6
View File
@@ -9,8 +9,9 @@ documentation continues.
## Opening it
Click the **?** in the navbar, next to the theme toggle. It is the only way in, on purpose: a
keyboard shortcut would fire while you were typing a question mark into a note.
Click the **?** (**Help for this screen**) in the navbar, next to the theme toggle. In Journey's
Studio, which has no navbar, the same **?** sits in the Studio toolbar. There is no keyboard
shortcut, on purpose: it would fire while you were typing a question mark into a note.
The panel opens over the app, already on the screen you were looking at. **Escape** closes it, and
the focus goes back to the `?`. If you opened a dialog while following a guide, Escape closes that
@@ -31,7 +32,7 @@ The overview of a screen opens first. It carries:
- a **full-frame picture** of the screen as you find it,
- **On this screen**, a numbered list of what the screen holds and what each part does,
- **How do I…**, a card per guide,
- **In the docs**, the wiki pages that go deeper.
- **In the docs**, the wiki pages that go deeper. A guide's link to them reads **Open in Help & Docs**.
A screen that has sub-screens lists them under **Sub-screens**, folded: the trip folds its plan
columns, its panels and its tabs; Settings and the Admin panel fold their tabs; Journey folds the
@@ -63,6 +64,12 @@ including from inside a guide. Clearing it puts you back where you were.
**Screens** lists every screen that has help, so you can read about one screen while standing on
another. Screens with sub-screens fold; the one you are actually on is marked **This screen**.
### Asking a person
At the bottom of the navigation, under **Missing something?**, are the two places to ask a person:
**Tell us on GitHub** opens a discussion, **Ask on Discord** opens the chat. They are there on
every screen.
## The pictures
Every picture is generated by driving the real app: same viewport, same theme, same language, same
@@ -75,14 +82,15 @@ cost nothing to a visitor who never asks for help.
## Languages
The guides are written in English first and translated into every language TREK speaks. Every button
The guides are written in English first and translated into all 27 languages TREK speaks (see
[Languages](Languages)). Every button
and field a guide names is the app's own string in that language, so what you read matches what you
see.
## When a screen has no help yet
The panel says so and leaves the search box as the way forward. Under it are the two places to ask a
person: **Tell us on GitHub** opens a discussion, **Ask on Discord** opens the chat.
The panel says *No guide for this screen yet.* and leaves the search box as the way forward, with the
**Tell us on GitHub** and **Ask on Discord** links below the navigation.
## See also
+15 -13
View File
@@ -8,19 +8,19 @@ TREK is a self-hosted, real-time collaborative travel planner licensed under AGP
### Planning
- **Drag & Drop Planner**: organize places into day plans with reordering and cross-day moves
- **Interactive Map**: Leaflet map with photo markers, clustering, route visualization, and customizable tile sources
- **Interactive Map**: Leaflet map with photo markers, clustering, route visualization, customizable tile sources, category buttons (plugins can add their own) and a lock that keeps the view where it is
- **Place Search**: TREK's own place index and OpenStreetMap, asked together, with no API key and no quota; Google or Amap answer only where both come up empty (see [TREK Places API](TREK-Places-API))
- **Day Notes**: notes between a day's stops, each with a title, Markdown text, an icon and a colour
- **Route Optimization**: auto-optimize place order and hand the day to Google Maps or CoMaps
- **Route Optimization**: auto-optimize place order, draw the day for driving, walking or cycling, leave single stops out of the route, and hand the day to Google Maps or CoMaps (see [Route Optimization](Route-Optimization))
- **Weather Forecasts**: 16-day forecasts via Open-Meteo (no API key required), historical climate averages as fallback
### Travel Management
- **Reservations & Bookings**: hotels, restaurants, tickets and every other booking with its confirmation code, travelers, costs and files, shown as cards, as a list or on a timeline; flights, trains and cars have their own Transports tab
- **Budget Tracking**: an expense ledger with who paid and itemised splits, settle-up, receipts, a table view with per person and per day figures, multi-currency support (see [Currencies](Currencies))
- **Packing Lists**: category-based checklists with user assignment, templates, and progress tracking
- **Document Manager**: attach documents, tickets, and PDFs to trips, places, or reservations (up to 50 MB per file)
- **Budget Tracking**: an expense ledger with who paid and itemised splits, settle-up, receipts (scanned into an expense with **Scan receipt** when AI Parsing is on), expenses linked to bookings, transports and places, a table view with per person and per day figures, multi-currency support (see [Budget Tracking](Budget-Tracking) and [Currencies](Currencies))
- **Packing Lists**: category-based checklists with user assignment, templates, quantities and weights, progress tracking, and print, PDF, Markdown and CSV export (see [Packing Lists](Packing-Lists))
- **Document Manager**: attach documents, tickets, and PDFs to trips, places, or reservations (up to 50 MB per file by default, set with `FILE_UPLOAD_LIMIT_MB`)
- **Document Sync** _(admin-enabled)_: keep a trip's documents in step with a self-hosted Paperless-ngx, Papra, Nextcloud, OpenCloud or Synology NAS, in both directions, under one connection the trip owner sets up for every member (see [Document Sync](Document-Sync))
- **PDF Export**: export complete trip plans as PDF with cover page, images, and notes
- **PDF Export**: export complete trip plans as PDF with cover page, images, and notes, or only your own activities with **My plan as PDF** (see [PDF Export](PDF-Export))
### Collaboration
- **Real-Time Sync**: WebSocket-based live sync; changes appear instantly for all connected users
@@ -29,7 +29,8 @@ TREK is a self-hosted, real-time collaborative travel planner licensed under AGP
- **OIDC SSO**: sign in with Google, Apple, Authentik, Keycloak, or any OIDC provider
- **Two-Factor Authentication**: TOTP-based 2FA with QR code setup
- **Passkeys** _(admin-enabled)_: passwordless WebAuthn sign-in with Touch ID, Windows Hello, Android screen lock, or a hardware key; owning one also satisfies the require-2FA policy (see [Passkeys](Passkeys))
- **Public Share Links**: share a read-only view of any trip
- **Public Share Links**: share a read-only view of any trip, in full, as **Travel & stays only** or **Without photos** (see [Public Share Links](Public-Share-Links))
- **Notifications**: in-app, email, webhook and ntfy, and Web Push to a phone or computer even while TREK is closed (see [Notifications](Notifications))
### Addons _(admin-toggleable)_
- **Lists**: packing lists and to-dos with templates, member assignments, optional bag tracking
@@ -37,15 +38,15 @@ TREK is a self-hosted, real-time collaborative travel planner licensed under AGP
- **Documents**: file manager for trips, places, and reservations
- **Collab**: group chat, shared notes, polls, day-by-day attendance
- **Road trip**: plan a trip as one continuous drive, with search along the route, driving limits, daily travel times and avoidance of toll roads, motorways and ferries (see [Road Trip](Road-Trip))
- **Vacay**: personal vacation day planner with calendar view, public holidays, and carry-over tracking
- **Atlas**: interactive world map, bucket list, travel stats, continent breakdown
- **Vacay**: personal vacation day planner with calendar view, public holidays, company holidays (also as half days), and carry-over tracking
- **Atlas**: interactive world map with visited countries and regions, bucket list (countries or regions), travel stats, continent breakdown
- **Collections**: a personal place library that saves places across trips into named lists, copies them into any trip, and shares them with per-member roles (see [Collections](Collections))
- **Journey**: magazine-style travel journal with entries, photos (via Immich/Synology Photos), maps, and moods
- **Journey**: magazine-style travel journal with entries, drafts, photos (via Immich/Synology Photos) shown on the journey's map when geotagged, and moods
- **Naver List Import**: import places from shared Naver Maps lists
- **MCP**: expose TREK to AI assistants via the Model Context Protocol (OAuth 2.1)
- **AirTrail**: sync flights from your self-hosted AirTrail instance into trips
- **Dawarich**: read the stays and routes your self-hosted Dawarich instance recorded, offered as suggestions you confirm; nothing is written back (see [Dawarich](Dawarich))
- **AI Parsing**: LLM fallback that extracts bookings from confirmation files KDE Itinerary cannot read (see [AI-Booking-Import](AI-Booking-Import))
- **AI Parsing**: LLM fallback that extracts bookings from confirmation files KDE Itinerary cannot read, and, with a model that reads images, from photos and scanned PDFs and receipts (see [AI-Booking-Import](AI-Booking-Import))
> Dashboard widgets (currency converter and timezone clock) are per-user preferences, not an admin-toggleable addon; see [Dashboard-Widgets](Dashboard-Widgets).
>
@@ -57,7 +58,7 @@ TREK is a self-hosted, real-time collaborative travel planner licensed under AGP
### AI / MCP Integration
- **MCP Server**: built-in Model Context Protocol server with OAuth 2.1 authentication
- **150+ Tools**: create trips, plan itineraries, manage budgets, send messages, and more
- **300+ Tools**: create trips, plan itineraries, manage budgets, upload files, search places near a point, send messages, and more
- **30 Resources**: read-only `trek://` URIs for trips, days, places, budget, packing, journeys, and more
- **35 OAuth Scopes**: granular permissions across 17 permission groups
- **Pre-built Prompts**: `trip-summary`, `packing-list`, and `budget-overview` context loaders
@@ -68,7 +69,8 @@ TREK is a self-hosted, real-time collaborative travel planner licensed under AGP
### Admin
- User management, invite links, packing templates, global categories
- Addon management, API key storage, scheduled auto-backups
- Addon management, API key storage with a daily limit for Google calls, scheduled auto-backups
- Notification defaults: each event and channel on, off or blocked for every user (see [Notifications](Notifications))
- System notices for onboarding and announcements, including a release notes notice every user sees once after each update (see [Admin-GitHub-Releases](Admin-GitHub-Releases#release-notes-notice))
> **Admin:** Most configuration lives in the Admin Panel. On first boot TREK seeds an admin account automatically: credentials come from `ADMIN_EMAIL` / `ADMIN_PASSWORD` if set, otherwise a random password is printed to the container log.
+2
View File
@@ -10,6 +10,8 @@ Click your avatar in the top-right navbar and choose **Help**, or go to `/help`
The page is titled **Help & Docs**. You must be signed in to reach the route.
The [Help Center](Help-Center) (the **?** in the navbar) links here too: its **In the docs** links and **Open in Help & Docs** open the matching page of this wiki at `/help/{slug}`.
## The docs ship with your install
Since **v3.4.0** the wiki is bundled into the TREK image and served from disk (commit `6c87bf2f`). That means:
+2
View File
@@ -62,6 +62,8 @@ The commented `HTTP_PROXY` / `HTTPS_PROXY` / `NO_PROXY` lines are interpolated a
Every other variable — `APP_URL`, the OIDC block, `FORCE_HTTPS`, `TRUST_PROXY`, `ADMIN_EMAIL`/`ADMIN_PASSWORD`, the MCP limits — ships as a commented literal. Uncomment the line in `docker-compose.yml` and put the value there; setting it in `.env` alone has no effect.
A few variables are not in the compose file at all, among them `FILE_UPLOAD_LIMIT_MB` (the upload limit for files, 50 MB by default) and `RESTORE_FROM_BACKUP` (a backup ZIP to restore on the very first start, see [Backups](Backups#restoring-on-a-new-install-before-setup)). Add a line for them to the `environment:` block yourself.
`APP_URL` is usually not needed. TREK resolves its public base URL as `APP_URL` → first `ALLOWED_ORIGINS` entry → `http://localhost:<PORT>`, so the `ALLOWED_ORIGINS` value above already gives OIDC redirect URIs, passkey origin checks and the links in email notifications the correct origin. Uncomment `APP_URL` only when the public base URL has to differ from the first allowed origin.
For a full description of every variable, see [Environment-Variables](Environment-Variables).
+2
View File
@@ -44,6 +44,8 @@ See [Environment-Variables](Environment-Variables) for the full list.
Replace `mauriceboe/trek:latest` in the run command with your chosen tag to pin to a major version or exact release.
Every image carries the standard `org.opencontainers.image.*` labels (title, version, source, documentation, licence), so an update tool such as Renovate links an image update to its release notes. `docker inspect mauriceboe/trek:latest --format '{{json .Config.Labels}}'` shows them.
## Volume Reference
| Volume | Container path | What lives there |
+19 -2
View File
@@ -113,11 +113,24 @@ env:
# ALLOWED_ORIGINS: "https://trek.example.com"
# APP_URL: "https://trek.example.com"
# FORCE_HTTPS: "false" # enable HTTPS redirect + HSTS; set TRUST_PROXY for correct client IPs
# HSTS_INCLUDE_SUBDOMAINS: "false" # add includeSubDomains to the HSTS header
# SESSION_DURATION: "24h" # session length without "Remember me"
# SESSION_DURATION_REMEMBER: "30d" # session length with "Remember me", and every SSO session with OIDC_ONLY
# TRUST_PROXY: "1" # proxy hops for X-Forwarded-For/Proto; defaults to 1 in production
# COOKIE_SECURE: "true" # auto-derived; set "false" only for local HTTP testing
# ALLOW_INTERNAL_NETWORK: "false" # set "true" if Immich or other services are on a private network
# ALLOW_LINK_LOCAL_IPS: "" # single link-local addresses TREK may reach, e.g. "169.254.1.2"
# HTTP_PROXY: "" # outbound proxy for HTTP requests
# HTTPS_PROXY: "" # outbound proxy for HTTPS requests
# NO_PROXY: "localhost,127.0.0.1" # hosts that bypass the proxy
# DEMO_MODE: "false" # enable demo mode (hourly data resets)
# MCP_RATE_LIMIT: "300" # max MCP requests per user per minute
# NOMINATIM_URL: "" # your own Nominatim for every geocoding call
# OVERPASS_URL: "" # your own Overpass endpoint(s), comma-separated
# OVERPASS_TIMEOUT_MS: "25000" # per-endpoint Overpass timeout
# TREK_PLACES_ENABLED: "false" # stop asking the TREK Places API
# TREK_PLACES_URL: "" # a copy of the TREK Places API you run yourself
# AMAP_API_BASE: "" # send the Amap calls through a proxy or gateway
# OIDC_ISSUER: "https://auth.example.com"
# OIDC_CLIENT_ID: "trek"
# OIDC_DISPLAY_NAME: "SSO"
@@ -131,7 +144,7 @@ env:
# VAPID_SUBJECT: "mailto:admin@example.com" # Web Push contact; defaults to APP_URL when it is https
```
> **Note:** `DEFAULT_LANGUAGE` is not declared in the chart's ConfigMap, so a value under `env:` is dropped and the fallback stays `en`. Patch it onto the Deployment if you need it. See [Environment-Variables](Environment-Variables#default_language--supported-codes) for the codes.
> **Note:** The chart only passes on the keys its ConfigMap declares. `DEFAULT_LANGUAGE`, `MCP_MAX_SESSION_PER_USER` (although `values.yaml` lists it in a comment), `FILE_UPLOAD_LIMIT_MB` and `RESTORE_FROM_BACKUP` are not among them, so a value under `env:` is dropped and the default stays. Patch such a variable onto the Deployment if you need it. See [Environment-Variables](Environment-Variables#default_language--supported-codes) for the language codes.
### Sensitive Variables (`secretEnv`)
@@ -145,11 +158,15 @@ secretEnv:
OIDC_CLIENT_SECRET: "" # set if using OIDC
UNSPLASH_ACCESS_KEY: "" # optional; free key from unsplash.com/developers
PLACES_API_KEY: "" # optional; Google Maps API key, wins over the one in Admin > Settings
AMAP_API_KEY: "" # optional; Amap Web 服务 key for place search in mainland China
AMAP_API_SECRET: "" # optional; the signing secret of that key, only when signing is on
VAPID_PRIVATE_KEY: "" # optional; Web Push private half, only together with env.VAPID_PUBLIC_KEY
```
Alternatively, use `generateEncryptionKey: true` to let the chart generate and manage the encryption key, or point `existingSecret` / `existingSecretKey` at an existing Kubernetes Secret.
Every value the chart writes into its Secret is quoted, so a password such as `12345` or a value like `true` reaches the container as the text you typed.
> **Note:** Web Push needs none of the `VAPID_*` values. TREK generates its key pair on first start and keeps it in the database on the data PVC, so it survives upgrades and restores. Set `env.VAPID_PUBLIC_KEY` and `secretEnv.VAPID_PRIVATE_KEY` together only to bring a pair of your own; changing the pair later means every device has to subscribe again. See [Environment-Variables](Environment-Variables#web-push).
> **Note:** Without `UNSPLASH_ACCESS_KEY` the server queries Unsplash's unauthenticated endpoint, which many datacenter and VPS IP ranges — including a lot of Kubernetes clusters — are blocked or rate-limited on. Trip-cover and place-image search then fail with **"Unsplash search unavailable"**. A free Access Key switches the server to Unsplash's authenticated API (`api.unsplash.com`), which is not subject to that block. The key can also be set in **Admin → Settings → API Keys**; this value takes priority over that one. See [Environment-Variables](Environment-Variables#image-search-unsplash).
@@ -208,7 +225,7 @@ ingress:
- trek.example.com
```
> **Important:** TREK uses WebSockets on `/ws`. Your ingress controller must support WebSocket upgrades. Set `proxy-read-timeout` to at least `86400` and `proxy-body-size` to at least `500m` for backup restores.
> **Important:** TREK uses WebSockets on `/ws`. Your ingress controller must support WebSocket upgrades. Set `proxy-read-timeout` to at least `86400` and `proxy-body-size` to at least `500m` for backup restores and video uploads.
> **Note:** Keep `env.ALLOWED_ORIGINS` in sync with `ingress.hosts` — the chart does not synchronize these automatically.
+4
View File
@@ -88,6 +88,10 @@ HOST=10.0.0.72 # bind only on this LAN interface
> **Note:** `HOST` is only relevant for source-based and Proxmox installs. Do not use it in Docker or any containerised deployment.
### Outbound proxy
If the container reaches the internet only through a proxy, set `HTTP_PROXY`, `HTTPS_PROXY` and `NO_PROXY` in the same file, and `NODE_USE_ENV_PROXY=1` next to them: unlike the Docker image, a Proxmox install does not set that switch for you, and without it Node ignores the proxy for everything except TREK's guarded integration requests. See [Environment-Variables](Environment-Variables#outbound-https-proxy).
See [Environment-Variables](Environment-Variables) for the full variable reference.
## Updating
+3 -1
View File
@@ -45,7 +45,9 @@ The Unraid template exposes the following fields in the container UI:
### Advanced Variables
Additional variables (`PORT`, `NODE_ENV`, `LOG_LEVEL`, `TREK_WIKI_DIR`, `DEFAULT_LANGUAGE`, `FORCE_HTTPS`, `HSTS_INCLUDE_SUBDOMAINS`, `TRUST_PROXY`, `COOKIE_SECURE`, `ALLOW_INTERNAL_NETWORK`, `SESSION_DURATION`, `SESSION_DURATION_REMEMBER`, all OIDC variables, `MCP_RATE_LIMIT`, `MCP_MAX_SESSION_PER_USER`, `DEMO_MODE`, `UNSPLASH_ACCESS_KEY`, `VAPID_PUBLIC_KEY`, `VAPID_PRIVATE_KEY`, `VAPID_SUBJECT`) are available under **Advanced View** in the template editor.
Additional variables (`PORT`, `NODE_ENV`, `LOG_LEVEL`, `TREK_WIKI_DIR`, `DEFAULT_LANGUAGE`, `FORCE_HTTPS`, `HSTS_INCLUDE_SUBDOMAINS`, `TRUST_PROXY`, `COOKIE_SECURE`, `ALLOW_INTERNAL_NETWORK`, `SESSION_DURATION`, `SESSION_DURATION_REMEMBER`, the OIDC variables apart from `OIDC_USERNAME_CLAIM`, `MCP_RATE_LIMIT`, `MCP_MAX_SESSION_PER_USER`, `DEMO_MODE`, `UNSPLASH_ACCESS_KEY`, `VAPID_PUBLIC_KEY`, `VAPID_PRIVATE_KEY`, `VAPID_SUBJECT`) are available under **Advanced View** in the template editor.
Any other variable from [Environment-Variables](Environment-Variables), such as `OIDC_USERNAME_CLAIM`, `FILE_UPLOAD_LIMIT_MB`, `PLACES_API_KEY` or `HTTP_PROXY`, is added as a new variable in the template editor, with its name as the key.
## Setting the Encryption Key
+4
View File
@@ -72,6 +72,10 @@ ALLOW_LINK_LOCAL_IPS=169.254.1.2
Several addresses are separated by commas. The list is read at startup, so restart TREK after changing it.
## Behind an outbound proxy
With `HTTP_PROXY` or `HTTPS_PROXY` set, requests through the strict and the relaxed guard go through that proxy too, unless `NO_PROXY` names the target host. The guard still checks the target first, so a blocked address is refused before anything reaches the proxy. From there on the proxy makes the connection itself, which means the DNS pinning below does not apply to proxied requests: the proxy you chose is the network boundary. Put your LAN services (Immich, a document store, your identity provider) into `NO_PROXY` when the proxy cannot reach them. See [Environment-Variables](Environment-Variables#outbound-https-proxy).
## DNS rebinding protection
Even with `ALLOW_INTERNAL_NETWORK=true`, TREK pins the DNS resolution to prevent rebinding attacks. When the guard checks a URL, it resolves the hostname once and records the addresses it may use. The outbound connection is then made directly to those addresses using a pinned dispatcher (via undici), so the hostname cannot re-resolve to a different address between the check and the actual request.
+7 -5
View File
@@ -14,15 +14,17 @@ An invite link lets a person register a new TREK account without requiring the s
> **Admin:** invite link management is available in [Admin-Users-and-Invites](Admin-Users-and-Invites). Only admins can create invite links.
When creating an invite link you set two parameters:
Invite links live in the **Invite Links** card under **Admin > Users**. Click **Create Link** and set:
**Max uses** — how many times the link can be used to register an account. Choose from preset buttons: **1×, 2×, 3×, 4×, 5×**, or **∞** (unlimited).
**Max. Uses**: how many times the link can be used to register an account. Choose from preset buttons: **1×, 2×, 3×, 4×, 5×**, or **∞** (unlimited).
**Expiry** — how long until the link stops working. Choose from preset buttons: **1d, 3d, 7d, 14d**, or **∞** (no expiry).
**Expires after**: how long until the link stops working. Choose from preset buttons: **1d, 3d, 7d, 14d**, or **∞** (no expiry).
**Add to trip (optional)** — bind the invite to any trip on the instance, not just your own. When someone registers through the link, they are automatically added to that trip as a member. Leave it on **No trip** for a plain registration invite. The selector only appears when at least one trip exists.
**Add to trip (optional)**: bind the invite to any trip on the instance, not just your own. When someone registers through the link, they are automatically added to that trip as a member. Leave it on **No trip** for a plain registration invite. The selector only appears when at least one trip exists.
Once created, a 32-character hexadecimal token is generated and the URL is automatically copied to your clipboard.
**Create & Copy** generates a 32-character hexadecimal token and copies the URL to your clipboard.
Each link in the list shows whether it is **Active**, **Expired** or **Used up**, how often it was used out of its limit, when it expires, the trip it adds to, and who created it. The copy button (**Copy link**) copies its URL again.
## Sharing the link
+29 -2
View File
@@ -42,6 +42,15 @@ Each entry corresponds to a day in your journey. The entry editor provides:
- **Tags** — free-form labels (e.g. "hidden gem", "best meal").
- **Location** — pin the entry to a map location.
- **Time** — optionally record a time of day for the entry.
- **Draft**: a switch at the bottom of the editor. A draft entry is seen only by you and the other contributors, carries a **Draft** mark, and the shared journey leaves it out until you switch it off.
### Photo order
In the entry editor the photos can be dragged into any order. The first one is marked **1st** and is the entry's cover; hover another photo and click **Make 1st** to move it to the front. The order is the same for every member, on the share page and in Studio.
### Linking the trip a date falls in
When the date of an entry falls inside one of your trips that the journey is not linked to yet, the editor names that trip: *This day falls in this trip. Link it, and its places join this journey.* **Link Trip** links it in one click, **Not now** leaves it. When several trips cover the date, the shortest one is suggested.
### Entry fields
@@ -55,6 +64,8 @@ A journey that is still under way opens on today rather than at its first entry,
On desktop, the **Search this journey** box in the toolbar filters the timeline as you type, across the titles, stories, places and tags of the entries. Matching ignores case and accents, so `cafe` finds `Café`.
Next to those two buttons, a **Jump to a day** pill (labelled with the number of days) opens every day of the journey; open a day to see its entries, and picking a day or an entry scrolls straight to it.
Each day header carries a **+** button, **Add an entry on this day**, which opens the editor with that date already set, so an entry for an earlier day no longer starts on today.
### External photos
@@ -67,6 +78,16 @@ The same photo picker opens from the journey gallery, on desktop and on a phone.
Imported photos are added oldest first, so an entry lists a bulk import in the order the photos were taken, and you can still drag them into another order afterwards. The gallery sorts by capture time, which TREK asks Immich or Synology Photos for right after the import; once those times arrive the gallery re-sorts by itself on every device that has the journey open.
### Viewing photos
Clicking a photo opens it full size. The viewer zooms with the mouse wheel, a double click, the **Zoom in** and **Zoom out** buttons or a pinch, and a zoomed photo can be dragged around. **Back to full photo** resets the zoom.
## Journey status
By default a journey's status follows the dates of its linked trips; without a linked trip it stays a draft. To set it yourself, open **Journey Settings** and pick **Status**: **Automatic**, **Draft**, **Live** or **Completed**. A status set by hand stays until you switch back to **Automatic**.
**Archive Journey** in the same dialog hides the Live badge; **Restore Journey** reopens it.
## Mobile timeline
On a phone, entries sit in a horizontal carousel over the map, one photo card per entry. The entry's first photo is the card (a pin placeholder when it has none), with the title and place on it, the country flag and the date in the corners, and the mood and weather icons next to the date. A suggestion from a linked trip shows a plus mark and its title in italics. The day an entry belongs to is carried by the colour of the card's edge, the same colour its map marker uses; there is no day number on the card. Tap the centred card to open the entry in a sheet.
@@ -83,6 +104,10 @@ The journey detail page includes a map on the right (desktop) or an integrated m
The thin dashed line connecting entries in date order is something else and stays as it is: that one is drawn by TREK, while a track is the route you actually recorded.
**Geotagged photos are drawn too.** A photo of the journey that knows where it was taken appears on the map as a thumbnail, and photos taken close together collapse into one thumbnail with a count. Click one to open those photos in the viewer.
**Place entries from their photos**, a switch under **Photos** in **Journey Settings**, goes one step further: an entry without a place takes the spot where its first photo with GPS was taken. Places you set yourself are never moved. It is off by default.
![Journey detail page for "Autumn in Japan" with its cover header and day/place/entry/photo counts, the day-by-day timeline with Add Entry actions on the left, and the entry map on the right](assets/JourneyDetail.png)
## TREK Studio
@@ -94,8 +119,10 @@ A journey can also be laid out as a printable photo book. Open a journey and cli
- **Page format** — Square 21 × 21 cm (the default), Square 30 × 30 cm, A4 landscape, A4 portrait, A5 landscape, or a custom width × height in millimetres. Everything is drawn as a spread (two pages side by side) with 3 mm bleed and a 5 mm safe margin.
- **The shape of the book** follows a bound one: a cover, a single first page on the right (page 1, where a title page or a dedication goes), the spreads, a single last page on the left, and a back cover. The first and last pages take the cover layouts and, like the covers, stay where they are; new spreads always go between them. Page numbers, when switched on, count from the first page, and the number on screen is the number that prints. Books made before this had no single pages and keep their numbering as it was.
- **Auto layout** has two entries. **This spread** builds the spread on screen again from the journal entry it came from, and is only offered on a spread that came from one. **The whole book** replaces every page, keeping your title and page setup. Both are ordinary undo steps, so you can press one, look at it, and undo.
- **Pages, Content, Elements, Travel and Layouts** are the sections of the left rail. Content holds the journey's own photos and entries; Layouts has thirteen spread layouts (Hero and story, Four up, Strip and text, Mosaic and so on) plus a separate set of five for the cover and back; Elements has text styles, shapes, lines, grids, empty frames with their frame styles, and a searchable icon library; Travel builds figures out of the journey itself — route maps, country outlines and lists, flags, date, day and distance marks, and a trip summary.
- **Pages, Content, Elements, Travel and Layouts** are the sections of the left rail. Content holds the journey's own photos and entries, with **Upload photos** and, when Immich or Synology Photos is connected, **From Immich** or **From Synology Photos** to add photos from your library the way the journey gallery does; Layouts has thirteen spread layouts (Hero and story, Four up, Strip and text, Mosaic and so on) plus a separate set of five for the cover and back; Elements has text styles, shapes, lines, grids, empty frames with their frame styles, and a searchable icon library; Travel builds figures out of the journey itself: route maps, country outlines and lists, flags, date, day and distance marks, and a trip summary.
- **Properties** on the right edits whatever is selected: position and size, crop and focal point, fill or fit, a look filter, corner radius, frame style, stacking order, lock. An element that auto layout tied to a journal entry follows that entry until you edit it here, which breaks the link.
- **Copy and paste**: a selected element copies with Ctrl+C and pastes on any page with Ctrl+V or the paste button.
- **My layouts**: **Save this page as a layout** keeps the arrangement of a page without its photos, for every editor of the book, and applying it lays another page out the same way while keeping that page's photos and words. A book keeps up to 24 layouts.
- **Export** opens a print view that your browser turns into a PDF. Pick **Single pages** (one leaf per sheet, what a printer wants) or **Spreads** (two pages at a time, the way the book opens), with optional crop marks that add the bleed on every edge and mark where to cut.
- **Spreads travel between books.** Download the spread you are on as a design file and import it into another book. The file carries the design only, not the photographs.
- **Several people can design at once.** Everyone in the same book sees the others' pointers with their names on them, and a save is pushed to the rest live. A save that lands on a version somebody else has already changed comes back as a conflict, with the other version alongside it, rather than quietly overwriting their work.
@@ -114,7 +141,7 @@ Installed plugins can add extra rows to a journal entry card via the `journalEnt
## Public sharing
You can share a journey with a read-only public link. When creating the link you can independently toggle which sections are visible to visitors: **Timeline** (entries and stories), **Gallery** (photos), and **Map**. Visitors can only see the sections you have enabled, and no TREK account is required. See [Public-Share-Links](Public-Share-Links) for details on the separate journey share token mechanism.
You can share a journey with a read-only public link. When creating the link you can independently toggle which sections are visible to visitors: **Timeline** (entries and stories), **Gallery** (photos), and **Map**. Visitors can only see the sections you have enabled, and no TREK account is required. Entries marked as **Draft** are left out of the shared journey until you publish them. See [Public-Share-Links](Public-Share-Links) for details on the separate journey share token mechanism.
**Photos appear on the public map too**, as long as **Gallery** and **Map** are both on. A gallery photo that knows where it was taken becomes a thumbnail pin, clustered into one pin where several were taken close together, and sitting below the entry pins so the itinerary stays the point of the map. The location comes from the file's own EXIF for uploads and from Immich or Synology for provider photos, and a photo that carries none simply stays off the map (see the HEIC note above — that conversion drops GPS, so iPhone uploads usually arrive without a location).
+5 -1
View File
@@ -1,6 +1,6 @@
# Languages
TREK ships with translations for 27 languages. You can change your language at any time without logging out.
TREK ships with translations for 27 languages, the [Help Center](Help-Center) guides included. You can change your language at any time without logging out.
## Supported languages
@@ -34,6 +34,10 @@ TREK ships with translations for 27 languages. You can change your language at a
| `vi` | Tiếng Việt |
| `ca` | Català |
## Place names in another language
Place search, suggestions, place details and addresses follow the app language by default. **Settings → General → Language & region → Place names** lets them answer in another language while the interface stays in yours, for example English place names in a German app. Where a place has no name in the chosen language, its local name is shown. See [Display-Settings](Display-Settings#place-names).
## RTL support
Arabic (`ar`) uses a right-to-left layout. All other languages use left-to-right.
+3 -1
View File
@@ -51,7 +51,9 @@ Passwords must meet all of the following rules:
- Must not be a commonly used password
- Must not consist of a single repeated character
> **Admin:** You can disable open registration so only invite links work. See [Admin-Users-and-Invites](Admin-Users-and-Invites).
As soon as you start typing, the five character rules appear under the password field as a checklist (**At least 8 characters**, **An uppercase letter**, **A lowercase letter**, **A number**, **A special character**), and each one is ticked off once the password meets it. The same checklist appears on every form that sets a password: registration, the forced password change, the reset page, **Change Password** in Settings and the admin's user dialogs. The common-password and repeated-character checks run when you submit.
> **Admin:** You can disable open registration so only invite links work: switch off **Password Registration** in **Admin → Settings**, card **Authentication Methods**. See [Admin-Users-and-Invites](Admin-Users-and-Invites).
### Invite link flow
+2 -1
View File
@@ -185,7 +185,7 @@ Requires `journey:read` or `journey:write` scope.
| `get_journey` | Get a full snapshot of a journey — metadata, entries, contributors, and linked trips. |
| `get_journey_stats` | What a journey adds up to: distance travelled in metres, calendar days spanned, countries in visit order, the furthest point reached, and entry, photo and place counts. Entries switched off with `stats_excluded` count towards none of those and are listed under `excluded`. Pass `include_route` for the route itself, up to 400 stops with coordinates. |
| `create_journey` | Create a new journey with title, optional subtitle, and an initial list of trip IDs. |
| `update_journey` | Update a journey's title, subtitle, cover or status, and whether its entries offer a pros/cons list, a mood and a weather note (`show_verdict`, `show_mood`, `show_weather`). Owner only. |
| `update_journey` | Update a journey's title, subtitle, cover or status, and whether its entries offer a pros/cons list, a mood and a weather note (`show_verdict`, `show_mood`, `show_weather`). `status_override` sets the shown status by hand (`draft`, `live` or `completed`), `null` goes back to following the trip dates. `photo_location` lets an entry without a place take the position of its first geotagged photo. Owner only. |
| `restore_journey_suggestions` | Bring back every trip-derived suggestion that was dismissed from a journey. Answers with how many came back. |
| `delete_journey` | Delete a journey. |
| `add_journey_trip` | Link an existing trip to a journey. |
@@ -195,6 +195,7 @@ Requires `journey:read` or `journey:write` scope.
| `update_journey_entry` | Edit a journey entry's title, story, date, time of day, place, coordinates, weather, tags, mood, pros/cons list or visibility. `stats_excluded: true` keeps the entry but takes it off the route and out of `get_journey_stats`; `dismissed: true` waves a trip-derived suggestion away without deleting it, so the trip sync does not offer it again. `is_draft` turns the entry into a draft or publishes it. |
| `delete_journey_entry` | Remove an entry from a journey. |
| `reorder_journey_entries` | Reorder entries by providing the new ordered list of entry IDs. |
| `reorder_journey_entry_photos` | Put the photos of one entry in a new order by passing every photo id of the entry once. The first photo is the entry's cover. |
| `list_journey_contributors` | List the contributors of a journey (owner and editors/viewers). |
| `add_journey_contributor` | Invite a user to a journey with `editor` or `viewer` role. |
| `update_journey_contributor_role` | Change a contributor's role between `editor` and `viewer`. |
+3 -1
View File
@@ -15,6 +15,8 @@ Once connected, an AI assistant can work with your TREK data in a single convers
- Mark countries and regions as visited in Atlas
- Log vacation days in Vacay
- Write journey entries across multiple trips
- Upload documents to a trip, read them and link them to bookings, places or expenses
- Look up how a TREK feature works in the bundled help
Changes made through MCP are broadcast to all connected clients in real-time — exactly like changes made in the web UI.
@@ -58,7 +60,7 @@ https://<your-trek-instance>/mcp
If the MCP addon is not enabled, this endpoint returns `403`. If authentication fails, it returns `401`.
> **Admin:** Enable the MCP addon in [Admin-Addons](Admin-Addons). Set `APP_URL` for OAuth discovery. Revoke tokens and manage OAuth clients from [Admin-MCP-Tokens](Admin-MCP-Tokens). Adjust rate and session limits with `MCP_RATE_LIMIT` and `MCP_MAX_SESSION_PER_USER` — see [Environment-Variables](Environment-Variables).
> **Admin:** Enable the MCP addon in [Admin-Addons](Admin-Addons). Set `APP_URL` for OAuth discovery. Revoke OAuth sessions and delete API tokens of any user under **Admin → MCP Access** ([Admin-MCP-Tokens](Admin-MCP-Tokens)). Adjust rate and session limits with `MCP_RATE_LIMIT` and `MCP_MAX_SESSION_PER_USER`, see [Environment-Variables](Environment-Variables).
## Next steps
+4 -4
View File
@@ -1,6 +1,6 @@
# MCP Scopes
OAuth scopes control exactly which data your AI client can read or write in TREK. You select scopes during the OAuth consent screen or when pre-creating an OAuth client. You can revoke access at any time by deleting the OAuth client or token from your **Settings → Integrations → MCP**.
OAuth scopes control exactly which data your AI client can read or write in TREK. You select scopes during the OAuth consent screen or when pre-creating an OAuth client. You can revoke access at any time by deleting the OAuth client or token, or revoking the session, under **Settings → Integrations → MCP Configuration**.
![OAuth consent screen](assets/OAuthConsentDCR.png)
@@ -40,7 +40,7 @@ TREK defines 35 scopes across 17 groups.
| | `journey:write` | Create, update, and delete journeys and their entries |
| | `journey:share` | Create, update, and revoke public share links for journeys |
| **Files** | `files:read` | List the documents on a trip: names, sizes, who uploaded them, what they link to |
| | `files:write` | Rename and describe files, link them to bookings and places, star and trash them |
| | `files:write` | Rename and describe files, link them to bookings and places, star and trash them. Also needed to upload a document with `upload_trip_file`, which additionally checks the trip's file upload permission |
| | `files:content` | Read what is inside an uploaded document, such as a booking PDF or a ticket |
| **Settings** | `settings:read` | Read units, time format, language, default currency, and start page |
| | `settings:write` | Change units, time format, language, default currency, and start page |
@@ -65,12 +65,12 @@ Grant only what you need. Some examples:
| Use case | Minimum scopes |
|---|---|
| Read-only AI assistant | All `:read` scopes relevant to your data |
| Full trip planner | All scopes except `:delete` (use the Claude.ai or Claude Desktop preset) |
| Full trip planner | All scopes except `trips:delete` (use the Claude.ai or Claude Desktop preset) |
| Budget review only | `trips:read` + `budget:read` |
| Packing list assistant | `trips:read` + `packing:read` + `packing:write` |
| Journey writer | `trips:read` + `journey:read` + `journey:write` |
The preset buttons in your **Settings → Integrations → MCP → OAuth 2.1 Clients** fill in a reasonable scope set for common clients. VS Code defaults to read-only scopes; Claude.ai and Claude Desktop default to all scopes except `:delete`.
The preset buttons in your **Settings → Integrations → MCP Configuration → OAuth 2.1 Clients** fill in a reasonable scope set for common clients. VS Code defaults to read-only scopes; Claude.ai, Claude Desktop, Cursor, Windsurf and Zed default to all scopes except `trips:delete`. No preset includes `plugins:use`.
## Related
+9 -7
View File
@@ -14,7 +14,7 @@ OAuth 2.1 is the preferred connection method. You grant specific scopes during t
Claude.ai (web) supports native MCP connections — no JSON config file required:
1. In TREK, go to your **Settings → Integrations → MCP → OAuth 2.1 Clients** and click **New Client**.
1. In TREK, go to your **Settings → Integrations → MCP Configuration → OAuth 2.1 Clients** and click **New Client**.
2. Select the **Claude.ai** preset. This fills in the redirect URI (`https://claude.ai/api/mcp/auth_callback`) and a default scope set.
3. Give the client a name, adjust scopes if needed, and save. Copy the client ID and client secret (`trekcs_` prefix) — the secret is shown only once.
4. In Claude.ai, open the MCP settings and add a new server using your TREK URL (`https://<your-trek-instance>/mcp`). Claude.ai will open your browser to complete the OAuth consent flow.
@@ -23,7 +23,7 @@ Claude.ai (web) supports native MCP connections — no JSON config file required
Claude Desktop supports native MCP connections — no JSON config file required:
1. In TREK, go to your **Settings → Integrations → MCP → OAuth 2.1 Clients** and click **New Client**.
1. In TREK, go to your **Settings → Integrations → MCP Configuration → OAuth 2.1 Clients** and click **New Client**.
2. Select the **Claude Desktop** preset. This fills in the redirect URI and a default scope set.
3. Give the client a name, adjust scopes if needed, and save. Copy the client ID and client secret — the secret is shown only once.
4. In Claude Desktop, open Settings → MCP and add a new server using your TREK URL (`https://<your-trek-instance>/mcp`). Claude Desktop will open your browser to complete the OAuth consent flow.
@@ -86,14 +86,16 @@ TREK accepts `https://` URIs, plain HTTP only on `localhost` or `127.0.0.1`, and
### Pre-created OAuth clients
Your **Settings → Integrations → MCP → OAuth 2.1 Clients** page (your own settings, not the admin area) lets you create named OAuth clients before connecting. This gives you:
Your **Settings → Integrations → MCP Configuration → OAuth 2.1 Clients** page (your own settings, not the admin area) lets you create named OAuth clients before connecting. This gives you:
- A fixed, named scope list defined up front
- A client secret (`trekcs_` prefix, shown once) for confidential client mode
- Preset buttons for Claude.ai, Claude Desktop, Cursor, VS Code, Windsurf, and Zed that fill in the correct redirect URIs and a sensible default scope set
- **Quick presets** for Claude.ai, Claude Desktop, Cursor, VS Code, Windsurf, and Zed that fill in the correct redirect URIs and a sensible default scope set
Each user can have up to **10 OAuth clients**.
Each client in the list has a **Rotate Secret** button, which issues a new client secret (shown once) and ends every existing session of that client at once, and a **Delete Client** button. Both ask in a confirmation dialog first. Below the list, **Active OAuth Sessions** shows each session a client holds for your account, with its scopes and expiry date; **Revoke** ends that session immediately.
## Option B: Machine client — no browser login (for AI agents and scripts)
Use this when your AI agent or automation script needs to authenticate silently without any browser interaction. Instead of going through an OAuth consent flow, the client exchanges a `client_id` and `client_secret` directly for an access token ([RFC 6749 §4.4 — Client Credentials grant](https://datatracker.ietf.org/doc/html/rfc6749#section-4.4)).
@@ -104,9 +106,9 @@ Use this when your AI agent or automation script needs to authenticate silently
### Create a machine client
1. Go to your **Settings → Integrations → MCP → OAuth 2.1 Clients** and click **New Client**.
1. Go to your **Settings → Integrations → MCP Configuration → OAuth 2.1 Clients** and click **New Client**.
2. Tick **Machine client (no browser login)**. The redirect URI field disappears — machine clients don't need one.
3. Give it a name, select scopes, and click **Register Client**.
3. Give it an **Application Name**, select the **Allowed Scopes**, and click **Register Client**.
4. Copy the `client_id` and `client_secret` shown — the secret is displayed only once.
### How token management works
@@ -125,7 +127,7 @@ Machine clients are designed for **AI agent frameworks and custom MCP client imp
Static tokens grant full access to all tools and resources with no scope restrictions. A static-token session is warned about the deprecation once, not on every call: the notice rides along with the result of the first `list_trips` or `get_trip_summary` in that session — the trip-discovery tools an AI client normally reaches for first — for the client to surface to you. The tool's own payload still comes with it, and every later call in that session returns a plain result. The notice is also part of the session instructions the server sends when the connection initializes.
1. Go to your **Settings → Integrations → MCP**, open the **API Tokens** sub-tab, and click **Create New Token**.
1. Go to your **Settings → Integrations → MCP Configuration**, switch to **API Tokens**, and click **Create New Token**.
2. Give the token a name and copy it immediately — it is shown only once. The token starts with `trek_`.
3. Pass the token as a header in your client config:
+5 -4
View File
@@ -57,8 +57,8 @@ Requires `places:read` or `places:write` scope.
| Tool | Description |
|---|---|
| `list_places` | List places in a trip, optionally filtered by assignment status, category, tag, or search query. |
| `create_place` | Add a place with name, coordinates, address, category, notes, website, phone, and optional `google_place_id` / `osm_id`. An optional `stop_type` (`fuel`, `charging`, `rest_area`, `campsite`, `restaurant`, `sights` or `hotel`) marks it as a service stop on a drive rather than a destination, so it is left out of the day's stop count; see [Road-Trip](Road-Trip). Leave it unset for an ordinary place. |
| `update_place` | Update any field of an existing place including transport mode, timing, price and `stop_type`. Pass `stop_type: null` to turn a service stop back into an ordinary place. |
| `create_place` | Add a place with name, coordinates, address, category, notes, website, phone, email, and optional `google_place_id` / `osm_id` / `amap_poi_id`. `opening_hours` takes the place's own hours, seven days starting on Monday (`closed`, `open`, `close` as `HH:MM`), shown instead of looked-up hours; `null` clears them. An optional `stop_type` (`fuel`, `charging`, `rest_area`, `campsite`, `restaurant`, `sights` or `hotel`) marks it as a service stop on a drive rather than a destination, so it is left out of the day's stop count; see [Road-Trip](Road-Trip). Leave it unset for an ordinary place. |
| `update_place` | Update any field of an existing place including phone, email, opening hours, transport mode, timing, price and `stop_type`. Pass `stop_type: null` to turn a service stop back into an ordinary place. |
| `rate_place` | Set or clear your own 1–5 star rating on a place. Every trip member rates independently and the place shows the average. Pass `null` to clear the vote. |
| `bulk_update_places` | Update many places at once, applying the same field values (e.g. category, price, transport mode, `stop_type`) to every listed place in a single call. `stop_type: null` turns the listed service stops back into ordinary places. |
| `delete_place` | Remove a place from a trip. Also removes all day assignments, the expenses linked to the place and any night booked at it, together with that night's reservation and the reservation's expense. Cannot be undone, so an assistant should warn before deleting a hotel that holds a booking. |
@@ -121,7 +121,7 @@ Requires `reservations:write` scope.
| Tool | Description |
|---|---|
| `create_transport` | Create a transport booking in any of the nine types the transport form offers (`flight`, `train`, `bus`, `car`, `taxi`, `bicycle`, `cruise`, `ferry`, `transport_other`), with optional multi-stop endpoints, departure/arrival times, and confirmation details. Scheduled public transit goes through `create_transit_journey` instead. |
| `create_transport` | Create a transport booking in any of the ten types the transport form offers (`flight`, `train`, `bus`, `car`, `taxi`, `bicycle`, `cruise`, `ferry`, `cable_car`, `transport_other`), with optional multi-stop endpoints, departure/arrival times, and confirmation details. Scheduled public transit goes through `create_transit_journey` instead. |
| `update_transport` | Update an existing transport booking. Pass `endpoints[]` to replace all stops. |
| `delete_transport` | Delete a transport booking from a trip. |
@@ -226,7 +226,7 @@ Requires `settings:read` or `settings:write`.
| Tool | Description |
|---|---|
| `get_display_settings` | Read the user's units, time format, first day of the week, language, the language of place names in search, default currency and start page. Read this before rendering a temperature, a distance or a clock time. |
| `get_display_settings` | Read the user's units, time format, first day of the week, language, the language of place names in search, default currency, start page, the trip tab a trip opens on, the colour mode (light, dark or auto) and a few map and planner switches such as blurred booking codes. Read this before rendering a temperature, a distance or a clock time. |
| `update_display_settings` | Change one or more of those preferences. Only display preferences: API keys, map tokens and LLM settings are refused, whatever is passed. |
### Calendar feeds
@@ -281,6 +281,7 @@ Photo bytes are never returned: those are image URLs the app renders.
| Tool | Description |
|---|---|
| `list_help_topics` | List the bundled help pages. Answers "how do I do X in TREK?" without guessing. |
| `search_help` | Full-text search across the bundled help pages, the same search the in-app help uses. Returns the best-matching pages with the section heading and a snippet; follow up with `get_help_page`. |
| `get_help_page` | Read one help page. |
| `list_addons` | Which addons and collaboration features this instance has enabled. Worth calling when a tool you expected is not in the list: an addon that is off removes its tools exactly the way a missing scope does. |
| `get_trip_warnings` | Warnings plugins have raised about a trip. A plugin raising one is telling the user something is wrong, so it is worth reading before reviewing an itinerary. |
+20 -3
View File
@@ -13,6 +13,12 @@ The scopes required for Mapbox GL are:
- DATASETS:READ
- VISION:READ
On MapLibre GL and Mapbox GL the map can be rotated and tilted. A round compass button shows where north is; click it to turn the map back to north and flat. On the phone it sits above the satellite switcher.
## Map lock
On the desktop, a lock button sits on top of the satellite switcher in the bottom-left corner. Click it (*Lock the map view*) and the map stays where you put it: picking a day or a place no longer zooms or pans it, so you can keep one part of the map in view while you click through the plan. Click it again (*Let the map follow the selection*) to unlock. Opening a trip still fits the map once, and your browser remembers the lock for every trip.
## Satellite view
A round button in the bottom-left corner of the map flips the base layer between the normal map tiles and **satellite** imagery (ESRI World Imagery, no API key needed, usable up to zoom 19). The icon always shows the layer it switches to. The button is on all three renderers: Leaflet swaps its tile layer for the imagery, while MapLibre GL and Mapbox GL put the same imagery on as a raster layer of their own beneath everything TREK draws, so the route, the pins and the tracks stay on top of it. Your choice is stored on your account (`map_base_layer`), the same setting whichever renderer you use, so it carries over to every trip and survives a reload.
@@ -26,6 +32,8 @@ Each place is a round marker:
- **Selected place:** the active place has a larger marker.
- **Order badge:** while a day is open, a small badge at the bottom right shows the stop's position in that day's plan, and a place that comes up twice in the day carries both numbers. Without an open day the badge shows the place's rating instead, where it has one.
- **Rating:** a place that members rated and that carries no order badge shows its average as a small disc in its corner.
- **Unplanned places, compact:** with **Compact markers for unplanned places** switched on under **Settings > General > Travel & map**, places that no day holds are drawn as small markers without their photo, so the planned stops stand out. It is off by default, and the selected place always shows in full.
- **Pending stay:** the place of an [accommodation](Accommodations) whose booking is still **Pending** is drawn with a dashed ring and a lighter face until the booking is confirmed.
Click a marker to open the [place inspector](Places-and-Search#the-place-inspector).
@@ -45,7 +53,11 @@ Markers that [plugins](Places-and-Search#categories-from-plugins) put on the map
A day's route is drawn as a solid blue line, a bright core over a darker casing in the look Apple Maps uses, through that day's stops in the order you arranged them. It is not on automatically: switch it on with **Route** in the route bar of the selected day (see [Day Plans and Notes](Day-Plans-and-Notes#the-route-bar)), or in the day sheet on a phone. The choice is remembered per trip in your browser, and the phone's map turns it on by default the first time you open a trip you have not decided on.
A straight line is drawn immediately, then upgraded to real road geometry from a public OSRM router (or from a plugin route profile), each leg routed in the travel mode that leg carries. If routing fails, that leg stays a straight line between the two stops.
A straight line is drawn immediately, then upgraded to real road geometry from a public OSRM router (or from a plugin route profile), each leg routed in the travel mode that leg carries: driving, walking or cycling. If routing fails, that leg stays a straight line between the two stops.
A leg you walk is drawn as a dotted line in the same colour, without the casing, so the drive stands apart from the stretches on foot.
**Leave out of route**, in the right-click or **…** menu of a stop in the day plan, keeps the place on the day but takes it out of the route: the route runs from the stop before it to the stop after it, as if it were not there. **Add back to route** in the same menu undoes it. On the phone the same switch is in the stop's place sheet.
### The whole trip at once
@@ -81,11 +93,11 @@ Places carry their description and address, and their category travels along as
## Travel times between stops
Travel times are not drawn on the map; they sit in the day plan. Switch a day's **Route** on and a slim connector row appears between each pair of consecutive stops with that leg's travel time and distance, and an icon for the mode it was routed in: a car for driving, a foot for walking, a bolt for a plugin route profile. On a phone the same rows sit in the day's plan timeline, where they are always shown and need no toggle. If the day has an accommodation and **Optimize route from accommodation** is on, two extra connectors frame the day, naming the hotel with the drive out in the morning and back in the evening.
Travel times are not drawn on the map; they sit in the day plan. Switch a day's **Route** on and a slim connector row appears between each pair of consecutive stops with that leg's travel time and distance, and an icon for the mode it was routed in: a car for driving, a foot for walking, a bicycle for cycling, a bolt for a plugin route profile. On a phone the same rows sit in the day's plan timeline, where they are always shown and need no toggle. If the day has an accommodation and **Optimize route from accommodation** is on, two extra connectors frame the day, naming the hotel with the drive out in the morning and back in the evening.
Each leg carries its own mode, so a day routed by car can still have one leg you walk. If you may edit the day, clicking a connector (*Change travel mode*) opens the mode menu for that leg alone, with **Public transit** on a trip with dates. See [Route Optimization](Route-Optimization#route-calculation).
Car and foot times come from a public OSRM router, so they follow real roads and footpaths instead of straight-line estimates. A plugin route profile is answered by the plugin's own route provider instead, which is what lets it fold in things like charging stops; those legs can add a short note next to the distance. When routing is unavailable the leg falls back to a straight line and shows no time.
Car, foot and bicycle times come from a public OSRM router, so they follow real roads, footpaths and cycle routes instead of straight-line estimates. A plugin route profile is answered by the plugin's own route provider instead, which is what lets it fold in things like charging stops; those legs can add a short note next to the distance. When routing is unavailable the leg falls back to a straight line and shows no time.
## Reservation and transport overlay
@@ -94,6 +106,7 @@ Flights, trains, cars, cruises and other bookings with a start and an end point
- **Flights, cruises and ferries:** geodesic great-circle arcs.
- **Cars, buses, taxis and bicycles:** real routed lines that follow actual roads, fetched on demand from a public OSRM router (driving for car, bus and taxi, cycling for bicycle). A straight line is shown while the route loads, and kept if routing fails or the trip is very long (about 2,000 km or more).
- **Trains:** a straight line between the endpoints; a multi-leg train draws its whole station chain (from, stop, to).
- **Cable cars and gondolas**, and bookings of the type **Other**: a straight line between the endpoints.
- **Automated public transit:** a journey added from the transit search draws its real rail and bus alignment instead of a straight line: each ride leg in its line's own colour over a white casing, walking transfers as a dotted grey line. A journey whose provider sent no shape falls back to a straight line. Unlike every other type it has no route button of its own in the days column. It is drawn when the day's own **Route** is on and the journey runs on that day, and independently of that by the bulk button, the account-wide default, or **On map** in its detail. Because those are two separate gates, **Hide all booking routes** does not clear a transit journey while that day's **Route** is still on.
- **Antimeridian crossings:** routes that cross the date line draw as one continuous arc instead of splitting at the edges of the map.
- **Endpoint markers:** pill-shaped labels with the transport icon and the endpoint code (for example the IATA airport code) or the location name. Click one to open the booking's detail.
@@ -108,6 +121,10 @@ On a phone the plan map shows one day at a time, so a booking you have switched
> **Tip:** Whether endpoint text labels appear on the endpoint markers is your own choice: the **Booking route labels** setting in Settings → General → Travel & map (`map_booking_labels`). It is off by default; with it off, the endpoint markers show only the transport icon.
## Category buttons
With **Explore places on the map** switched on (Settings > General > Travel & map), the trip map carries a row of category buttons such as **Restaurants**, **Sights** or **Nature & parks**, and [plugins](Plugins) can add buttons of their own, such as trailheads, EV chargers or drinking water. Click one to show that kind of place around the part of the map you are looking at, and click a marker to add it as a place. See [Exploring the map by category](Places-and-Search#exploring-the-map-by-category).
## Plugin map markers
Installed plugins can add their own markers to the trip map, for example to show bookings on the map (#587). A plugin implements the `mapMarkerProvider` hook and returns marker specs (`id`, `lat`, `lng`, and optional `label`, `popupText`, `url`, `icon`, `tone`); TREK range-checks the coordinates, length-caps the text, allows only http, https and mailto links, and draws them itself. Markers are additive and fail-safe: a plugin never runs code on the map canvas, and one that errors or is slow simply contributes nothing.
+5
View File
@@ -10,6 +10,8 @@ The Map tab controls which map engine and tile source TREK uses in the Trip Plan
Open the user menu in the top navigation bar, select **Settings**, then the **Map** tab. Unlike the General tab, changes here are not saved as you make them — click **Save Map** when you are done.
Some map display options are not on this tab but on the **General** tab under **Travel & map**, and save as you change them: **Booking route labels**, **Always show booking routes**, **Compact markers for unplanned places** and **Explore places on the map**. See [Display-Settings](Display-Settings).
## Map provider
Choose the rendering engine:
@@ -37,6 +39,8 @@ When Leaflet is selected, pick a preset or enter a custom tile URL.
| CartoDB Light (needs a key) | `https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png` |
| CartoDB Dark (needs a key) | `https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png` |
| Stadia Smooth | `https://tiles.stadiamaps.com/tiles/alidade_smooth/{z}/{x}/{y}{r}.png` |
| 高德地图 (Amap) | `https://webrd01.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=7&x={x}&y={y}&z={z}` |
| 高德卫星 (Amap Satellite) | `https://webst01.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}` |
**OpenFreeMap Positron is the default** and is what every map falls back to when the field is empty. It needs no key,
no account and has no request limit, and it is a MapLibre *style* rather than an XYZ template — TREK renders it with
@@ -162,5 +166,6 @@ The small map preview on this settings page is the exception: it stays on a fixe
## See also
- [Map-Features](Map-Features)
- [Display-Settings](Display-Settings)
- [Admin-Panel-Overview](Admin-Panel-Overview)
- [User-Settings](User-Settings)
+15
View File
@@ -10,6 +10,20 @@ Use the toggle button in the top toolbar to switch between **grid** (card thumbn
In both modes the dashboard shows a large [Spotlight card](#spotlight-card) for your most relevant trip at the top of the page — the toggle only changes how the trips below it are laid out. The spotlighted trip is taken out of that list when it earns the spot on its own: an ongoing trip, or the next upcoming one. If you have neither, the spotlight borrows your first trip for the header and that trip still shows up in the list below.
## Searching Trips
On desktop the trips section header has a search box, **Search trips or places**. It searches **every** trip you have, archived and completed ones included, whichever filter is selected:
- by the trip's **title** and **description**,
- by its **dates**, written as numbers (`2024-05`) or as words (`May 2024`, in your language),
- by a **place** on the trip, once you have typed at least two letters. A trip found this way lists the matching places under its dates.
Several words must all match, and accents do not matter, so `cafe` finds "Café". While a search is active, the **Planned / Archived / Completed** filter is dimmed and the grid shows only the matches; with none, it says *No trip matches "…"*. Clear the box with **×** or **Escape** to go back. Offline, the place part of the search is skipped and only titles, descriptions and dates are matched.
## Calendar Subscription
The calendar button next to the filter, **Subscribe to all trips**, opens one calendar feed for all your active trips. See [Calendar-Feeds](Calendar-Feeds).
## Sort Order
Trips are always sorted in this order:
@@ -64,3 +78,4 @@ When you have no trips, the dashboard shows the TREK mascot with the caption **N
- [Creating-a-Trip](Creating-a-Trip)
- [Trip-Planner-Overview](Trip-Planner-Overview)
- [Dashboard-Widgets](Dashboard-Widgets)
- [Calendar-Feeds](Calendar-Feeds)
+10
View File
@@ -78,6 +78,16 @@ The following event is fired automatically and can only be delivered in-app —
The preferences panel shows a grid of events × channels. Toggle each intersection independently. Changes are saved automatically.
### Defaults set by the admin
An admin decides how every user's matrix starts, under **Admin → Notifications → Defaults for users**. Each event and channel is set to one of three values:
- **On**: switched on until you turn it off. This is the default for every cell.
- **Off**: switched off until you turn it on yourself.
- **Blocked**: switched off for everyone. In your matrix the switch is replaced by a lock with the tooltip *Turned off for everyone by the admin*, and nothing is sent there.
A default applies to every cell you have not changed yourself, so when the admin changes it later, it reaches you too. A cell you switched yourself keeps your choice, unless the admin blocks it.
## Webhook configuration
Enter a URL that TREK will POST to when a notification fires. Once saved, the URL is displayed as `••••••••`. Use the **Test** button to send a test payload to the saved URL.
+4 -2
View File
@@ -92,7 +92,7 @@ A provider that sends the claim as an empty list instead of dropping it is not a
When an SSO login matches an existing TREK account by OIDC subject (`sub`), that account is used directly. When it matches only by **email**, the OIDC identity is linked to that account only if the provider asserts `email_verified` for it; if the claim is missing or false the login is rejected with an `email_not_verified` error, so an unverified address can never take over a local account. Make sure your IdP includes `email_verified` in the userinfo response — it is part of the `email` scope. If no matching account exists, TREK attempts to create one. The outcome depends on the following:
- **First user ever**: always created as admin, no invite required.
- **Open SSO registration enabled** (admin panel toggle `oidc_registration`): account is created as a regular user.
- **Open SSO registration enabled** (**SSO Auto-Provisioning** in **Admin → Settings**, card **Authentication Methods**; setting `oidc_registration`): account is created as a regular user.
- **Invite token present** in the login URL: account is created regardless of the registration toggle. Pass the token as `?invite=<token>` when initiating SSO login (e.g. `GET /api/auth/oidc/login?invite=<token>`).
- **SSO registration disabled and no invite**: login is rejected with a `registration_disabled` error.
@@ -112,7 +112,9 @@ Environment variables take priority over database settings when both are present
The following variables are **env var only** and have no admin panel equivalent: `OIDC_ONLY`, `OIDC_SCOPE`, `OIDC_ADMIN_CLAIM`, `OIDC_ADMIN_VALUE`, `OIDC_USERNAME_CLAIM`.
The `OIDC_ONLY` env var always overrides the panel's login-method toggles. To disable password login at runtime without `OIDC_ONLY`, use the **password_login** and **password_registration** toggles in Admin → Settings instead.
The `OIDC_ONLY` env var always overrides the panel's login-method toggles: while it is set, the **Authentication Methods** card in **Admin → Settings** says the password settings are controlled by `OIDC_ONLY` and cannot be changed there. To disable password login at runtime without `OIDC_ONLY`, switch off **Password Login** and **Password Registration** in that card instead. **SSO Login** in the same card turns the SSO button on or off.
When password login and password registration are both off, through `OIDC_ONLY` or the two switches, the **Change Password** section is hidden from **Settings → Account**.
> **Note:** The admin panel prevents you from disabling all login methods simultaneously. At least one method (password or SSO) must remain active. Similarly, you cannot remove the OIDC configuration from the admin panel while password login is disabled.
+9 -4
View File
@@ -18,7 +18,11 @@ TREK must be served over **HTTPS** — the install prompt does not appear on pla
Once installed, TREK launches in **standalone** mode (fullscreen, no browser UI) using the TREK icon.
The installed app starts at the app root, so the **Start page** setting decides what you see when you tap the icon — the dashboard, or straight into your active trip on a tab of your choice. See [Display-Settings](Display-Settings).
The installed app starts at the app root, so the **Start page** setting decides what you see when you tap the icon: the dashboard, or straight into your active trip on a tab of your choice. See [Display-Settings](Display-Settings).
### The app reopens where it was
Phones close an installed app in the background soon after you switch away from it, for example to a map app for directions. When you open TREK again within six hours, the installed app goes back to where you were instead of the start page: the same trip, on the same tab and the same day of the plan, or the Journey, Collections, Vacay, Atlas or Files page you had open. After six hours, or after logging out, it starts at the start page again. This only happens in the installed app; in a browser tab, opening the address starts as usual.
### Push notifications
@@ -61,8 +65,9 @@ On login, when the browser comes back online, and when you lift **Force offline
**Sync scope and eviction**
- Only ongoing and future trips are cached (trips whose `end_date` is today or later, or has no end date).
- Ongoing and future trips are cached (trips whose `end_date` is today or later, or has no end date).
- Trips that ended more than 7 days ago are automatically evicted from IndexedDB on the next sync.
- A finished trip is cached too when you switch it on yourself under **Settings → Offline → What to store offline**, and it is then kept regardless of its dates.
## Settings → Offline
@@ -79,7 +84,7 @@ The **Offline** tab gives you control over what is stored on this device and let
### What to store offline
- **Store map tiles offline** — map tiles use the most storage by far. Turn this off to keep only trip data and documents on the device; the pre-downloaded tile cache is cleared immediately.
- **Per-trip toggle** — each trip has its own on/off switch. Turning a trip off evicts its cached read data from the device (your unsynced edits are kept and still sync).
- **Trips**: each trip has its own switch, with **Stored offline** or **Not stored** under its name. Turning a trip off evicts its cached read data from the device (your unsynced edits are kept and still sync). A finished trip is marked *Finished. Only stored if you switch it on.*: it is left out by default, and switching it on keeps it on the device.
### Sync conflicts
@@ -87,7 +92,7 @@ If a change you made offline collides with a newer change on the server, it is s
### Stats & cache
The stats panel shows cached trips, pending changes, conflicts and failed changes. **Clear cache** removes all offline data from IndexedDB (you can re-sync any time while online). Each cached trip entry shows its date range, place/file count and last successful sync.
The stats panel shows cached trips, pending changes, conflicts and failed changes. **Clear cache** removes all offline data from IndexedDB after you confirm it in TREK's dialog (you can re-sync any time while online). Each cached trip entry shows its date range, place/file count and last successful sync.
## Limitations
+9 -3
View File
@@ -16,6 +16,10 @@ TREK turns a trip into a printable **Trip Plan PDF**: a cover, a map of the whol
![Export dialog with the PDF under Document, Download .ics and Subscribe to calendar under Calendar, and the three GPX downloads under Maps & GPS](assets/ExportDialog.png)
### My plan as PDF
When some activities or bookings of the trip name who takes part (participants on a day plan entry, travelers on a booking), the **Document** group also offers **My plan as PDF** (*Only the activities and bookings you take part in*). It builds the same document with only your part of the plan: an entry or booking that names its people stays only when it names you, and one that names nobody belongs to everyone and stays. The row is offered on the phone's export sheet as well.
The other groups of the same dialog are covered elsewhere: **Calendar** in [Calendar-Feeds](Calendar-Feeds), and the GPX downloads under **Maps & GPS** (*Whole trip*, *Places only*, *Days as routes*) in [Map-Features](Map-Features#exporting-a-trip-as-gpx).
### Cover page
@@ -28,7 +32,7 @@ The other groups of the same dialog are covered elsewhere: **Calendar** in [Cale
- **Places**: every place in the trip's place list
- **Planned**: how many different places are assigned to at least one day
- **Distance**: the routed distance of the whole trip, in your own unit; left out when no day has a route
- **Cost**: the prices of all assigned places, in the trip's currency; left out when it is zero. Mixed currencies are converted at current rates and marked with "≈"; when a rate is missing, the figure is shown per currency instead
- **Cost**: with the Costs addon on, the expenses of the trip from Costs, each counted once (an expense linked to a place lands on that place's day); without it, the price of each planned place, once. In the trip's currency, left out when it is zero. Mixed currencies are converted at current rates and marked with "≈"; when a rate is missing, the figure is shown per currency instead
### Route overview
@@ -42,17 +46,19 @@ Routes come from the same router the planner uses, and the export does not wait
### Day pages
Each day starts on a new page, unless you turn off **Page break per day**, with a dark header: the day number, its title, the date and the day's estimated cost.
Each day starts on a new page, unless you turn off **Page break per day**, with a dark header: the day number, its title, the date and the day's cost, counted the same way as the **Cost** figure on the cover.
**Page break per day** is a switch in the preview's header, next to **Save as PDF**. It is on by default. Turn it off and the days run on one after another, which saves paper on a trip of short days that would otherwise print a sheet for every handful of lines. Your choice is remembered in that browser for the next export.
**Transport notes** sits next to it when a flight, train, rental or other transport of the trip has notes. On by default, it prints those notes under the transport in the day plan; turn it off to leave them out. This choice is remembered in the browser too.
Under the header:
- **The stay**, when an accommodation covers that day: *Check-in* on the first day, *Check-out* on the last, *Accommodation* on the nights in between, with the time, the place name, the address, the notes, and the booking code on the check-in day only
- **The day's entries**, in the order of the day plan:
- **Places**: a photo (or a coloured category icon without one), a numbered badge, the name, the category, the address, the description, the time, the price and the notes
- **Notes**: the icon, the text and the time, if set
- **Bookings**: the type icon, the title, the time, the details that fit the type (airline, flight number and route for a flight; train number, platform and seat for a train; party size for a restaurant; the venue for an event; the operator for a tour), the location and the booking code
- **Bookings**: the type icon, the title, the time, the notes of a transport (unless **Transport notes** is off), the details that fit the type (airline, flight number and route for a flight; train number, platform and seat for a train; party size for a restaurant; the venue for an event; the operator for a tour), the location and the booking code
### Footer
+13 -4
View File
@@ -34,6 +34,8 @@ Under the progress card, beside the Shared and My list switch (see [The two view
- **Open**: what still has to be packed.
- **Done**: what is already packed.
On the desktop, **A to Z** at the far end of the same row shows each list's items in name order, so you can check at a glance whether something is already on the list. Click it again to go back to the manual order. TREK remembers the choice in this browser.
## Categories
Items are grouped into categories, each a card with a coloured dot taken from a palette of ten. A new packing list starts empty and reads *Packing list is empty* until you add something: create lists and items by hand, apply a saved template (see [Templates](#templates)), or paste a whole list in at once (see [Importing a list](#importing-a-list)).
@@ -63,6 +65,8 @@ Each item row holds:
- the **quantity** and, with bag tracking on, the **weight** in grams, as small badges you click to type into,
- with bag tracking on, the **bag** circle, which opens the bag picker. The picker stays open until you click beside it.
An item with a quantity above one also shows a packed counter (for example **3/10**) with a minus and a plus beside it: count the pieces in as they go into the bag. Once the count reaches the quantity, the item ticks itself off.
At the end of the row sit the **delete** bin and a **⋯** menu with **Move to List**, **Sharing**, **Rename** and **Delete**. Whatever a row does not use (a quantity of one, an empty weight, no bag, the bin and the menu) stays dimmed until you point at the row or tab into it, so the columns stay in line from row to row.
**Add item** at the foot of each list opens a field shaped like the next row: Enter adds the item and keeps the field open for the next one, Esc closes it. A whole list comes in at once with **Import** (below).
@@ -96,7 +100,7 @@ A Markdown list is read as well, the way Obsidian, Notion, GitHub and most notes
Anything that is neither a heading nor a list item, a note or a blank line, is left out.
Import is the only way to load weights and bag assignments in bulk; applying a template brings across names and categories only. It needs the `packing_edit` permission.
Import loads weights and bag assignments in bulk, and so does applying a template (see [Templates](#templates)). It needs the `packing_edit` permission.
## Printing and exporting
@@ -131,6 +135,8 @@ Open **Sharing** in an item's **⋯** menu to move it between tiers:
New items take the view you add them in: an item added in **My list** is Personal, one added in **Shared** goes to the group pool. The same goes for a template applied while **My list** is open. To share an item with specific people, add it first, then open its Sharing control and choose them.
In **My list**, a list whose items you have all shared with the same people passes that on: a new item added to it is shared with those people right away. If the items in the list differ, or one of them is kept to yourself, the new item stays Personal.
Only the item's owner (the person bringing it) can change its sharing. Someone you shared an item *with* sees it on their **My list** with a **by {name}** badge and can tick it off, but does not manage who else it is shared with.
### Who's bringing what
@@ -160,7 +166,10 @@ With it on, a **Bags** card sits to the right of the lists on wide screens; on n
- the avatars of the members assigned to the bag, beside its name, with a dashed **+** to pick them,
- the item count, under the fill bar.
Below the bags, **Unassigned** counts the items that are in no bag and their weight, and **Total weight** at the foot of the card sums everything.
Below the bags, **Unassigned** counts the items that are in no bag and their weight. The foot of the card then shows:
- **Per person**: what each member carries, from the bags they are assigned to. A bag shared by several people is split evenly between them; the weight is then underlined and says so on hover.
- **Total weight**: the sum of everything, with **Packed** under it, the weight already packed (for an item with a packed counter, only the pieces counted in), and a thin bar for the share.
To use bags:
@@ -172,8 +181,8 @@ To use bags:
Packing lists can be saved and reused across trips:
- **Save as template** (instance admins only): click **Save as template** in the Lists bar and name the template in the dialog that opens. It saves the current list's items and categories, and only shows when the list has items.
- **Apply template**: when templates exist, **Apply template** in the Lists bar opens them with their item counts. Picking one adds its items to the list in the view that is open, without removing anything already there.
- **Save as template** (instance admins only): click **Save as template** in the Lists bar and name the template in the dialog that opens. It saves the current list's items and categories with each item's weight, quantity and bag, and only shows when the list has items.
- **Apply template**: when templates exist, **Apply template** in the Lists bar opens them with their item counts. Picking one adds its items to the list in the view that is open, with their weight, quantity and bag, without removing anything already there. A bag the trip does not have yet is created.
Templates are managed by admins in [Admin-Packing-Templates](Admin-Packing-Templates). See also [Packing-Templates](Packing-Templates).
+5 -5
View File
@@ -6,19 +6,19 @@ Reuse packing lists across trips using pre-built templates.
## Applying a template
In the Packing Lists panel, click the **Apply Template** button (shown with a package icon in the toolbar). A dropdown lists all available templates, each showing its name and item count. Click a template to apply it.
In the Lists bar of the packing list, click **Apply template** (package icon). A menu lists all available templates, each with its name and item count. Click a template to apply it.
Applying a template copies all categories and items from the template into the current trip's packing list — existing items are not removed. Items are inserted with the same category names as defined in the template, so they appear alongside any existing items that share the same category name.
Applying a template copies all categories and items from the template into the current trip's packing list; existing items are not removed. Items keep the category names of the template, so they appear alongside any existing items that share the same category name. Each item brings its weight, quantity and bag along; a bag the trip does not have yet is created. The items land in the view that is open: in **Shared** they go to the group pool, in **My list** they are Personal.
Requires the `packing_edit` permission.
On the desktop planner the **Apply Template** button appears as soon as at least one template exists — it is not permission-gated in the UI. A member without `packing_edit` still sees it; the server refuses the apply with `403 No permission` and the app shows a *Failed to apply template* toast. On mobile the packing tab does gate it: the action menu that holds Apply Template only opens for members who have `packing_edit`.
On the desktop planner the **Apply template** button appears as soon as at least one template exists; it is not permission-gated in the UI. A member without `packing_edit` still sees it; the server refuses the apply and the app shows a *Failed to apply template* toast. On the phone the packing tab does gate it: **Apply template** sits in the packing list's action menu and only shows for members who have `packing_edit`.
## Saving the current list as a template
In the packing panel toolbar, click the **Save as template** button (folder-plus icon) when items exist in the list. An inline name input appears in the toolbar — type a name and press **Enter** or click the confirm button. The template captures the **Shared** pool plus your own items — other members' Personal items, and the items they shared with specific people, are deliberately left out. Only each item's name and category are stored; quantities, weights, bag assignments and checked state are not.
In the Lists bar, click **Save as template** when the list has items. A small dialog asks for the **Template name**; click **Save**. The template captures the **Shared** pool plus your own items; other members' Personal items, and the items they shared with specific people, are deliberately left out. Each item is stored with its name, category, weight, quantity and bag name; the checked state is not.
The Save as Template button only appears when there are items in the list, you have the `packing_edit` permission, and you are an instance admin. Non-admins can apply templates but not create them; the API answers a non-admin with `403 Admin access required`.
The **Save as template** button only appears when there are items in the list, and you are an instance admin with the `packing_edit` permission. Non-admins can apply templates but not create them; the API answers a non-admin with `403 Admin access required`.
> **Admin:** Templates are created and managed in [Admin-Packing-Templates](Admin-Packing-Templates). Each template has a three-level structure: template → categories → items.
+3
View File
@@ -59,6 +59,9 @@ When choosing a new password (whether via the reset flow, the forced-change prom
- Contain at least one **number**
- Contain at least one **special character**
- Not be a commonly used password
- Not consist of a single repeated character
While you type, the form lists the five character rules under the password field and ticks each one off as it is met, so you see what is still missing before you submit.
## Rate limiting
+10 -4
View File
@@ -29,8 +29,8 @@ Go to **Settings → Integrations**. Each enabled provider gets its own settings
|-------|----------|-------|
| Server URL | Yes | Full URL of your Immich instance, e.g. `https://immich.example.com` |
| API Key | Yes | Stored encrypted; never returned to the browser after saving |
| Skip SSL certificate verification | No | Checkbox; lets TREK connect to an Immich server with a self-signed certificate. Off by default |
| Mirror journey photos to Immich on upload | No | Checkbox; when enabled, photos you upload in TREK are also pushed to your Immich library |
| Skip SSL certificate verification | No | Switch; lets TREK connect to an Immich server with a self-signed certificate. Off by default |
| Mirror journey photos to Immich on upload | No | Switch; when on, photos you upload in TREK are also pushed to your Immich library |
Enter the full URL of your Immich instance and an Immich API key. The API key is stored encrypted on the TREK server and is never returned to the browser after it is saved.
@@ -67,7 +67,7 @@ TREK never modifies or deletes anything in Immich, so no `update`, `delete`, or
| Username | Yes | Synology account username |
| Password | Yes | Stored encrypted; leave blank to keep the existing password |
| MFA code (if enabled) | No | One-time password for 2FA; only needed on first connection or when re-authenticating |
| Skip SSL certificate verification | No | Checkbox; disable TLS certificate validation for self-signed certificates |
| Skip SSL certificate verification | No | Switch; disables TLS certificate validation for self-signed certificates |
#### Required DSM account permissions
@@ -84,7 +84,7 @@ Synology Photos doesn't use API keys — TREK signs in with a regular DSM user a
## Testing the connection
Each provider section has a **Test Connection** button. Clicking it sends your current field values to the server and attempts to authenticate with the provider. A green "Connected" badge confirms success; any error message from the provider is shown if it fails.
Each provider card has a **Test connection** button next to **Save**. Clicking it sends your current field values to the server and attempts to authenticate with the provider. The card's badge then reads **Connected** (otherwise **Not connected**); any error message from the provider is shown if it fails.
For Synology, a successful test stores a session token so the OTP code is not required again on subsequent saves (as long as the URL and username remain the same).
@@ -100,6 +100,12 @@ You can configure both Immich and Synology simultaneously. TREK queries photos f
Once a provider is connected, you can browse and attach photos to your trips. See [Documents-and-Files](Documents-and-Files) for how to manage files after setup.
In the [Journey Journal](Journey-Journal) the same libraries are used in three places:
- the **External photos** tab of the entry editor, which searches the entry's day and puts photos taken near the entry first (see [External photos](Journey-Journal#external-photos));
- the journey gallery's photo picker, with **Select all** over a day, the **Trip Period**, a **Date Range** or **All Photos**;
- TREK Studio, where the **Content** section offers **From Immich** and **From Synology Photos** next to **Upload photos** (see [TREK Studio](Journey-Journal#trek-studio)).
---
## See also
+36 -11
View File
@@ -9,11 +9,13 @@ Places are the building blocks of a trip: sights, restaurants, hotels, stations,
The right column of the Plan tab lists every place of the trip. Its head band has three rows:
1. **Add Place/Activity** and the import button (*Import Places*). While a day is open, the add button splits in two: **New place** adds a place to the trip, **To day** (*Add to the open day*) puts it straight onto that day. In a narrow column both buttons drop to their icons. The import button opens a menu with **Import file** and **List Import** (it reads **Google List** when Google is the only list source); see [Importing multiple places](#importing-multiple-places).
2. **Search**, which narrows the list to places whose name or address contains what you type, and the **Select** button, see [Selecting several places](#selecting-several-places).
3. Three filters:
2. **Search**, which narrows the list to places whose name, address, description or notes contain what you type, and the **Select** button, see [Selecting several places](#selecting-several-places).
3. The filters and the order:
- **Show**: **All**, **Unplanned**, **Planned**, and **Tracks** once the trip has one, each with its count.
- **Categories** (the tag icon): tick one or several categories, or **No Category**. A badge on the icon counts the categories in force, and **Clear filter** lifts them.
- **Filter by rating** (the star): **All**, or a floor from **5+** down to **1+**.
- **Filter by country or region** (the globe): every country the trip's places lie in, with its regions underneath, each with the number of places in it. Pick a country or one region; **All countries** is the default and **Clear filter** goes back to it. The button only appears once the trip spans more than one country or region.
- **Sort by**: newest first (**Recently added**, the default), **Oldest first**, by name, **Highest rated** or **Recently changed**. The order applies to the list only, not to the map, and your browser remembers it.
With a day open and **Planned** chosen, the list shows only that day's places, and a chip says **Showing the open day only**. Its **X** (*Show the whole trip*) closes the day. See [Trip Planner Overview](Trip-Planner-Overview#layout).
@@ -47,9 +49,12 @@ Click **Select** (the tick next to the search field) to switch the list into sel
![The Edit Place dialog: the name and category in the head band, Place details with picture choices on the left, the form in the middle and Saved places on the right](assets/PlaceForm.png)
- **The head band** holds the name, which you type straight into the band, and the category as a pill. The **+** next to the pill (*New category*) turns it into a field for a new category's name; **OK** or Enter creates it, **Cancel** or Escape closes the field. After a search pick, a pill names where the place came from.
- **Search** finds the place and fills in the rest, see [Searching for a place](#searching-for-a-place).
- **The head band** holds the name, which you type straight into the band, and the category as a pill. The **+** next to the pill (*New category*) turns it into a field for a new category's name; **OK** or Enter creates it, **Cancel** or Escape closes the field. Categories are shared by the whole instance, so creating one takes an admin account (see [Tags and Categories](Tags-and-Categories)). After a search pick, a pill names where the place came from. Once the place has coordinates, the round **Open in maps** pill opens it in a map app, the same menu as **Navigation** (see [Opening a place in a map app](#opening-a-place-in-a-map-app)).
- **Search** finds the place and fills in the rest, see [Searching for a place](#searching-for-a-place). A place picked from the search, or from a marker of the [map categories](#exploring-the-map-by-category), comes with the matching category already picked when the trip's palette has one (a hotel goes to the category named like Hotel or Accommodation, a café to Café or Bar, and so on). A category you chose yourself is never replaced.
- **Places near this pin** (the target button beside the search button) appears once the form has coordinates, for example after a right-click on the map. It lists the named places around that point, nearest first with their distance, so you can pick the café you clicked on instead of keeping a bare pin. The TREK API answers it; when it has nothing, Google with a key, otherwise OpenStreetMap. The same lookup is `POST /api/maps/nearby` and the MCP tool `search_nearby_places`.
- When a full search finds nothing, a box says *Nothing found for "…"* with **Add by hand**: it takes what you searched for as the name, if the name is still empty, and jumps to the phone, e-mail and opening hours fields.
- **Address**, **Latitude** and **Longitude** say where it is.
- **Phone**, **E-mail** and the opening hours are the place's own, see [Phone, e-mail and opening hours](#phone-e-mail-and-opening-hours).
- **Start**, **End** and **Notes for this day** appear when you edit a place from a day, since they belong to that one visit.
- **Description** and **Notes** take Markdown and each have a formatting bar.
- **Website** and **Files** sit side by side; **Attach** picks files.
@@ -71,12 +76,22 @@ Click **Select** (the tick next to the search field) to switch the list into sel
| Description | Markdown. |
| Notes | Markdown, up to 2,000 characters. |
| Website | A URL. |
| Phone / E-mail | Free text. Filled in by a search pick when the source knows them. |
| Opening hours | Per weekday, see [below](#phone-e-mail-and-opening-hours). |
| Files | **Attach** a file, or paste an image or a PDF anywhere in the dialog. The files are uploaded when the place is saved. The instance's **Allowed File Types** list applies (by default jpg, jpeg, png, gif, webp, heic, pdf, doc, docx, xls, xlsx, txt, csv, pkpass, pkpasses, md and markdown), plus video, which is exempt from that list. See [Documents-and-Files](Documents-and-Files). |
Two warnings appear under the times: one if the end lies before the start, and one (*Time overlap with:*) naming the places on the same day whose times overlap.
A new place that looks like one already on the trip (the same name, the same Google place, or practically the same coordinates) is not saved at once. A message says *'Louvre' is already in this trip.* and the save button turns into **Add anyway**.
### Phone, e-mail and opening hours
A place can carry its own **Phone**, **E-mail** and opening hours, so a guesthouse no provider knows gets the same fields as a place found through Google. A search pick fills in phone and website when its source has them; everything else you type yourself.
The hours stay folded away until you click **Add opening hours**. Each weekday then gets an *opens* and a *closes* time, or **Closed**. A button copies the first day's hours to every day, and **Remove opening hours** clears them all again. When the [Place details](#place-details-while-searching) column found hours for the place, a place without hours of its own takes them over on its own; one that already has some gets **Take over from the place details** instead.
The place inspector shows the phone and the e-mail address as pills in its head band (a click calls or writes), and your own hours win over the ones a provider knows.
### Costs for a place
With the [Costs](Budget-Tracking) addon enabled, the place form carries the same **Costs** block that bookings and transports have. **Create expense** saves the place and then opens the Costs editor for a new expense linked to it: the museum ticket, the guided tour, the entry fee. On a saved place, **Link existing expense** ties one that is already in Costs. Every linked expense is listed with edit, **Unlink, keep the expense** and **Remove expense**, and a place can carry several.
@@ -98,6 +113,10 @@ After two or more characters and a 300 ms pause, suggestions appear under the se
- Only when the TREK API has nothing does TREK ask the keyed provider (Google or Amap), or, without one, OpenStreetMap's own search service.
- An installed [search plugin](Plugin-Cookbook#suggestions-while-the-user-types) whose index can keep up with typing adds up to three of its places under the suggestions, marked with the plugin's name. Picking one fills in what the plugin knows about the place, with no second lookup.
### Language of place names
By default, search, suggestions and addresses answer in the language TREK is set to. **Settings > General > Language & region > Place names** picks another one, for example English names while the app is in German, or **Same as the app** again. Where a place has no name in that language, its local name is shown. The TREK API has no translations, so its results keep the names used on the spot either way.
### The full search
Press **Enter** without picking a suggestion, or click the search button beside the field, to run a full search. It asks the TREK API and OpenStreetMap at the same time and interleaves their answers, TREK first, up to ten results. A place both of them know (within 60 metres, with a matching name) is listed once.
@@ -146,6 +165,8 @@ The key's block carries five switches under **What the key may be used for**:
| **Place Enrichment** | The **Place details** column in the place form, see [below](#place-details-while-searching). |
| **Search with Google only** | Every search and every suggestion goes to Google Places instead of the TREK API and OpenStreetMap. Off by default. On, every list already comes from Google, so the per-search line above has nothing to offer and does not appear; off, the line appears under lists the TREK API or OpenStreetMap produced. |
Under the switches, **Daily limit for Google calls** caps how many calls TREK makes to Google per day. A badge beside it shows today's count (*Today: 120 of 500*). Once the limit is reached, TREK stops calling Google until the next day (UTC) and searches with OpenStreetMap instead. Leave the field empty for no limit, which is the default.
> **Place Autocomplete and Place Details act on every provider**, not only on Google. Switched off, the suggestion dropdown stays empty and details lookups stop for the TREK API and OpenStreetMap too; the full search keeps working. Leave both on unless that is what you want.
> **API key restrictions:** TREK calls the Google Places API from the server, not the browser. If you apply **HTTP referrers** restrictions to your key in Google Cloud Console, you must also set `APP_URL` in your environment: TREK sends it as the `Referer` header on every outbound Google API request, and without it Google rejects every server-side call with `REQUEST_DENIED`. For server-side deployments, **IP address** restrictions are simpler and need no extra configuration. See [Troubleshooting](Troubleshooting) if photos are missing after adding a key.
@@ -209,7 +230,7 @@ Pictures are copied to your own server and served from there. Nothing is loaded
> **Admin:** the column is controlled by **Place Enrichment**, under **What the key may be used for** in the Google Maps API Key block of **Admin → Settings → API Keys**, and it is on by default. Wikipedia and OpenStreetMap are always used; the Google half additionally follows **Place Photos** and **Place Details**. Turning Place Enrichment off leaves the column with a short note and makes no outbound calls.
The column is desktop-only.
On the phone, the place editor shows the same details under its search field: the pictures to pick from, the opening hours, the rating and the description with **Use this text**.
## Saved places
@@ -231,10 +252,10 @@ Click a place in the places column, in a day, or on the map, and its inspector o
![The place inspector over the map: the photo, name and address in its head, then the rating, the description, the notes and the files, with Add to Day, Navigation, Save to Collection and Edit at its foot](assets/PlaceInspector.png)
- **The head band** shows the photo, with a green ring while the place is open and a red one while it is closed, the name (double-click it to rename the place), the address on one line with the full address in a tooltip, and pills: **Open** or **Closed**, the category, the time of the visit, the Google rating, the phone number to call, and the coordinates. **X** closes the inspector.
- **The head band** shows the photo, with a green ring while the place is open and a red one while it is closed, the name (double-click it to rename the place), the address on one line with the full address in a tooltip, and pills: **Open** or **Closed**, the category, the time of the visit, the Google rating, the phone number to call, the e-mail address, and the coordinates. **X** closes the inspector.
- **Rating**: every member's vote, see [Rating a place](#rating-a-place).
- **Description**, **Notes** and **Notes for this day**, rendered as Markdown.
- **Bookings** pinned to this stop, as small cards with the status, date, time and booking code. Click a card (*Open booking*) to open the booking's detail. Next to them, **Participants** says who joins this stop.
- **Bookings** pinned to this stop, as small cards with the status, date, time and booking code. For a hotel, the stays booked there are listed too (see [Accommodations](Accommodations)). Click a card (*Open booking*) to open the booking's detail. Next to them, **Participants** says who joins this stop.
- **Opening Hours**: today's line, and the whole week a click away.
- **Files**: the place's files and the files of its bookings, with **Upload**.
- For an imported track: its statistics and **Track color**, see [GPX tracks](Map-Features#gpx-tracks).
@@ -253,15 +274,19 @@ Saved places in [Collections](Collections) are rated the same way. Saving a trip
## Custom place image
By default a place's thumbnail is fetched automatically (from Google or Wikimedia when the place was imported or matched, otherwise it shows a category icon). To use your own photo instead, click the round photo in the head band of the place inspector. Pick an image and it becomes that place's thumbnail everywhere (list, map marker, itinerary, PDF export and shared trips). A small remove button on the photo clears the custom image and restores the automatic default. Accepted formats are JPG, PNG, GIF and WebP (HEIC is converted automatically), up to 20 MB.
By default a place's thumbnail is fetched automatically (from Google or Wikimedia when the place was imported or matched, otherwise it shows a category icon). To use your own photo instead, click the round photo in the head band of the place inspector. When the place or one of its bookings has pictures attached (JPG, PNG, GIF or WebP), a small menu offers **Upload from device** and **From attached files**, so a photo already on the trip can be reused without uploading it again. Pick an image and it becomes that place's thumbnail everywhere (list, map marker, itinerary, PDF export and shared trips). A small remove button on the photo clears the custom image and restores the automatic default. Accepted formats are JPG, PNG, GIF and WebP (HEIC is converted automatically), up to 20 MB.
A picture picked under **Pick a picture** in the place form works the same way, see [Place details while searching](#place-details-while-searching). The same control is available on saved places in [Collections](Collections#place-detail).
## Opening a place in a map app
**Navigation** in the footer of the place inspector, on the phone's place sheet and on a saved place in Collections opens a short menu of map apps, in this order: **Google Maps**, **Waze**, **Apple Maps**, **OpenStreetMap**, **CoMaps** and, for a place in China, **高德地图** (Amap). Waze starts navigating straight away; the others open the place, and starting navigation from there is one tap. When only one app is available the button opens it directly. The **…** menu of a place in a day lists the same apps.
**Navigation** in the footer of the place inspector, on the phone's place sheet and on a saved place in Collections (on the desktop and on the phone), and the **Open in maps** pill in the place form, open a short menu of map apps, in this order: **Google Maps**, **Waze**, **Apple Maps**, **OpenStreetMap**, **CoMaps**, for a place in China **高德地图** (Amap), and on Android **Other map app**. Waze starts navigating straight away; the others open the place, and starting navigation from there is one tap. When only one app is available the button opens it directly. The right-click menu of a stop in a day no longer lists map apps; use **Navigation**. The **…** menu of a row in the places column still has **Google Maps**.
Which entries appear depends on the place and on where you are, not on the search provider the admin picked. Apple Maps is left out on Android. Amap is offered by where the place is, because it only has a map of China: a stop in Shanghai gets it whoever is planning the trip, a stop in Lisbon never does. Waze, Apple Maps, CoMaps and Amap need the place's coordinates; Google Maps and OpenStreetMap can still open a place that has none, Google from its name and address, OpenStreetMap from its name. Coordinates handed to Amap are converted to its own datum on the way out, so the pin lands on the right street.
**Other map app** hands the place's coordinates to Android as a `geo:` link, so Android offers every map app installed on the phone, OsmAnd or Organic Maps for example.
To skip the menu, pick your app under **Settings > General > Travel & map > Open places in**. With an app picked, every navigate button opens it straight away; **Ask every time** brings the menu back. A place that app cannot open (Amap outside China, Waze without coordinates) still shows the full menu.
Which entries appear depends on the place and on where you are, not on the search provider the admin picked. Apple Maps is left out on Android, and **Other map app** is offered only there. Amap is offered by where the place is, because it only has a map of China: a stop in Shanghai gets it whoever is planning the trip, a stop in Lisbon never does. Waze, Apple Maps, CoMaps and Amap need the place's coordinates; Google Maps and OpenStreetMap can still open a place that has none, Google from its name and address, OpenStreetMap from its name. Coordinates handed to Amap are converted to its own datum on the way out, so the pin lands on the right street.
In the installed app the map app takes over the current window rather than a new tab, so coming back lands you where you were.
@@ -276,7 +301,7 @@ Imported tracks each get their own line colour so multiple routes stay apart on
Importing the same list again does not duplicate what is already in the trip. A place is recognised by the provider id it was imported with (Google place id, Google feature id, or OSM id) before its name or its coordinates are considered, so renaming a place in TREK, or moving its pin, does not make it come back as a second copy on the next import.
> **Admin:** with a Google Maps API key in **Admin → Settings → API Keys**, the list import offers **Enrich places via Google**, which looks up each imported place to fill in photos, address and contact details, one Google lookup per place. Without a key the import works the same, just without that option.
> **Admin:** with a Google Maps API key in **Admin → Settings → API Keys**, the list import offers **Enrich places via Google**, which looks up each imported place to fill in photos, address and contact details, one Google lookup per place. **Import file** offers the same switch while **Waypoints** (GPX) or **Points (Placemarks)** (KML, KMZ) are ticked: each imported point is looked up on Google afterwards and gets its photo, address, website and phone, while paths and tracks stay as they are. Without a key the imports work the same, just without that option.
## Exploring the map by category
+3 -3
View File
@@ -6,7 +6,7 @@ Share a read-only view of your trip with people who do not have a TREK account.
## Creating a share link
Open your trip and click the **Share** button (Users icon) in the top navbar. This opens the Members & Share modal. The share link section appears on the right side of the modal and is visible only to users with the `share_manage` permission (trip owner and admins by default).
Open your trip and click the **Share** button (Users icon) in the top navbar. This opens the **Share Trip** dialog. The **Public Link** card appears in its right column and is visible only to users with the `share_manage` permission (trip owner and admins by default).
Click **Create link** to generate a token.
@@ -22,7 +22,7 @@ Copy this URL and send it to anyone you want to share the trip with. No TREK acc
A share link is valid for **90 days**, counted from the last time it was saved. Creating the link writes a 90-day expiry, and flipping one of the unlocked permission toggles re-saves the link and writes a new one, so a link you actively manage never lapses under you.
Once the 90 days are up, visitors get **Link expired or invalid**. The share section in the Members & Share modal does not show this — it keeps displaying the URL and the **Delete link** button, because the owner-side lookup ignores the expiry. There is no expired badge to warn you.
Once the 90 days are up, visitors get **Link expired or invalid**. Only an unknown, expired or deleted link shows that screen. When the page cannot be loaded for another reason (the server restarting, a proxy error, a viewer who is briefly offline), the visitor sees **This trip could not be loaded** with the hint that this does not mean the link has expired, and **Try again** reloads it in place. The **Public Link** card in the Share dialog does not show this: it keeps displaying the URL and the **Delete link** button, because the owner-side lookup ignores the expiry. There is no expired badge to warn you.
To revive a lapsed link, flip one of the unlocked toggles — **Bookings**, **Packing**, **Costs** or **Chat** — and flip it back if you did not mean to change anything. **Map & Plan** is locked, so clicking it sends no request and will not revive the link. Flipping an unlocked toggle re-saves the **same** token for another 90 days and the old URL starts working again. If you want a genuinely different URL, because the old one leaked for instance, use **Delete link** and then **Create link**.
@@ -44,7 +44,7 @@ Disabled toggles hide the corresponding tab from the public viewer entirely. Per
### Options
Under the toggles, two options narrow what the Plan tab shows. Both are off by default and apply the moment you flip them.
Under the toggles, the **Options** row has two switches that narrow what the page shows. Both are off by default and apply the moment you flip them.
| Option | What it does |
|--------|--------------|
+2
View File
@@ -56,6 +56,8 @@ On first boot TREK automatically seeds an admin account before any user register
You will be prompted to change the password on first login.
**Moving an existing TREK?** Instead of setting up a new admin, start the new install with `RESTORE_FROM_BACKUP` pointing at a backup ZIP inside the container (for example `-e RESTORE_FROM_BACKUP=/app/data/backup.zip` with the file placed in `./data`). On that first start TREK restores the backup before any setup and creates no admin account; sign in with an account from the backup. See [Backups](Backups#restoring-on-a-new-install-before-setup).
> **Admin:** As admin you unlock the Admin Panel — user management, addon toggles, packing templates, backups, and API key configuration.
## Next Steps
+6 -6
View File
@@ -6,7 +6,7 @@ TREK keeps every trip in sync across all connected members without requiring a p
## Real-time sync
All changes to a trip — places, day plans, reservations, budget entries, and packing lists — are broadcast instantly to every connected member via WebSocket. You see other people's edits as they happen.
All changes to a trip (places, day plans, reservations, budget entries and packing lists) are broadcast instantly to every connected member via WebSocket. You see other people's edits as they happen.
## WebSocket transport
@@ -21,10 +21,10 @@ All changes to a trip — places, day plans, reservations, budget entries, and p
**Authentication** uses a short-lived ephemeral token passed as a query parameter on connect. If authentication fails, the server closes the connection with one of these codes:
- **4001** — missing, invalid, or expired token; user not found
- **4403** — site-wide MFA is required but the account does not have MFA enabled
- **4001**: missing, invalid, or expired token; user not found
- **4403**: site-wide MFA is required but the account does not have MFA enabled
An origin rejection happens before the socket exists, so it produces no close code at all — the browser just reports a failed connection. And because clients that send no `Origin` header are exempt, curl and other CLI clients keep connecting while every browser fails, which makes it look like a client bug. If real-time sync stops working behind a reverse proxy, check that `ALLOWED_ORIGINS` lists the exact scheme, host, and port the browser uses: the comparison is a plain string match, so `https://trek.example.com` matches neither `http://trek.example.com` nor `https://trek.example.com:443`. See [Environment-Variables](Environment-Variables) and [Reverse-Proxy](Reverse-Proxy).
An origin rejection happens before the socket exists, so it produces no close code at all: the browser just reports a failed connection. And because clients that send no `Origin` header are exempt, curl and other CLI clients keep connecting while every browser fails, which makes it look like a client bug. If real-time sync stops working behind a reverse proxy, check that `ALLOWED_ORIGINS` lists the exact scheme, host, and port the browser uses: the comparison is a plain string match, so `https://trek.example.com` matches neither `http://trek.example.com` nor `https://trek.example.com:443`. See [Environment-Variables](Environment-Variables) and [Reverse-Proxy](Reverse-Proxy).
## The Collab addon
@@ -44,7 +44,7 @@ On a **desktop** (1024 px and wider) each sub-feature is a card with a head band
### Links
The **Links** panel collects the web addresses a trip runs on: the booking portal, the shared photo album, the restaurant's menu. **Add link** in its head band opens a small dialog for a **Link title** and an `http(s)` address; anything else is refused. Each link is a chip with the site's favicon, the title and the host, two to a row where the panel is wide enough and one to a row where it is narrow; a pinned chip is drawn in the accent tint. The whole chip is the link and opens the address in a new tab. Members with `collab_edit` find three buttons in the chip's tail, faint until the pointer is on the chip and always shown on touch: **Edit link** opens the same dialog with the title and the address filled in, **Pin link** moves it to the top of the list, and **Delete link** asks first, because the link goes for every member. Pinned links come first, then the newest. Adding, editing, pinning and deleting show up for every connected member at once.
The **Links** panel collects the web addresses a trip runs on: the booking portal, the shared photo album, the restaurant's menu. **Add link** in its head band opens a small dialog for a **Link title** and an `http(s)` address; anything else is refused. Each link is a chip with the site's favicon, the title and the host (a long title wraps onto further lines rather than being cut off), two to a row where the panel is wide enough and one to a row where it is narrow; a pinned chip is drawn in the accent tint. The whole chip is the link and opens the address in a new tab. Members with `collab_edit` find three buttons in the chip's tail, faint until the pointer is on the chip and always shown on touch: **Edit link** opens the same dialog with the title and the address filled in, **Pin link** moves it to the top of the list, and **Delete link** asks first, because the link goes for every member. Pinned links come first, then the newest. Adding, editing, pinning and deleting show up for every connected member at once.
## Conflict handling
@@ -52,7 +52,7 @@ TREK uses a **last-write-wins** model. Each mutation is applied on the server an
On reconnect, any locally queued mutations are flushed to the server before the client re-fetches trip data, so offline changes are applied before the latest state is read back.
There is no operational-transform or CRDT merge — simultaneous edits to the same field are not merged; one silently wins.
There is no operational-transform or CRDT merge: simultaneous edits to the same field are not merged; one silently wins.
## Access control
+13 -4
View File
@@ -8,13 +8,13 @@ Everything you booked for a trip that is not a way of getting around: hotels, re
Open a trip and select the **Bookings** tab. It lists accommodation, restaurant, event, tour, parking and other bookings. Transport records never show up here; they stay on the **Transports** tab, which works the same way and is described on [its own page](Transport-Flights-Trains-Cars).
The tab starts with a bar like the other planner tabs. The name sits on the left. On the right are a search box, **Filter**, the switch between **Cards**, **List** and **Timeline**, and **View options**. If you may edit bookings, the bar ends with **Import booking confirmations** (the download icon, shown when your server can [import confirmations](#import-from-booking-confirmation)) and **Manual Booking**.
The tab starts with a bar like the other planner tabs. The name sits on the left. On the right are a search box, **Filter**, the switch between **Cards**, **List** and **Timeline**, **View options** and **Export as spreadsheet (CSV)** (the spreadsheet icon, see [Exporting as CSV](#exporting-as-csv)). If you may edit bookings, the bar ends with **Import booking confirmations** (the download icon, shown when your server can [import confirmations](#import-from-booking-confirmation)) and **Manual Booking**.
A trip without any bookings shows *No reservations yet* instead, with **Manual Booking** and **Import from file** as buttons right under it.
## Reservation types
TREK knows sixteen types. Six of them belong to the Bookings tab and ten to the Transports tab:
TREK knows seventeen types. Six of them belong to the Bookings tab and eleven to the Transports tab:
| Type | Tab | How it is created |
|------|-----|-------------------|
@@ -24,7 +24,7 @@ TREK knows sixteen types. Six of them belong to the Bookings tab and ten to the
| Tour | Bookings | **Manual Booking** |
| Parking | Bookings | **Manual Booking**; a booking at one fixed place, such as airport parking |
| Other | Bookings | **Manual Booking** |
| Flight, Train, Bus, Car, Taxi, Bicycle, Cruise, Ferry, Other | Transports | The transport editor, see [Transport-Flights-Trains-Cars](Transport-Flights-Trains-Cars) |
| Flight, Train, Bus, Car, Taxi, Bicycle, Cruise, Ferry, Cable car, Other | Transports | The transport editor, see [Transport-Flights-Trains-Cars](Transport-Flights-Trains-Cars) |
| Public transit | Transports | The public transit search, see [Public transit search](Transport-Flights-Trains-Cars#public-transit-search) |
A new booking made with **Manual Booking** starts as type **Other**. Change it with the type pill in the head of the editor.
@@ -78,6 +78,12 @@ The search box looks through the title, the type, the place and address, the acc
A number on the Filter button counts what is switched on, and a chip such as *3 of 12* appears next to the search. Click the chip, or **Reset filters** in the panel, to see everything again. Filters are kept per trip and per tab until you close the browser tab.
## Exporting as CSV
**Export as spreadsheet (CSV)**, the spreadsheet icon after **View options**, downloads the bookings as a CSV file. It holds exactly what the tab shows: the search and the filters apply, and the rows follow **Sort by** from the view options (the grouping is left out, one row per booking). The columns are **Type**, **Title**, **Status**, **Start**, **End**, **From**, **To**, **Location**, **Confirmation** and **Notes**; **From** and **To** are filled for bookings with a route. The file is semicolon-separated with a UTF-8 byte-order mark, so Excel opens it cleanly, and is named after the trip and the tab, such as `berlin-2026-bookings.csv`. A cell that would start with `=`, `+`, `-` or `@` gets a leading apostrophe, so a spreadsheet never runs it as a formula.
The button is there for every member who can see the tab, as soon as it has at least one booking. The Transports tab exports its own list the same way.
## Pending and Confirmed
Every booking is either **Pending** or **Confirmed**. The colour follows it everywhere: an amber dot and head band for pending, green for confirmed.
@@ -111,7 +117,8 @@ Clicking a booking opens its detail over the page. The same popup opens wherever
- a card, a list row or a timeline bar on the Bookings and Transports tabs,
- a booking row in the day plan, a rental car pill in a day's head band, a booking pinned to a stop,
- the **Reservations** list in a day's details, the **Bookings** cards in the place inspector,
- the ticket button (**Open booking**) on a booked stay's pill in a day's head band; the hotel's name on the same pill still opens the place,
- the **Reservations** list in a day's details, the **Bookings** cards in the place inspector (for a hotel, these also list the stay booked for it),
- a booking's endpoint on the map, and the rides on the [Road Trip](Road-Trip) rail.
![Booking detail of a hotel stay: the status, type and day pills and the booking code with a copy button in the head, tiles for check-in, check-out and the nights, the accommodation, and On map, the bin and Edit at the foot](assets/BookingDetail.png)
@@ -149,6 +156,8 @@ A booking for one particular stop is quicker from the plan: point at the stop in
Click the pencil on a card or list row, or **Edit** in the booking detail. The editor opens as **Edit Reservation** with everything the booking has; change what you need and click **Update**.
If you have changed something and then press Escape or click beside the editor, TREK asks *Discard your changes?* before it closes. **Keep editing** takes you back to the form, **Discard** closes it without saving. The cross and **Cancel** close the editor straight away.
To delete a booking, click the bin on its card or row, or **Delete** in the detail. TREK asks once (*Delete booking?*) before it removes the booking.
## Import from booking confirmation
+4 -3
View File
@@ -43,7 +43,8 @@ server {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 86400;
# Documents are capped at 50 MB and photos/covers at 20 MB, but video
# Documents are capped at 50 MB by default (FILE_UPLOAD_LIMIT_MB) and
# photos/covers at 20 MB, but video
# uploads go up to 500 MB — both journey gallery clips and videos in a
# trip's file manager. Backup restore ZIPs can include the full uploads
# directory and may exceed even that (see BACKUP_UPLOAD_LIMIT_MB, default
@@ -65,7 +66,7 @@ server {
Key lines:
- `proxy_read_timeout 86400` — keeps WebSocket connections alive (86400 s = 24 h).
- `client_max_body_size 500m` — allows large backup restore uploads; set in both locations.
- `client_max_body_size 500m`: allows large backup restore uploads and video uploads; set in both locations. If you raise `FILE_UPLOAD_LIMIT_MB` or `BACKUP_UPLOAD_LIMIT_MB` above 500, raise this as well.
- `X-Forwarded-Proto $scheme` — tells TREK whether the original request was HTTPS; required for `FORCE_HTTPS` redirect and cookie security to work correctly.
## Caddy
@@ -137,7 +138,7 @@ Five variables control how TREK behaves behind a proxy. They work as a group:
| `HSTS_INCLUDE_SUBDOMAINS` | When `true`: adds the `includeSubDomains` directive to the HSTS header, extending HTTPS enforcement to all subdomains. Only effective while HSTS is active. Leave `false` if you run other services on sibling subdomains over plain HTTP. | `false` |
| `TRUST_PROXY` | Number of trusted proxy hops. Lets Express read the real client IP from `X-Forwarded-For`. Automatically set to `1` in production even if not explicitly configured. | `1` (production), off (development) |
| `COOKIE_SECURE` | Controls the `secure` flag on `trek_session`. Auto-derived as `true` when `NODE_ENV=production`, when `FORCE_HTTPS=true`, or when the request itself arrived over TLS — Express sets `req.secure` once your proxy sends `X-Forwarded-Proto: https` and `TRUST_PROXY` is configured. Set to `false` explicitly to allow cookies over plain HTTP (e.g. LAN testing without TLS). | auto |
| `ALLOWED_ORIGINS` | Comma-separated list of allowed CORS origins (e.g. `https://trek.example.com`). In production without this set, all cross-origin requests are blocked. In development without this set, all origins are allowed. | blocked in prod, open in dev |
| `ALLOWED_ORIGINS` | Comma-separated list of allowed CORS origins (e.g. `https://trek.example.com`). The address TREK is opened under is always allowed, even when the list does not name it; a request from any other origin gets `403 Not allowed by CORS` and a `CORS: refused origin ...` line in the log. In production without this set, all cross-origin requests are blocked. In development without this set, all origins are allowed. | blocked in prod, open in dev |
> **Note on HSTS:** The `max-age=31536000` header goes out whenever `FORCE_HTTPS=true` **or** `NODE_ENV=production`, and `NODE_ENV=production` is the default in the Docker image, the compose file and the Helm chart — so a standard install sends HSTS even with `FORCE_HTTPS` unset. Browsers ignore the header on a plain-HTTP response, so an instance you only ever reach over HTTP is unaffected. Once a browser has seen it over HTTPS, though, it refuses plain HTTP to that hostname for a year, so don't plan on falling back to `http://` for a hostname you have already served over HTTPS.
+9 -5
View File
@@ -1,6 +1,6 @@
# Route Optimization
TREK works out the walking and driving times between the places of a day, draws the route on the map, can reorder the places into a shorter route, and hands the day to a map app for navigation. All of it sits in the route bar at the foot of the selected day.
TREK works out the driving, walking and cycling times between the places of a day, draws the route on the map, can reorder the places into a shorter route, and hands the day to a map app for navigation. All of it sits in the route bar at the foot of the selected day.
![The route bar of the selected day: the Route toggle, the travel mode, Optimize, and the buttons for Google Maps and CoMaps](assets/PlanRouteBar.png)
@@ -11,7 +11,7 @@ Click a day's head band to select it. Its card then ends in the route bar, as lo
| Control | What it does |
|---|---|
| **Route** | Draws the day's route on the map and shows the travel time between each pair of stops in the day. See [Route lines](Map-Features#route-lines). |
| Travel mode | **Driving** (car), **Walking** (foot), and any mode a plugin adds (bolt). It sets the day's default mode. |
| Travel mode | **Driving** (car), **Walking** (foot), **Cycling** (bike), and any mode a plugin adds (bolt). It sets the day's default mode. |
| **Optimize** | Reorders the day's free places into a shorter route. See [Optimize route](#optimize-route). |
| **Open in Google Maps** | Hands the day's stops to Google Maps as a route. |
| **Open in CoMaps** | Hands the same day to CoMaps for offline navigation. |
@@ -22,16 +22,20 @@ Time that plugins add to the day, such as a charging stop, shows under the bar a
TREK uses **OSRM** (Open Source Routing Machine) to calculate routes between consecutive places in the selected day. No API key is required. By default that is the public FOSSGIS OSRM, which allows about one request a second. An admin can point TREK at an OSRM of their own under **Admin → User Defaults** (**Own routing engine**, restart required); see [Road-Trip](Road-Trip#routing-engines).
The travel mode in the route bar offers **Driving** and **Walking**, each routed on the matching OSRM network. Installed plugins can add further profiles: a plugin with the `routeProvider` hook, for example an e-mobility plugin that plans charging stops, appears as an extra mode next to Driving and Walking. When such a profile is selected, that plugin computes the day's route: its geometry is drawn on the map, planned stops such as chargers appear as small dots on the line, and the connectors between the stops show the plugin's travel times plus any note it attaches ("25 min charge"). If the plugin fails or times out, TREK falls back to straight lines exactly as it does on an OSRM outage.
The travel mode in the route bar offers **Driving**, **Walking** and **Cycling**, each routed on the matching OSRM network (on the public servers `routed-car`, `routed-foot` and `routed-bike`; an own OSRM is asked under the profiles `driving`, `foot` and `bike`). Installed plugins can add further profiles: a plugin with the `routeProvider` hook, for example an e-mobility plugin that plans charging stops, appears as an extra mode next to the built-in ones. When such a profile is selected, that plugin computes the day's route: its geometry is drawn on the map, planned stops such as chargers appear as small dots on the line, and the connectors between the stops show the plugin's travel times plus any note it attaches ("25 min charge"). If the plugin fails or times out, TREK falls back to straight lines exactly as it does on an OSRM outage.
The mode you pick is the **day's** default. It is stored on the day, so each day of a trip can differ and the choice survives a reload.
A single leg can override the day default. With **Route** on, click the connector between two stops (*Change travel mode*) and pick **Driving**, **Walking** or a plugin profile for that leg alone, or **Use day default** to clear the override again. The same menu sits on the connectors to and from the day's accommodation and on the connector after a transport booking, where it sets the mode of the leg *arriving* at the next stop. Every connector shows the icon and the time of the mode its leg was actually drawn with.
A single leg can override the day default. With **Route** on, click the connector between two stops (*Change travel mode*) and pick **Driving**, **Walking**, **Cycling** or a plugin profile for that leg alone, or **Use day default** to clear the override again. The same menu sits on the connectors to and from the day's accommodation and on the connector after a transport booking, where it sets the mode of the leg *arriving* at the next stop. Every connector shows the icon and the time of the mode its leg was actually drawn with.
When the trip has a start and an end date and you may edit the day, that menu also carries **Public transit**. It opens the automated transit search (see [Transport-Flights-Trains-Cars](Transport-Flights-Trains-Cars)) already filled in with the leg's two endpoints and the departure time of the stop you are leaving.
Route segments reset at any transport booking (flight, train, car, bus or cruise) between two places: that leg is not driven or walked, so no ground route is drawn across it.
### Leaving a stop out of the route
A place can stay on its day without being part of the route: **Leave out of route** in the place's **…** menu in the day (on a phone, the route icon on the day's chip in the place sheet). The route then runs from the stop before it straight to the one after, the connectors skip it, and the row carries an **Off route** pill. **Add back to route** in the same menu undoes it. See [Leaving a stop out of the route](Day-Plans-and-Notes#leaving-a-stop-out-of-the-route).
### Counting routing requests
> **Admin:** counting is on by default. To switch it off, set `route_usage_enabled` to `false` in the `app_settings` table of the database; there is no screen for it.
@@ -42,7 +46,7 @@ Signed in as an admin, `GET /api/route-usage/summary` returns the totals, the re
## Route display
- The route runs through the day's stops on the map, in their planned order.
- The route runs through the day's stops on the map, in their planned order. Stretches routed for walking are drawn dashed, so they read apart from the drive.
- Between each pair of consecutive stops, a slim connector row in the day carries that leg's travel time and distance, with an icon for the mode it was routed in.
- Plugins can attach time entries to the day (planned charging time at a stop, a security buffer before a flight). They appear as slim rows under the place or booking they belong to, and their minutes add up to the **+X min** under the route bar.
+2
View File
@@ -39,6 +39,8 @@ TREK enforces a minimum password policy on all registrations and password change
- Common passwords and fully-repetitive strings are rejected
- Passwords are hashed with bcrypt (cost factor 12)
Every form that sets a password (registration, including through an invite link, the new password asked for on first login, the password reset, a password change in **Settings > Account**, and the admin's **Create User** and **Edit User** dialogs) lists these rules as a checklist under the field and ticks each one off while you type, using the server's own policy.
No configuration is required; this policy is always active.
## Rate Limiting
+4 -4
View File
@@ -38,9 +38,9 @@ Names are the ones the index has, which are the names used on the spot. The inde
| Booking imports, and stops given only by name in an imported Google Maps route | The coordinate of a venue, found by its name | OpenStreetMap's search service, which also resolves street addresses |
| Preparing a trip for offline use | Up to 3000 places around the trip, in one request | Nothing is cached, and offline search has nothing to answer from |
| MCP: `search_place` and `search_pois` | The same as the full search and the category buttons | The same fallbacks |
| Places near a point (**Nearby** in the add place dialog, `search_nearby_places`) | Named places of any kind around the point, nearest first | Google Places when the index has nothing and a key exists, OpenStreetMap otherwise |
| Places near a point (**Places near this pin** in the place form, `POST /api/maps/nearby`, `search_nearby_places`) | Named places of any kind around the point, nearest first | Google Places when the index has nothing and a key exists, OpenStreetMap otherwise |
Where Google holds the keyed slot (a Google key, with neither Amap nor OpenStreetMap picked as the places provider), two things skip the index and OpenStreetMap for a search: the **Search Google instead** line under a result list (`provider: 'google'` on `search_place`) sends that one search to Google Places alone, and the admin switch **Search with Google only** sends every search and every suggestion there, `search_place` included; the category buttons and `search_pois` keep asking the index. See [Google and Amap](Places-and-Search#google-and-amap).
Where Google holds the keyed slot (a Google key, with neither Amap nor OpenStreetMap picked as the places provider), two things skip the index and OpenStreetMap for a search: the **Search Google instead** line under a result list (`provider: 'google'` on `search_place`) sends that one search to Google Places alone, and the admin switch **Search with Google only** sends every search and every suggestion there, `search_place` and **Places near this pin** included; the category buttons and `search_pois` keep asking the index. See [Google and Amap](Places-and-Search#google-and-amap).
Right-click reverse geocoding on the map does not use it: that is OpenStreetMap's (or Amap's inside mainland China, when Amap holds the keyed slot).
@@ -76,9 +76,9 @@ Every request goes out from your TREK server, never from a browser, so the servi
The header carries an opaque token derived from your instance's own address, so the service can rate-limit each instance on its own instead of everyone behind one IP. Set `APP_URL` (or `ALLOWED_ORIGINS`): without either, the token is derived from the port alone, and two unconfigured installs on the same port share one rate-limit bucket.
Who is searching never goes along. No user, account, session, cookie or trip id is sent, and neither is the language TREK is set to. The service's own front page states that queries are not logged, that requests are counted per rate-limit bucket and nothing else, and that the instance token is not stored.
Who is searching never goes along. No user, account, session, cookie or trip id is sent, and neither is the language TREK is set to or the one picked under **Place names** (see [Language of place names](Places-and-Search#language-of-place-names)). The service's own front page states that queries are not logged, that requests are counted per rate-limit bucket and nothing else, and that the instance token is not stored.
The requests use Node's default HTTP client, so an outbound proxy set with `HTTPS_PROXY` applies to them; see [Environment Variables](Environment-Variables#outbound-https-proxy).
The requests use Node's default HTTP client, so an outbound proxy set with `HTTPS_PROXY` applies to them, and `NO_PROXY` can exempt the service's host. The official image already turns Node's environment proxy on; a source install needs `NODE_USE_ENV_PROXY=1` as well. See [Environment Variables](Environment-Variables#outbound-https-proxy).
The instance's own [Place Search Log](Places-and-Search#place-search-log) is a different thing: it is off by default, lives in your database and never leaves the instance.
+20 -17
View File
@@ -2,10 +2,8 @@
TREK has two independent labelling systems for places:
- **Global Place Categories** — admin-managed, shared across every user on the instance (e.g. `Restaurant`, `Museum`).
- **Personal Tags** — user-scoped labels (e.g. `hidden gem`, `kid-friendly`).
<!-- TODO: screenshot: tag list on place detail -->
- **Global Place Categories**: admin-managed, shared across every user on the instance (e.g. `Restaurant`, `Museum`).
- **Personal Tags**: user-scoped labels (e.g. `hidden gem`, `kid-friendly`).
## Global Place Categories
@@ -13,18 +11,23 @@ Categories classify places across all trips. Every user sees the same set of cat
**Fields per category:**
- **Name** — displayed in the place form and sidebar filter.
- **Color** — used for the colored icon background on map markers and in the places sidebar. Default: `#6366f1`.
- **Icon** — a Lucide icon name (e.g. `MapPin`, `Coffee`, `Mountain`). The UI form defaults to `MapPin`; the database-level fallback is the 📍 emoji, which is also resolved to the `MapPin` Lucide icon at render time.
- **Name**: displayed in the place form and sidebar filter.
- **Color**: used for the colored icon background on map markers and in the places sidebar. Default: `#6366f1`.
- **Icon**: a Lucide icon name (e.g. `MapPin`, `Coffee`, `Mountain`). The UI form defaults to `MapPin`; the database-level fallback is the 📍 emoji, which is also resolved to the `MapPin` Lucide icon at render time.
Categories appear in:
- The **place form** when adding or editing a place.
- The **places sidebar** as filter options.
- **Map markers** — the category icon and color are used to style each place's marker pin.
- **Map tooltips** — hovering a marker shows the category name and icon.
- **Map markers**: the category icon and color are used to style each place's marker pin.
- **Map hover cards**: resting the pointer on a marker shows the category with the place's name and address.
- **Saved places** in [Collections](Collections), which use the same set.
> **Admin:** Create and manage categories in [Admin-Categories](Admin-Categories). Only admins can create, edit, or delete categories. All users can read them.
A place picked from the search or from a marker of the map's category buttons comes with a matching category already picked, when the palette has one whose name or icon fits (a hotel goes to a category such as Hotel or Accommodation, a museum to Sights or Museum). Pick another one and it stays yours. See [The place form](Places-and-Search#the-place-form).
> **Admin:** Create and manage categories in [Admin-Categories](Admin-Categories), or create one on the spot with the **+** (*New category*) next to the category pill of the place form. Only admins can create, edit, or delete categories. All users can read them.
> **AI / MCP:** `list_categories` lists the palette; `create_category`, `update_category` and `delete_category` are for admins only.
## Personal Tags
@@ -32,20 +35,20 @@ Tags are personal labels owned by each user. They attach to individual places vi
**Fields per tag:**
- **Name** — free-form text.
- **Color** — hex value displayed alongside the tag name. Default: `#10b981` (emerald).
- **Name**: free-form text.
- **Color**: hex value displayed alongside the tag name. Default: `#10b981` (emerald).
Tags are owned by their creator, but only the *list* is private. `GET /api/tags` and the `list_tags` MCP tool return only your own tags, and tag names carry no uniqueness constraint, so different users — or even the same user — can create tags with identical names without conflict.
Tags are owned by their creator, but only the *list* is private. `GET /api/tags` and the `list_tags` MCP tool return only your own tags, and tag names carry no uniqueness constraint, so different users, or even the same user, can create tags with identical names without conflict.
A tag you attach to a place is **not** private. It becomes part of that place: the place read-back joins `place_tags` → `tags` with no owner filter, so every trip member gets it from `GET /api/trips/:id/places`, the day and assignment endpoints, and the MCP `list_places` tool and `trek://trips/{tripId}/places` resource — gated by trip access alone. The `?tag=` filter on the places list is likewise not user-scoped, so a member can filter by a co-traveller's tag ID. This is deliberate: a tag is kept as long as its owner is on the trip roster, so a co-traveller's tag is not silently stripped when another member re-saves the place. A tag owned by someone outside the trip is dropped instead.
A tag you attach to a place is **not** private. It becomes part of that place: the place read-back joins `place_tags` → `tags` with no owner filter, so every trip member gets it from `GET /api/trips/:id/places`, the day and assignment endpoints, and the MCP `list_places` tool and `trek://trips/{tripId}/places` resource, gated by trip access alone. The `?tag=` filter on the places list is likewise not user-scoped, so a member can filter by a co-traveller's tag ID. This is deliberate: a tag is kept as long as its owner is on the trip roster, so a co-traveller's tag is not silently stripped when another member re-saves the place. A tag owned by someone outside the trip is dropped instead.
If a trip has a public share link with the map/itinerary section enabled, the tags of places **scheduled on a day** also reach anonymous viewers — trimmed to the tag's ID, name and color, so the owner's user ID never leaves the server. Unscheduled places in the shared place pool carry no tags.
If a trip has a public share link with the map/itinerary section enabled, the tags of places **scheduled on a day** also reach anonymous viewers, trimmed to the tag's ID, name and color, so the owner's user ID never leaves the server. Unscheduled places in the shared place pool carry no tags.
In practice these tags surface through the API and MCP rather than in the app — no view renders a place's tags yet. Deleting a tag automatically removes it from every place it was attached to.
In practice these tags surface through the API and MCP rather than in the app: no view renders a place's tags yet. Deleting a tag automatically removes it from every place it was attached to.
### Where to manage them
At the moment tags are exposed primarily through the MCP API — AI assistants connected to your instance can list, create, update, and delete tags (`list_tags`, `create_tag`, `update_tag`, `delete_tag`) and attach them to places through the place endpoints. A dedicated web UI for tag management is not yet available; the filter `tag` parameter on the places API and on the MCP `list_places` tool does support filtering places by a tag ID once one exists (the `trek://trips/{tripId}/places` MCP resource only filters by `assignment`).
At the moment tags are exposed primarily through the MCP API: AI assistants connected to your instance can list, create, update, and delete tags (`list_tags`, `create_tag`, `update_tag`, `delete_tag`) and attach them to places through the place endpoints. A dedicated web UI for tag management is not yet available; the filter `tag` parameter on the places API and on the MCP `list_places` tool does support filtering places by a tag ID once one exists (the `trek://trips/{tripId}/places` MCP resource only filters by `assignment`).
> **AI / MCP:** See [MCP-Tools-and-Resources](MCP-Tools-and-Resources) for the full tag tool list.
+3 -1
View File
@@ -24,7 +24,7 @@ The to-do view has two columns, and a third while a task is open:
|---|---|
| Name | Required. |
| Done | The checkbox; ticks the task off. |
| Description | Optional free text. |
| Description | Optional text with Markdown (see below). |
| Priority | **None**, **P1**, **P2** or **P3**, picked on one segmented track. |
| List | Optional grouping. The sidebar heading is **Lists**, the button reads **Add list**, and a task without one shows **No list**. The **+** beside the field names a new list. |
| Due date | Optional date. |
@@ -32,6 +32,8 @@ The to-do view has two columns, and a third while a task is open:
Click a task row to open the detail pane, where every field can be changed. **Save changes** keeps them.
The description understands Markdown: bold text, lists and links render as such, in the task list (shortened to one line) and in the detail pane. In the detail pane a click on the text switches it back to the editing box (the tooltip reads *Click to edit, links open directly*); a click on a link opens the link instead. An empty description is the editing box straight away.
## Priority levels
| Level | Label | Colour |
+14 -4
View File
@@ -24,6 +24,7 @@ Transport records live on the **Transports** tab and never on the [Bookings](Res
The tab works exactly like the Bookings tab: the same bar with search, **Filter**, the **Cards**, **List** and **Timeline** views and **View options**, the same cards and the same detail popup. [Reservations-and-Bookings](Reservations-and-Bookings#views) describes them. A few things are specific to transports:
- The bar also holds **Import from AirTrail** (the plane icon) when the AirTrail addon is on.
- **Export as spreadsheet (CSV)** saves the filtered transports as a CSV, with the first and last stop of each route under **From** and **To**. See [Exporting as CSV](Reservations-and-Bookings#exporting-as-csv).
- Cards show the whole route, stop by stop, with the type's icon between the stops, and **Segment codes** when the legs of a connection have their own codes.
- Public transit journeys have no status. They are tinted blue, and in the cards view they sit among the confirmed entries in time order. **View options → Public transit as its own section** gives them a section of their own, **Automated public transit**. The list always does that when it is grouped by status.
- On the timeline, **Show the other tab** draws the Bookings tab's entries in a dimmed lane at the top.
@@ -44,9 +45,9 @@ Until the title has something in it, the line under it marks the title as requir
## Transport types
Nine types are created in the editor: **Flight**, **Train**, **Bus**, **Car**, **Taxi**, **Bicycle**, **Cruise**, **Ferry** and **Other**. A tenth, **Public transit**, only comes from the public transit search.
Ten types are created in the editor: **Flight**, **Train**, **Bus**, **Car**, **Taxi**, **Bicycle**, **Cruise**, **Ferry**, **Cable car** and **Other**. **Cable car** covers gondolas and aerial cableways and has its own icon. An eleventh type, **Public transit**, only comes from the public transit search.
> **AI / MCP:** `create_transport` accepts the same nine. Scheduled public transit is its own tool: `create_transit_journey` attaches the provider's itinerary. See [MCP-Tools-and-Resources](MCP-Tools-and-Resources).
> **AI / MCP:** `create_transport` accepts the same ten. Scheduled public transit is its own tool: `create_transit_journey` attaches the provider's itinerary. See [MCP-Tools-and-Resources](MCP-Tools-and-Resources).
## Common fields
@@ -66,6 +67,10 @@ Every transport has these fields, whatever its type:
When editing, the foot of the dialog also has **Delete**, which asks once before it removes the transport.
If you have changed something and then press Escape or click beside the dialog, TREK asks *Discard your changes?* first: **Keep editing** returns to the form, **Discard** closes it without saving.
The notes of a transport also print in the [trip PDF](PDF-Export). The PDF preview has a **Transport notes** switch to leave them out.
## Routes
### Flights
@@ -80,6 +85,10 @@ Trains use the same rail, with stations instead of airports. Search each station
Trains saved before the multi-leg editor existed still open fine: their train number, platform and seat are read as a single leg.
### Cruises
A cruise uses the same rail as a train, with ports instead of stations. The first stop is **Embarkation**, the last **Disembarkation**, and **Add port** between two of them inserts a **Port of call**. Every port the ship arrives at has **Arrival** and **Arr. time**, every port it leaves from **Departure** and **Dep. time**, so a port of call carries both. A cruise has no train number, platform or seat.
### Cars, buses and everything else
The other types have a single **From** and **To**. The location picker offers the trip's own places before you type; type at least three characters to search, and pick one of the results. A name that is only typed and never picked is not saved.
@@ -94,7 +103,7 @@ The **Automated** mode searches real public transit connections, by default thro
The head band reads **Public transit** and holds a day pill: the search runs for that day. Then:
1. Pick **From** and **To**. The day's own places and hotels are offered as quick picks, and any stop or station can be searched. **Swap** turns the two around.
1. Pick **From** and **To**. Quick picks are offered before you type: first the day's accommodation, then the airports, stations and ports the day's flights, trains, buses, ferries and cruises leave from or arrive at, then the day's own places. Any stop or station can be searched as well. **Swap** turns the two around.
2. Choose **Depart** or **Arrive** and the time.
3. Narrow the modes if you like: Train, Subway, Tram, Bus, Ferry, Cable car.
4. Rank the results by **Best route**, **Fewer transfers** or **Less walking**, and click **Search**.
@@ -126,6 +135,7 @@ A transport with both ends set can be drawn as a line on the trip map:
- **Flights**, **cruises** and **ferries** follow a great-circle curve, the way they actually travel across the globe.
- **Cars**, **buses**, **taxis** and **bicycles** follow real roads, routed on demand through a public OSRM router (driving for car, bus and taxi, cycling for the bicycle). A straight line shows while the route loads, and stays when routing fails or the distance is over about 2000 km.
- **Trains** are drawn as a straight line through all their stations.
- **Cable cars** are drawn as a straight line from the valley to the mountain station, the way the rope runs.
- **Public transit** journeys follow their real rail and bus lines, each ride in its line's own colour and the walks between them as a dotted grey line. A journey the provider sent no shape for falls back to a straight line. A journey is also drawn whenever its day's **Route** is switched on, so it has no route button of its own in the day plan.
Confirmed transports get a solid line, pending ones a dashed line. Each end carries a pill-shaped marker with the transport's icon; click it to open the detail. Turn on **Booking route labels** (Settings → General → Travel & map) to print the airport code or station name in the pill as well, once the two ends are far enough apart on screen.
@@ -134,7 +144,7 @@ Lines are off until you ask for them: the route button on a transport's row in t
## In the day plan
A transport shows up on its day as a row between the stops, tinted with its type's colour, with its time as a badge and its route or carrier underneath. A ride that runs over several days appears on each of them with a label for the phase:
A transport shows up on its day as a row between the stops, tinted with its type's colour, with its time as a badge and its route or carrier underneath. When a departure or arrival has a time zone, a small globe after the time names it on hover. A ride that runs over several days appears on each of them with a label for the phase:
| Type | First day | Days in between | Last day |
|------|-----------|-----------------|----------|
+5 -3
View File
@@ -25,13 +25,13 @@ If you have the `member_manage` permission (default: trip owner), an invite cont
Click the remove icon next to any member's name (**Remove access**). TREK asks first, in a dialog over the Share dialog, and removes the member only on **Confirm**.
If you click the remove icon next to **your own** name, the action is labeled **Leave trip** and uses a "log out" icon. Leaving reloads the page and returns you to the dashboard.
If you click the remove icon next to **your own** name, the action is labeled **Leave trip**, and the same dialog asks *Leave trip? You will lose access.* before anything happens. Leaving reloads the page and returns you to the dashboard.
The trip owner cannot be removed through this panel.
### Transferring Ownership
Only the current owner sees a crown button next to each non-owner member. Click it and confirm the prompt — that member becomes the trip owner, you drop to a regular member, and the page reloads so the new permissions take effect everywhere.
Only the current owner sees a crown button (**Make owner**) next to each non-owner member. Click it and press **Confirm** in the dialog that asks *Transfer ownership to (name)? You will become a regular member.*; on confirm that member becomes the trip owner, you drop to a regular member, and the page reloads so the new permissions take effect everywhere.
Guests are never listed among the members, and the server refuses to hand ownership to one.
@@ -74,7 +74,7 @@ These limits are enforced on the server, not just hidden in the UI.
### Renaming and removing
In the owner's Guests section, each guest row has a **Rename** (pencil) and a **Remove access** (trash) button. Rename turns the name into a field: Enter saves, Escape leaves it as it was. Removing a guest is **destructive and cascading**, so TREK asks before it deletes:
In the owner's Guests section, each guest row has a **Rename** (pencil) and a **Remove access** (trash) button. Rename turns the name into a field: Enter saves, Escape leaves it as it was. Removing a guest is **destructive and cascading**, so TREK asks in a dialog before it deletes, and removes the guest only on **Delete**:
> Remove this guest? Their assignments and cost shares will be removed too.
@@ -112,6 +112,8 @@ Before or after creating the link, you can control what the link exposes. Toggle
Changes to toggles take effect immediately for an existing link.
Under **Options**, two more switches narrow what the link shows: **Travel & stays only** (only transport and accommodation, without activities, day notes and empty days) and **Without photos** (the place photos are left out of the shared page). See [Public-Share-Links](Public-Share-Links#options).
### Deleting a Link
Click **Delete link** (red button below the URL) to revoke access. The token is invalidated; anyone who opens the old URL now sees *Link expired or invalid*.
+10 -8
View File
@@ -17,10 +17,10 @@ On a desktop or a tablet (768 px and wider) the **Plan** tab has three parts:
```
- **Days** on the left: the trip day by day. Every day is a card with its places, bookings, transports and notes. See [Day Plans and Notes](Day-Plans-and-Notes).
- **Map** in the centre: the places of the trip, the route of the selected day and the booking routes you switched on. See [Map Features](Map-Features).
- **Map** in the centre: the places of the trip, the route of the selected day and the booking routes you switched on. The lock on the map (*Lock the map view*) keeps the view where it is, so picking a day or a place no longer zooms or pans; click it again to let the map follow the selection. See [Map Features](Map-Features).
- **Places** on the right: every place of the trip, with search, filters, import and a select mode. See [Places and Search](Places-and-Search).
The two side columns float over the map. Drag the inner edge of a column to make it wider or narrower. The small tab on its edge tucks the column away, and a tucked column leaves a tile named **Plan** or **Places** at the edge of the map that brings it back.
The two side columns float over the map. Drag the inner edge of a column to make it wider or narrower. On a tablet the edge follows a finger as well and shows a grip, also in the narrower portrait layout, and with the keyboard focus on it the arrow keys change the width. The small tab on its edge tucks the column away, and a tucked column leaves a tile named **Plan** or **Places** at the edge of the map that brings it back.
Two panels open over the map, centred between the columns:
@@ -38,23 +38,23 @@ The tab bar sits directly below the main navigation bar.
| Tab | What it holds |
|---|---|
| **Plan** | Days, map and places, as described on this page. Always shown. |
| **Transports** | Flights, trains, buses, cars, taxis, bicycles, ferries, cruises and public transit, as cards, a list or a timeline. See [Transport: Flights, Trains, Cars](Transport-Flights-Trains-Cars). |
| **Transports** | Flights, trains, buses, cars, taxis, bicycles, ferries, cruises, cable cars and public transit, as cards, a list or a timeline. See [Transport: Flights, Trains, Cars](Transport-Flights-Trains-Cars). |
| **Bookings** | Stays, restaurants, events, tours, parking and other bookings, in the same three views. See [Reservations and Bookings](Reservations-and-Bookings). |
| **Lists** | Packing list and to-dos. See [Packing Lists](Packing-Lists) and [Todos and Tasks](Todos-and-Tasks). |
| **Costs** | Expenses, splits and settling up. See [Costs](Budget-Tracking). |
| **Costs** | Expenses, splits and settling up, as a list or a table. See [Costs](Budget-Tracking). |
| **Files** | Tickets, receipts and other documents. See [Documents and Files](Documents-and-Files). |
| **Collab** | Chat, shared notes, polls and What's Next. See [Real-Time Collaboration](Real-Time-Collaboration). |
> **Admin:** The **Lists**, **Costs**, **Files** and **Collab** tabs only appear when the matching addon is enabled. See [Admin-Addons](Admin-Addons).
The active tab is saved in `sessionStorage` per trip, so switching between trips brings you back to where you were.
The active tab is saved in `sessionStorage` per trip, so switching between trips brings you back to where you were. The installed app (PWA) goes further: after the system closed it, it reopens on the trip and the tab it was on, and on a phone on the plan day as well.
## Bookings on the plan
A booking or transport opens its detail first, wherever you click it on the Plan tab:
- a booking or transport row in a day,
- a rental car pill in a day's head band,
- a rental car pill in a day's head band, or the ticket at the end of a stay pill there (*Open booking*),
- a booking in the day details panel, including the booking box of a stay,
- a booking card in the place inspector,
- an endpoint of a booking route on the map,
@@ -68,9 +68,11 @@ The detail shows status, type and day, the booking code with a copy button, the
Every dialog of a trip shares one frame. The head band carries an icon tile, a small line that says what the dialog does (for example **Edit Place** or **Add accommodation**), the name, and pills for facts such as the status, the type or the category. In the dialogs for a place, a booking, a transport or a note, the name is a field: you type it straight into the band. **Cancel** and the save button sit in the footer. **Escape** or the **X** in the head band closes the dialog without saving.
When a dialog opens, the focus moves inside it (on a desktop into its first field), and **Tab** stays inside until it closes. In the dialogs for a place, a booking and a transport, a stray click beside the dialog or **Escape** no longer throws away what you typed: once something has changed, TREK asks *Discard your changes?* with **Keep editing** and **Discard**.
## Undo
The planner keeps your recent actions in a short undo ring: adding, deleting and importing places, putting them on a day, taking them off, moving them to another day, reordering, optimizing a route, locking a place and changing categories. The **Undo** button (a curved arrow) sits in the head band of the days column. It is greyed out until there is something to undo, its tooltip names the last action (*Undo: Route optimized*), and a click reverses it.
The planner keeps your recent actions in a short undo ring: adding, deleting and importing places, putting them on a day, taking them off, moving them to another day, reordering, optimizing a route, clearing a day, locking a place and changing categories. The **Undo** button (a curved arrow) sits in the head band of the days column. It is greyed out until there is something to undo, its tooltip names the last action (*Undo: Route optimized*), and a click reverses it.
Deleting a day is not in the ring. The question before the delete lists what goes with the day instead; see [Deleting a day](Day-Plans-and-Notes#deleting-a-day). An earlier reorder of the days can still be undone afterwards, minus the day that is gone.
@@ -91,7 +93,7 @@ In the Road trip view, **Edit** on a stop on the way or on a booked night opens
## Mobile layout
On screens narrower than 768 px, TREK does not squeeze the three columns together. It opens a dedicated trip screen instead: a rail of day chips under the top bar, a switch between the day plan and a full-screen map, and a dock at the bottom for the other tabs.
On screens narrower than 768 px, TREK does not squeeze the three columns together. It opens a dedicated trip screen instead: a rail of day chips under the top bar, a switch between the day plan and a full-screen map, and a dock at the bottom for the other tabs. While a trip is running, today's chip is marked, and a button beside the rail (*Jump to today*) scrolls back to it, in the plan and on the map. Reopening a trip selects a day again instead of showing an empty plan.
## Splash screen
+19 -2
View File
@@ -147,6 +147,21 @@ Keep the proxy's `client_max_body_size` at or above `BACKUP_UPLOAD_LIMIT_MB`. No
---
## File upload refused: "File is too large"
**Cause:** A file uploaded to a trip, a booking or a collab note is capped at 50 MB by default. The Files tab refuses a bigger file before the upload starts with `File is too large (max 50 MB)`, and the server answers the same check with `400 File is too large`. Videos have their own 500 MB cap, and trip covers and place images 20 MB. If the upload instead fails with a `413` or without any message, your reverse proxy refused the request body before TREK saw it.
**Fix:** Raise the limit with `FILE_UPLOAD_LIMIT_MB` and restart:
```yaml
environment:
- FILE_UPLOAD_LIMIT_MB=200 # in MB (default: 50)
```
Keep the proxy's body limit (`client_max_body_size` on nginx) at or above that value. On Helm the chart does not pass this variable through, so patch it onto the Deployment. See [Environment Variables](Environment-Variables#storage--paths) and [Reverse Proxy](Reverse-Proxy).
---
## "Cannot find module" on startup
**Likely cause:** A volume is mounted at `/app`, which hides the application code (`node_modules` and `dist`) shipped inside the image. Mount only the data and uploads directories — `-v ./data:/app/data -v ./uploads:/app/uploads` — never `/app` itself. Current images detect this before Node starts and print `FATAL: TREK application files are missing from the image.` instead of the bare module error.
@@ -367,13 +382,15 @@ If `ALLOWED_ORIGINS` is not set, the default is **same-origin only** — cross-o
**Cause:** The browser Clipboard API (`navigator.clipboard`) is only available in a [secure context](https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts), so on plain HTTP at a non-localhost address it is undefined.
TREK works around this where it matters most. The share-link and invite-link buttons in the trip **Members** dialog, the journey share link, and the calendar-subscribe URLs fall back to a hidden textarea plus the deprecated `document.execCommand('copy')`, which is not secure-context gated — **those keep working over plain HTTP**, on desktop and mobile alike.
TREK works around this where it matters most. The share-link and invite-link buttons in the trip's **Share Trip** and **Members** dialogs, the journey share link, and the calendar-subscribe URLs fall back to a hidden textarea plus the deprecated `document.execCommand('copy')`, which is not secure-context gated, so **those keep working over plain HTTP**, on desktop and mobile alike.
The remaining copy buttons call `navigator.clipboard` directly and have no fallback:
- **Settings > Integrations (MCP)** — the MCP endpoint URL, the JSON client config, a newly created MCP token, and OAuth client IDs, client secrets and rotated secrets. These fail with no message at all, because the click handler throws before any toast is shown.
- **Settings > Account** — the 2FA backup codes. This one shows a generic error toast. Use the **Download** button next to it as a workaround; it does not need a secure context.
- **Admin Panel > Users & Invites** — the registration invite link, both on create ("create and copy") and via the copy button on an existing invite.
- **Admin Panel > Users** (the **Invite Links** card): the registration invite link, both on create ("create and copy") and via the copy button on an existing invite.
- The copy button next to a booking's confirmation code in the booking's detail popup. It shows `Could not copy`.
- The webhook URL of a [Document-Sync](Document-Sync) connection in the Files tab.
**Fix:** For those buttons, one of:
+1 -1
View File
@@ -13,7 +13,7 @@ Go to **Settings → Account**, find the **Two-factor authentication (2FA)** sec
1. A QR code and a text secret are displayed. Scan the QR code with your authenticator app.
> **Note:** The setup session expires after **15 minutes**. If you do not complete setup within that window, start again.
2. Enter the 6-digit code shown in your authenticator app and click **Enable 2FA**.
3. Save your **10 backup codes**. These are single-use codes shown only once — store them somewhere safe (a password manager, printed paper). Each code has the format `XXXX-XXXX`.
3. Save your **10 backup codes**. These are single-use codes shown only once, so store them somewhere safe (a password manager, printed paper). Each code has the format `XXXX-XXXX`. The **Backup codes** box offers **Copy codes**, **Download TXT** and **Print / PDF**.
4. 2FA is now active on your account.
## Logging in with 2FA
+1 -1
View File
@@ -4,7 +4,7 @@ How to update TREK to a newer version without losing data.
## Before You Update
Back up your data first. Go to Admin Panel → Backups and create a manual backup, or copy your `./data` and `./uploads` directories to a safe location. See [Backups](Backups) for details.
Back up your data first. Go to Admin Panel → **Backup** and create a manual backup, or copy your `./data` and `./uploads` directories to a safe location. See [Backups](Backups) for details.
## Image Tags
+11 -4
View File
@@ -1,18 +1,22 @@
# User Settings
The Settings page lets you personalise every aspect of TREK — appearance, maps, notifications, offline behaviour, and your account.
The Settings page lets you personalise TREK: appearance, maps, notifications, offline behaviour and your account.
## Navigating to Settings
Open the user menu in the top navigation bar and select **Settings**. The page opens on the **General** tab by default.
On desktop the tabs are a side navigation on the left and each tab is a set of cards: one card per group of settings, with a switch, segmented control or dropdown at the end of each row. Anything that cannot be undone (deleting your account, removing a passkey, clearing the offline cache) asks for confirmation in TREK's own dialog. On a phone the same settings open as the mobile settings screens.
A link can open a tab directly with `?tab=`, for example `/settings?tab=notifications`.
If your account requires MFA setup, TREK redirects you directly to the **Account** tab (via `?mfa=required`).
## Tabs
| Tab | Purpose | Shown when |
|-----|---------|------------|
| General | Start page and start tab, currency, language, temperature unit, distance unit, time format, week start, booking route labels, always show booking routes, map POI pills, blur booking codes, and optimize route from accommodation | Always |
| General | Start page and start tab, display currency, language, place names, temperature unit, distance unit, time format, week start, the map app places open in, date first in day headings, booking route labels, always show booking routes, compact markers for unplanned places, explore places on the map, blur booking codes, and optimize route from accommodation | Always |
| Appearance | Color mode, color scheme / accent, readability (transparency, reduce motion, density, text size), and which widgets appear on your dashboard | Always |
| Map | Map provider (Leaflet, Mapbox GL, or MapLibre GL), tile presets, map style and Mapbox token, 3D buildings, high-quality mode | Always |
| Notifications | Email, webhook, ntfy, push and in-app notification preferences, plus switching push on or off for this device (every device is switched on separately) | Always |
@@ -33,7 +37,7 @@ The General tab controls the following preferences, all saved immediately on cha
**Language & region**
- **Currency** — your display currency; **Trip currency** (the default) shows each trip in its own. See [Currencies](Currencies).
- **Display currency**: your display currency; **Trip currency** (the default) shows each trip in its own. See [Currencies](Currencies).
- **Language** — displayed as a button grid on desktop and a dropdown on mobile.
- **Place names**: the language place search, suggestions and addresses answer in. **Same as the app** follows the language above; picking another one keeps the interface as it is and asks for place names in that language. Where a place has no name in it, the local name is shown.
- **Temperature unit** — Celsius (°C) or Fahrenheit (°F).
@@ -43,8 +47,11 @@ The General tab controls the following preferences, all saved immediately on cha
**Travel & map**
- **Open places in**: the map app the navigate buttons open straight away, or **Ask every time** (the default) for the full list.
- **Date first in day headings**: lead each day in the day plan with its date and show "Day 1" or the day's title next to it.
- **Booking route labels** — show or hide station / airport names on booking route endpoint markers.
- **Always show booking routes** — draw the route for every flight, train and other booking on the map automatically, instead of switching it on per item.
- **Compact markers for unplanned places**: places not planned into any day show as small markers without a photo.
- **Explore places on the map** — show a POI category pill on the trip map for finding nearby places from OpenStreetMap.
- **Blur booking codes** — blur confirmation codes and reference numbers (useful when screen-sharing).
- **Optimize route from accommodation** — when optimizing a day, start the route at the hotel you wake up in and end it at the one you check into that evening.
@@ -83,7 +90,7 @@ Each GL provider keeps its own saved style, so switching between Mapbox GL and M
The Account tab lets you:
- Edit your **username** and **email address**.
- Change your **password** (hidden when the server runs in OIDC-only mode — see [OIDC-SSO](OIDC-SSO)).
- Change your **password** (hidden when the server runs in OIDC-only mode, see [OIDC-SSO](OIDC-SSO)). The password rules are shown as a checklist under the new password and tick off as you type.
- Set up or disable **two-factor authentication** (TOTP). After enabling MFA, backup codes are shown once and can be copied, downloaded, or printed. See [Two-Factor-Authentication](Two-Factor-Authentication).
- Manage your **passkeys** — add one (confirm your password, then follow your device prompt), rename it, or remove it. **Add a passkey** only appears when the instance has passkeys switched on and a WebAuthn domain resolves; an existing passkey stays listed either way so you can always clean it up. See [Passkeys](Passkeys).
- Upload or remove your **profile avatar**.
+3 -1
View File
@@ -48,6 +48,8 @@ Days that overlap with any of your existing TREK trips are marked with a small b
You can also switch the calendar toolbar to **Company** mode to mark shared company holidays, which are highlighted in amber and do not deduct from personal allowances.
A company holiday can be a half day too (a free afternoon, say): switch on **Half day** while in **Company** mode before clicking the day. A half company holiday is drawn half filled and leaves room for half a day of leave, so a vacation day logged on it costs only 0.5. Clicking the same day with the same size again removes the company holiday, and the other size converts it. Turning a day into a whole company holiday removes any leave logged on it; making it a half one shortens a full day of leave to a half.
### Half days and comp days
Two toggles in the toolbar change what a click logs. They are independent, so they combine:
@@ -60,7 +62,7 @@ Each toggle's icon in the toolbar is the marker it places, so you can see what a
**Settings** (gear icon) let you configure:
- **Block weekends** — prevents logging on weekend days. You choose which days count as the weekend.
- **Week start** — Monday or Sunday. This one is per plan and applies to the Vacay calendar only; every other calendar in TREK follows **Week starts on** under Settings → General.
- **Week starts on**: Monday or Sunday. This one is per plan and applies to the Vacay calendar only; every other calendar in TREK follows **Week starts on** under Settings > General > Language & region.
- **Carry-over** — toggle as described above.
- **Vacation year** — Calendar, Fiscal or Hire date, as described under Leave year above. Unlike the rest of this panel it is personal to you rather than to the plan.
- **Company holidays** — enable a shared company holiday layer that any fused user can edit.
+2 -2
View File
@@ -26,14 +26,14 @@ A day without a date, or without a place to take the weather from, has no weathe
| Date range | Data source | Cache |
|---|---|---|
| From yesterday up to 16 days ahead | Open-Meteo forecast API | 1 hour |
| More than a day in the past | Open-Meteo archive API (actual historical data), for the reading on the day card. The day details ask the forecast API for past days too | 24 hours (1 hour in the day details) |
| More than a day in the past | Open-Meteo archive API (actual historical data), for the reading on the day card and for the day details. The archive lags a few days behind, so for a recent day it cannot answer yet the day details fall back to the forecast API | 24 hours (1 hour for a day details reading from the forecast API) |
| More than 16 days ahead | Climate estimate from the same date a year earlier | 24 hours |
Climate estimates carry a **Ø** in front of the temperature (for example *Ø 18°C*), so they are never mistaken for a real forecast, and the day details add a line saying that a real forecast is available within 16 days of the date. The reading on the day card fetches again quietly in the background when a cached climate estimate could be upgraded to a live forecast.
## Temperature and wind units
Temperature follows your setting in [Display-Settings](Display-Settings): switch between °C and °F there. Wind speed is shown in km/h with °C and in mph with °F.
Temperature follows **Temperature Unit** under Settings > General > Language & region (see [Display-Settings](Display-Settings)): switch between °C and °F there. Wind speed is shown in km/h with °C and in mph with °F.
## Session cache
+3
View File
@@ -96,12 +96,15 @@
## Admin Panel
- [[Admin Panel Overview|Admin-Panel-Overview]]
- [[Admin: Users and Invites|Admin-Users-and-Invites]]
- [[Admin: User Defaults|Admin-User-Defaults]]
- [[Admin: Settings|Admin-Settings]]
- [[Admin: Addons|Admin-Addons]]
- [[Admin: Categories|Admin-Categories]]
- [[Admin: Packing Templates|Admin-Packing-Templates]]
- [[Admin: Permissions|Admin-Permissions]]
- [[Admin: Plugins|Admin-Plugins]]
- [[Admin: Storage|Admin-Storage]]
- [[Admin: Notifications|Admin-Notifications]]
- [[Admin: MCP Tokens|Admin-MCP-Tokens]]
- [[Admin: GitHub Releases|Admin-GitHub-Releases]]