Configuration
All Zander components share a small set of configuration files. This page is a complete reference for every variable and option across the web platform and each Minecraft plugin.
Web Platform (zander-web)
Environment Variables (.env)
Copy .env.example to .env and populate the following values:
| Variable | Required | Description |
|---|---|---|
PORT | No | HTTP port (default: 8080) |
siteAddress | Yes | Public base URL, e.g. https://example.com |
TZ | No | Timezone (default: Australia/Sydney) |
sessionCookieSecret | Yes | Random string, 32+ characters |
DATABASE_URL | Yes | MySQL connection string for the main database |
LUCKPERMS_URL | Yes | MySQL connection string for the LuckPerms database |
QUICKSHOP_URL | No | MySQL connection string for QuickShop (shop directory feature) |
apiKey | Yes | API key used by Minecraft plugins to authenticate |
discordAPIKey | Yes | Discord bot token |
discordClientId | Yes | Discord OAuth2 application client ID |
discordClientSecret | Yes | Discord OAuth2 application client secret |
twitchClientId | No | Twitch OAuth2 client ID (Watch feature) |
twitchClientSecret | No | Twitch OAuth2 client secret (Watch feature) |
googleClientId | No | Google OAuth2 client ID (YouTube Watch feature) |
googleClientSecret | No | Google OAuth2 client secret (YouTube Watch feature) |
youtubeApiKey | No | YouTube Data API v3 key (Watch feature) |
VAPID_SUBJECT | No | Contact email for web push notifications |
VAPID_PUBLIC_KEY | No | Web push VAPID public key |
VAPID_PRIVATE_KEY | No | Web push VAPID private key |
config.json
Copy config.json.example to config.json. Key sections:
{
"debug": false,
"siteConfiguration": {
"siteUrl": "https://example.com",
"siteName": "My Network",
"tagline": "...",
"email": "support@example.com",
"googleTag": "G-XXXXXXXXXX",
"policy": {
"termsOfService": "https://...",
"rules": "https://...",
"privacy": "https://...",
"refund": "https://..."
},
"platforms": {
"webstore": "https://...",
"discord": "https://discord.com/invite/...",
"issueTracker": "https://..."
}
},
"discord": {
"guildId": "YOUR_GUILD_ID",
"supportPanelChannelId": "CHANNEL_ID",
"supportTicketCategoryId": "CATEGORY_ID",
"botChannelId": "CHANNEL_ID",
"webhooks": {
"welcome": "WEBHOOK_URL",
"networkChatLog": "WEBHOOK_URL",
"adminLog": "WEBHOOK_URL",
"staffChannel": "WEBHOOK_URL",
"staffAuditLog": "WEBHOOK_URL",
"staffPunishmentNotifications": "WEBHOOK_URL"
},
"nicknameReportChannelId": "CHANNEL_ID",
"roles": {
"verified": "ROLE_ID",
"muted": "ROLE_ID"
},
"punishments": {
"logChannelId": "CHANNEL_ID",
"appealBaseUrl": "/appeal",
"permissions": {
"can_warn": "zander.discord.punish.warn",
"can_kick": "zander.discord.punish.kick",
"can_ban": "zander.discord.punish.ban",
"can_mute": "zander.discord.punish.mute",
"can_view_history": "zander.discord.punish.history"
},
"requireDmSuccess": false
}
},
"watch": {
"contentChannelId": "CHANNEL_ID",
"contentPingRoleId": null,
"filters": {
"twitch": {
"titleMarkers": ["#cfc", "[cfc]"],
"tags": ["cfc"]
},
"youtube": {
"tags": ["cfc"],
"descriptionMarkers": ["#cfc"]
}
}
},
"events": {
"discordChannelId": "CHANNEL_ID"
},
"staffAuditReport": {
"enabled": true,
"dayOfWeek": "Monday",
"time": "12:00",
"timezone": "Australia/Sydney",
"webhookUrl": "WEBHOOK_URL"
}
}
features.json
This file enables or disables individual platform features. All values are booleans:
| Key | Description |
|---|---|
announcements | Announcement system |
applications | Staff/player application listings |
forms | Custom form builder |
forums | Community forums |
support | Support ticket system |
server | Server management |
ranks | Rank system |
report | Player reporting |
shopdirectory | In-game shop directory (requires QUICKSHOP_URL) |
vault | Map/resource vault |
bridge | Command bridge executor |
watch | Creator content watch page |
vote | Vote tracking and monthly rewards |
events | Event management |
staffAuditReport | Automated staff audit reports |
discord.punishments | Discord punishment system |
discord.events.generalKenobi | Discord join/leave/switch announcements |
discord.events.guildMemberBoost | Server boost notifications |
discord.events.guildMemberVerify | Account verification events |
discord.events.nicknameCheck | Periodic nickname compliance checks |
discord.events.unverifiedReminder | Reminders to unverified members |
discord.events.ipAutoDetect | IP detection on member join |
filter.link | Link/URL filtering |
filter.phrase | Profanity/phrase filtering |
web.login | Web login |
web.register | Web registration |
smDiscord, smTwitter, smYouTube, etc. | Social media platform links in the site footer |
Minecraft Plugins
zander-addon (plugins/zander-addon/config.yml)
BaseAPIURL: "https://example.com/api"
APIKey: "your-api-key"
features:
policyBook:
enabled: false
slot: 8
socialPaper:
enabled: false
slot: 7
zander-auth (plugins/zander-auth/config.yml)
BaseAPIURL: "https://example.com/api"
APIKey: "your-api-key"
MOTDTopLine: "&e&lMy &2&nMinecraft&r &6&oAUTH Server"
zander-hub (plugins/zander-hub/config.yml)
velocitymultiplier: 3
hub:
world: 'world'
x: 0.5
y: 33.0
z: 0.5
yaw: -180.0
pitch: 0.0
messages:
join: '&7%p% joined.'
leave: '&7%p% left.'
misc:
always_first_join: false
slot_hub_compass: 4
| Key | Description |
|---|---|
velocitymultiplier | Velocity multiplier applied in the hub world |
hub.world | World name for the hub spawn |
hub.x/y/z/yaw/pitch | Spawn coordinates and rotation |
messages.join / messages.leave | Join/leave messages; %p% is replaced with the player name |
misc.always_first_join | Whether to always treat every join as a first join |
misc.slot_hub_compass | Inventory slot for the hub compass item |
zander-velocity (plugins/zander-velocity/config.yml)
config-version: 1
BaseAPIURL: "https://example.com/api"
APIKey: "your-api-key"
announcementMOTDTopLine: "&e&lMy &2&nMinecraft&r &6&oServer"
announcementTipPrefix: "&7&l[&6&lTIP&7&l]&r "
announcementTipInterval: 10
| Key | Description |
|---|---|
announcementMOTDTopLine | Top line of the server MOTD |
announcementTipPrefix | Prefix prepended to rotating tip messages |
announcementTipInterval | How often (in seconds) tips rotate |