Configuration
Traverse is configured in two places: environment variables for the deployment, and per-world settings edited in the admin console.
Environment variables
PORT=3000
DATABASE_URL="mysql://user:password@localhost:3306/traverse"
ADMIN_EMAIL="admin@example.com"
ADMIN_PASSWORD="change-me"
PLUGIN_API_KEY="change-me"
SESSION_SECRET="change-me"
PUBLIC_BASE_URL="https://traverse.example.net"
| Variable | Required | Purpose |
|---|---|---|
PORT | no | Port the server listens on. |
DATABASE_URL | yes | MySQL connection string used by Prisma. |
ADMIN_EMAIL / ADMIN_PASSWORD | seed only | Credentials for the admin user created by npm run seed. Change the password after first login. |
PLUGIN_API_KEY | yes | Shared secret the Paper plugin authenticates with. Must match the plugin's api-key. |
SESSION_SECRET | yes | Signs admin session cookies. Must be at least 32 bytes; the server refuses to start otherwise. |
PUBLIC_BASE_URL | yes | The app's public root. Access links are built from it, and it decides whether cookies are marked secure. The server refuses to start without it. |
Generate a session secret with:
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
:::note Why the base URL controls cookie security
Secure cookies are dropped by browsers on plain HTTP origins, and WebKit enforces that even on localhost. Traverse derives the secure flag from PUBLIC_BASE_URL's scheme, so an HTTP dev origin keeps working and Safari clients are not silently signed out.
:::
Access tokens appear in the URL path of /access/:token, so the request logger redacts that segment. Keep that in mind if you add your own logging or proxy access logs in front of the app.
World settings
A world is one campaign: one seed, one qualification rule, one time window, one set of search constraints. Everything below is edited per world in the admin console.
Identity
| Setting | Default | Meaning |
|---|---|---|
name | - | Display name shown to supporters. |
seed | - | The Minecraft world seed. Locks once previews or claims exist for the world. |
minecraftVersion | MC_1_21_3 | Which generator the biome engine uses. See Installation. |
enabled | true | Turning this off puts the world in DISABLED and stops all access. |
startAt / endAt / timezone | now / now / UTC | The campaign window. Before startAt the world is SCHEDULED, after endAt it is ENDED, in between it is ACTIVE. Only an ACTIVE world issues access. |
Qualification
| Setting | Default | Meaning |
|---|---|---|
qualificationMode | PERMISSION | PERMISSION matches against permission nodes; GROUP matches against LuckPerms group names. |
qualificationValues | [] | The list of nodes or groups that qualify. Any one match is enough. Comparison is case insensitive. |
Server operators bypass this check.
Search area
| Setting | Default | Meaning |
|---|---|---|
originX / originZ | 0 | Candidate draws radiate from this point. |
minimumSearchDistance | 0 | Nothing is offered closer than this to the origin. |
maximumSearchDistance | 20000 | Nothing is offered further than this. This is the knob that actually controls search spread. |
borderEnabled | false | Whether the world border is enforced as an outer cap. |
borderCenterX / borderCenterZ / borderSize | 0 / 0 / 60000000 | The square border. |
borderSafetyMargin | 32 | Extra blocks a plot must stay inside the border by. |
:::caution Do not raise the maximum search distance to match a huge border
Candidates are drawn uniformly in distance, not in area. borderSize defaults to the vanilla maximum of 60,000,000, and stretching the search across that would make draws so sparse they essentially never land in any biome cluster. Keep maximumSearchDistance at the distance you actually want supporters spread over; the border only acts as a safety cap when it is the smaller of the two.
:::
Keep-out rules
| Setting | Default | Meaning |
|---|---|---|
spawnEnabled | true | Whether the spawn keep-out is enforced. |
spawnX / spawnZ / spawnRadius | 0 / 0 / 500 | The protected spawn area. |
spawnBuffer | 100 | Extra clearance between a plot and that area. |
minimumSelectionGap | 200 | Minimum blocks between a new plot and any existing claim. |
minimumPreviewCandidateSeparation | 300 | Minimum blocks between two candidates in the same supporter's set, so their options are genuinely different places. |
Exclusion zones are managed separately; see the Admin Guide.
Match quality thresholds
| Setting | Default | Meaning |
|---|---|---|
minimumCombinedCoveragePct | 70 | How much of the plot must be covered by the requested landscapes in total. |
minimumConnectedCoveragePct | 20 | How much must be one connected piece rather than scattered fragments. |
maximumAdjacencyGapBlocks | 32 | With a secondary selector, how far apart the two landscapes may sit. |
minimumSingleBiomeCoveragePct | 70 | Coverage floor for a single-selector search. |
minimumPrimaryCoveragePct | 25 | Coverage floor for the primary in a two-selector search. |
minimumSecondaryCoveragePct | 25 | Coverage floor for the secondary. |
Raising these gives purer plots and fewer results. Lowering them finds more, scruffier ones. See How Matching Works.
Previews
| Setting | Default | Meaning |
|---|---|---|
previewCount | 3 | How many candidates a supporter is offered. |
previewHalo | 150 | Extra blocks rendered around the plot on the preview map. |
previewZoomOutFactor | 1.6 | How far the preview zooms out, so the image cannot be matched to a coordinate. |
Copy shown to supporters
| Setting | Meaning |
|---|---|
heroPhrase | Headline on the supporter welcome screen. |
welcomeDescription | Body text under it. |
dialogTitle / dialogMessage | The in-game onboarding dialog. Both must be set, or the dialog never shows. |
dialogYesLabel / dialogNoLabel | Button labels, defaulting to "Yes" and "No". |
notificationMode / notificationCooldownMinutes | How often a qualifying player is reminded. |
Instance settings
Separate from any world, the admin console holds instance-wide settings:
| Setting | Meaning |
|---|---|
discordWebhookUrl | Webhook that support requests are relayed to. |
discordWebhookEnabled | Whether that relay is on. |
Biome categories
Categories are per world and per version, and are what supporters see alongside individual biomes. Each is a name plus a list of biome names, for example a "Forests" category grouping every forest variant. A supporter picking a category matches any member of it.
Token and session lifetimes
| Item | Lifetime | Notes |
|---|---|---|
| Plugin access token | 15 minutes | Single use. Hashed at rest; the raw value only exists in the link. |
| Access code | 24 hours | Single use. Issuing a new one revokes any earlier active code for that entitlement. |
| Redemption session | 3 days | The supporter's browser session cookie. |
These are fixed in the application, not configurable.