Skip to content

🖥️ Adding a Panel Page

This page documents how to add or change a web panel page safely.

It is based on the current live Magikal panel structure.

Current panel structure

Area Path
Panel project /home/magikalbot/magikal-panel
FastAPI backend /home/magikalbot/magikal-panel/api/main.py
Next.js frontend /home/magikalbot/magikal-panel/web
Main frontend page /home/magikalbot/magikal-panel/web/pages/index.jsx
Global CSS /home/magikalbot/magikal-panel/web/styles/globals.css
Next config /home/magikalbot/magikal-panel/web/next.config.js

Current frontend model

The current frontend is a Next.js static export.

The live config shows:

output: 'export'

This means the frontend builds to:

web/out

The panel web service serves that static output.

Current UI shape

The current panel is mostly a single dashboard in web/pages/index.jsx.

Adding a new panel area usually means adding a new section/card/component inside index.jsx, not creating a separate routed page.

Do not introduce a new routing structure unless that refactor is explicitly approved.

Current backend model

The backend is FastAPI in:

api/main.py

The API handles:

  • health checks
  • database ping
  • Discord OAuth login
  • Discord OAuth callback
  • session logout
  • current user lookup
  • manageable guild list
  • config loading
  • config section metadata
  • config saving

Current important API routes include:

Route Purpose
/health API health check
/db/ping Database connectivity check
/auth/login Start Discord OAuth login
/auth/callback Discord OAuth callback
/auth/logout Clear session
/user/me Current logged-in user
/user/guilds Guilds the user can manage
/config/{guild_id} Load merged guild config
/config/{guild_id}/sections Load config section metadata
PUT /config/{guild_id} Save config updates

The public site normally reaches these through the Nginx /api/ proxy.

Frontend calls look like:

/api/user/me
/api/user/guilds
/api/config/{guild_id}
/api/config/{guild_id}/sections

Auth model

The panel uses Discord OAuth and server-side sessions.

The backend stores user/session information through session middleware.

Guild access is based on the Discord guild list returned through OAuth.

Permission rule

Do not rely on the frontend alone for permissions.

The API must enforce login and save permissions.

Frontend checks are for user experience. Backend checks are for security.

Config save/load model

The frontend loads config from:

GET /api/config/{guild_id}

It also loads section metadata from:

GET /api/config/{guild_id}/sections

It saves changed config with:

PUT /api/config/{guild_id}

The current frontend builds a dirty/changed payload, so only changed fields are sent on save.

Config source of truth

Panel-backed settings should save to Postgres-backed config.

The panel must not invent a second source of truth.

Expected flow:

Web panel -> FastAPI -> Postgres/cfg tables -> bot reads config

Before changing the panel

Check Git state:

cd /home/magikalbot/magikal-panel
git status --short

For large or risky layout/API changes, create a restore point first:

git add .
git commit -m "restore point before panel change"

Adding a new config section

Use this approach for most new panel work:

  1. Confirm the setting already exists in bot storage/database.
  2. Confirm the API exposes it through /config/{guild_id}.
  3. Confirm the API allows saving it through PUT /config/{guild_id}.
  4. Add the field/section to the frontend.
  5. Make sure save only sends changed fields.
  6. Test load, edit, save, reload.
  7. Check API logs.
  8. Check the bot reads the saved value.

Backend changes

Backend changes usually happen in:

api/main.py

Add or update backend support when:

  • the frontend needs a new API route
  • a config field is not exposed yet
  • save logic needs a new namespace/table
  • validation is needed
  • permission checks need tightening

Do not bypass backend permission checks

Any route that reads private user/session data must require login.

Any route that saves config must require the correct management permission.

Frontend changes

Frontend changes usually happen in:

web/pages/index.jsx

Current frontend responsibilities include:

  • loading current user
  • loading manageable guilds
  • selected guild state
  • loading config
  • loading config sections
  • editing fields
  • building dirty save payloads
  • saving changed config
  • showing save state/errors
  • layout for desktop/mobile

Layout rules

Panel layout should stay usable on different screen sizes.

Current design direction:

  • top/header area should remain easy to reach
  • selected server context should remain clear
  • server list and section navigation should not fight the main editor
  • the config editor can scroll independently
  • mobile should not feel like a crushed desktop page
  • avoid fixed-width designs that waste large screens

Panel layout test

Test the panel on desktop width and mobile width before calling layout work done.

Adding a frontend section safely

When adding a new section inside index.jsx:

  1. Keep the section small.
  2. Reuse existing card/field patterns.
  3. Add clear labels and descriptions.
  4. Use existing save state handling.
  5. Avoid hardcoding guild-specific values.
  6. Keep mobile layout in mind.
  7. Keep the selected guild context visible.
  8. Do not duplicate API fetch logic unless needed.

API fetch pattern

The frontend currently uses an API helper pattern around fetch.

New frontend calls should follow the existing helper style rather than inventing a separate fetch method.

Good goals:

  • include credentials/session where required
  • handle non-200 responses
  • show useful user-facing errors
  • avoid leaking raw backend errors to users

Save behaviour

Good save behaviour:

  • only send changed fields
  • show unsaved changes clearly
  • disable/guard save while saving
  • show success/failure result
  • reload or refresh state after successful save
  • avoid silently dropping fields

Save testing

After any save-related change, test this full loop:

  1. load current config
  2. change one field
  3. save
  4. refresh browser
  5. confirm the value stayed changed
  6. confirm bot behaviour matches the saved setting

Backend validation

Validate risky or typed fields on the backend.

Examples:

  • booleans
  • channel IDs
  • role IDs
  • JSON config
  • numeric limits
  • feature flags

Frontend validation is useful, but backend validation is the safety net.

JSON fields

The current frontend treats fields matching names like json, config, extra, or qa_config as JSON-style fields.

Be careful when adding JSON fields.

Bad JSON should not break the whole panel.

Restarting after changes

For backend/API changes:

sudo systemctl restart magikal-panel-api
sudo systemctl status magikal-panel-api --no-pager
sudo journalctl -u magikal-panel-api -n 120 --no-pager

For frontend/static UI changes, rebuild/export using the current panel workflow, then restart:

sudo systemctl restart magikal-panel-web
sudo systemctl status magikal-panel-web --no-pager
sudo journalctl -u magikal-panel-web -n 120 --no-pager

Confirm the deploy workflow

Before doing major panel deployment work, confirm the current live build/export/publish process.

The panel has changed over time, so do not assume old deployment notes are still correct.

Common red flags

Stop and review if a panel change:

  • changes auth/session behaviour
  • changes Discord OAuth setup
  • changes save permissions
  • changes config save payload shape
  • changes /config/{guild_id}
  • changes /config/{guild_id}/sections
  • changes database table mappings
  • breaks mobile layout
  • causes static export build errors
  • hardcodes a guild/server ID
  • introduces a second source of truth
  • exposes secrets or raw backend errors

Testing checklist

Before calling a panel change done:

  • git status --short checked
  • frontend builds successfully
  • API starts successfully
  • login still works
  • guild list loads
  • selected guild loads config
  • sections load
  • saving works
  • refresh keeps saved values
  • mobile layout is checked
  • logs have no traceback
  • no secrets or raw private data are exposed

Useful log checks

Panel API logs:

sudo journalctl -u magikal-panel-api -n 120 --no-pager

Panel web logs:

sudo journalctl -u magikal-panel-web -n 120 --no-pager

Search API errors:

sudo journalctl -u magikal-panel-api -n 300 --no-pager | grep -i error

Rule

Panel pages should be added through the existing API/config flow, stay responsive, keep permissions server-side, and never create a second source of truth.