Skip to main content

Database

Zander uses MySQL with Prisma as the ORM. This page documents the connection setup, how to apply migrations, and a full breakdown of every model in the schema so you know exactly where your data lives. The schema is defined in prisma/schema.prisma.

Connections

Up to four separate MySQL connections can be configured. zander-web owns and migrates only the main database via Prisma; the other three are external schemas it reads/writes into without owning their migrations:

VariablePurposeOwned by zander-web?
DATABASE_URLMain Zander database (required)Yes - migrated via prisma/migrations/
LUCKPERMS_URLLuckPerms database - used for rank/permission lookups (required if using ranks)No - external schema, read for permission checks and rank management
QUICKSHOP_URLQuickShop database - used for the shop directory (required if using shop directory)No - external schema
PUNISHMENTS_URLLiteBans database - read/written for the web punishments dashboard and profile pagesNo - external schema

Connection strings use the format:

mysql://username:password@host:3306/database_name
note

Most controllers query the main database with raw SQL via a mysql2 pool rather than through Prisma Client models - Prisma is used here primarily as a migration tool, not the everyday query layer. Schema changes should still always go through a new Prisma migration.

Initial Setup

Run the SQL initialisation script to create the base schema, then apply all numbered migrations from the migration/ directory in order:

mysql -u root -p zander < dbinit.sql
# then for each migration file in order:
mysql -u root -p zander < migration/001_name.sql

For new deployments using the Prisma build script:

npm run build

This runs prisma migrate deploy and prisma generate automatically.

Schema Overview

The following models are defined in prisma/schema.prisma:

Users & Authentication

ModelDescription
usersCore user accounts - UUID, username, email, password hash, profile data, social links
userEmailVerificationsEmail verification tokens
userPasswordResetsPassword reset tokens
userVerifyLinkShort-lived codes for linking Discord accounts to Minecraft UUIDs

Sessions

ModelDescription
sessionExpress session store (Prisma-backed)

Forums

ModelDescription
forumCategoriesForum categories with view/post permission nodes
forumDiscussionsDiscussion threads
forumPostsIndividual posts/replies
forumPostRevisionsEdit history for posts
forumPollsPolls embedded in discussions
forumPollOptionsPoll answer options
forumPollVotesUser vote records

Announcements & Servers

ModelDescription
announcementsMulti-type announcements (web, popup, tip, motd)
serversServer registry with connection details and type
serverStatusCached live server status (player count, online state)
gameSessionsIn-game session records reported by the plugins

Applications

ModelDescription
applicationsStaff/player application listings and submissions

Discord

ModelDescription
discord_punishmentsPunishment records (warn, kick, ban, mute) with expiry and status
discord_punishment_appealsAppeal submissions and review outcomes
scheduledDiscordMessagesScheduled message queue for the Discord scheduler

Support

ModelDescription
supportTicketsSupport ticket records with category and status
supportTicketMessagesMessages and internal notes within tickets
supportTicketCategoriesConfigured ticket categories
supportTicketCategoryPermissionsPer-category access permissions for staff

Reports (Web)

ModelDescription
reportsPlayer reports submitted via web or Discord
note

There is no local punishments Prisma model for website punishments - the web punishments dashboard and profile pages read and write to the external LiteBans schema via PUNISHMENTS_URL instead (see the Connections table above), the same way LUCKPERMS_URL is used for rank data.

Badges

ModelDescription
badgesBadge definitions (name, icon, description)
user_badgesBadge assignments to users

Webstore

ModelDescription
webstorePurchasesRecorded Tebex/Stripe purchases
webstoreSubscriptionsRecurring subscription records
webstoreWebhookEventsRaw webhook events received from Stripe
webstoreStripeCommandsCommand mappings run for Stripe products
webstoreCommandRunsExecution log for webstore-triggered commands
webstoreTransactionsTransaction ledger for the webstore/goal tracking

Finance

ModelDescription
financeAccountsFinance accounts (e.g. bank, PayPal)
financeCategoriesIncome/expense categories
financeTagsTags applied to finance transactions
financeVendorsVendor/payee records
financeTransactionsIndividual income/expense transactions
financeTransactionTagsJoin table linking transactions to tags
financeInvoicesInvoice records
financePaymentsPayments applied against invoices
financeAttachmentsFile attachments on finance records
financeOperationsBudgetOperating budget tracking
financeMonthlyReportsGenerated monthly finance reports

Voting

ModelDescription
votesIndividual vote records
vote_sitesConfigured voting sites
vote_reward_templatesCommand templates for vote and monthly rewards
vote_monthly_totalsAggregated monthly vote counts per player
vote_monthly_resultsProcessed monthly reward results
player_command_queueQueue of reward commands to execute in-game

Events

ModelDescription
eventsCommunity events with full lifecycle state
event_templatesRecurring event templates
event_template_announcementsAnnouncement config attached to event templates
event_template_hostsDefault host assignments for event templates
event_hostsHost assignments for events
event_actionsIn-game actions triggered by events
event_announcementsDiscord/web announcements tied to events
event_audit_logsChange history for events

Creator Content

ModelDescription
creator_content_itemsCached Twitch/YouTube content items
creator_content_notificationsNotification records for new creator content
user_platform_connectionsTwitch/YouTube account links for users

Bridge & Automation

ModelDescription
bridgeLegacy single command-bridge queue (command, target server, processed flag)
executorTasksIndividual command tasks in the newer bridge executor queue
executorRoutinesNamed multi-step routines for the bridge
executorRoutineStepsIndividual steps within an executor routine

Logs

ModelDescription
logsSystem activity/audit log entries shown in the dashboard (Dashboard → Logs)

Notifications

ModelDescription
userNotificationsIn-app notification records
pushSubscriptionsWeb push subscription endpoints per user

Migrations

Migration files are located in migration/. Run them in numeric order. After applying all migrations, the Prisma client must be regenerated:

npx prisma generate