Skip to content

GUI System

Journey’s GUI system lets you build and customize all in-game menus through JSON configuration files. Every menu — journal, party, bounty boards, backpacks — is defined as a config-driven GUI with slot types, state machines, MoLang-powered dynamic content, and template inheritance.


Path: config/journey/guis/ (loaded server-side)

FileDescription
journal.jsonQuest/task list and tracking
task_detail.jsonDetailed task information
party.jsonParty management and members
party_create.jsonCreate new party dialog
party_invites.jsonPending party invitations
bounty_board.jsonBounty board tasks
backpack.jsonQuest item storage
levelable.jsonXP and level progression
team_select.jsonPokemon team selector

All built-in GUIs can be overridden by placing a file with the same name in config/journey/guis/.


Every GUI file follows this format:

{
"gui_id": "unique_id",
"title": "<gold>GUI Title",
"size": "9x6",
"extends": "",
"states": {},
"placeholders": {},
"watchers": [],
"slots": []
}
FieldTypeDescription
gui_idStringUnique identifier for this GUI
titleStringTitle displayed at top (supports MiniMessage and placeholders)
sizeStringDimensions: 9x1 through 9x6 (chest inventory rows)
extendsStringID of another GUI to inherit from (see Extends)
statesObjectState machine definitions (see States)
placeholdersObjectCustom placeholder definitions
watchersArrayMoLang watchers that update the GUI reactively
slotsArrayList of slot definitions

Static item with no interaction.

{
"id": "info_display",
"type": "display",
"position": {"x": 4, "y": 0},
"enabled": true,
"item": "minecraft:paper",
"customModelData": 0,
"name": "<gold>Information",
"lore": [
"<gray>This is a display item",
"<yellow>It shows information"
],
"glow": false,
"count": 1
}

Clickable item that performs an action.

{
"id": "close_button",
"type": "button",
"position": {"x": 4, "y": 5},
"enabled": true,
"item": "minecraft:barrier",
"name": "<red>Close",
"lore": ["<gray>Click to close"],
"action": {
"type": "close"
}
}

Action Types:

TypeDescriptionExtra Fields
closeClose the GUI
commandRun a command"value": "/command"
open_guiOpen another GUI"value": "gui_id"
next_pageGo to next page
previous_pageGo to previous page
toggle_settingToggle a boolean"setting": "key"
set_stateChange GUI state"state": "state_name"
scriptRun MoLang script"script": "q.player.add_flag('x');"
open_party_invitesOpen party invites
open_player_inviteOpen invite dialog

Paginated list of tasks with formatting for different states.

{
"id": "task_list",
"type": "task_list",
"position": {"x": 1, "y": 1},
"enabled": true,
"size": {"width": 7, "height": 4},
"itemsPerPage": 28,
"taskFormat": {
"active": {
"item": "minecraft:paper",
"nameFormat": "<yellow>{task_name}",
"loreFormat": [
"<gray>{task_description}",
"",
"{objectives}",
"",
"<green>Click to view details"
],
"glow": false
},
"completed": {
"item": "minecraft:writable_book",
"nameFormat": "<green>{task_name} <dark_gray>(Completed)",
"loreFormat": ["{objectives}"],
"glow": true
},
"available": {
"item": "minecraft:map",
"nameFormat": "<gray>{task_name}",
"loreFormat": ["<red>Not started"],
"glow": false
}
}
}

Displays party members with different formatting per role.

{
"id": "party_members",
"type": "party_member_list",
"position": {"x": 1, "y": 1},
"enabled": true,
"size": {"width": 7, "height": 3},
"memberFormat": {
"leader": {
"item": "minecraft:golden_helmet",
"nameFormat": "<gold>{member_name} <yellow>(Leader)",
"glow": true
},
"member": {
"item": "minecraft:player_head",
"nameFormat": "<green>{member_name}",
"glow": false
},
"offline": {
"item": "minecraft:skeleton_skull",
"nameFormat": "<dark_gray>{member_name} <gray>(Offline)",
"glow": false
}
}
}

Toggle switches for party configuration (leader only).

{
"id": "party_settings",
"type": "party_settings",
"leaderOnly": true,
"settings": [
{
"id": "public_toggle",
"settingKey": "isPublic",
"position": {"x": 0, "y": 4},
"enabled": {
"item": "minecraft:lime_dye",
"name": "<green>Public Party",
"lore": ["<gray>Anyone can join", "", "<yellow>Click to make private"]
},
"disabled": {
"item": "minecraft:gray_dye",
"name": "<gray>Private Party",
"lore": ["<gray>Invite only", "", "<yellow>Click to make public"]
}
}
]
}

Page navigation for multi-page GUIs.

{
"id": "navigation",
"type": "navigation",
"previous": {
"position": {"x": 0, "y": 5},
"item": "minecraft:arrow",
"name": "<yellow>Previous Page",
"lore": ["<gray>Page {prev_page}/{max_pages}"]
},
"next": {
"position": {"x": 8, "y": 5},
"item": "minecraft:arrow",
"name": "<yellow>Next Page",
"lore": ["<gray>Page {next_page}/{max_pages}"]
},
"hideWhenUnavailable": true
}

Quest item storage area.

{
"id": "backpack_slots",
"type": "backpack_slots",
"position": {"x": 0, "y": 0},
"size": {"width": 9, "height": 6},
"emptySlot": {
"item": "minecraft:gray_stained_glass_pane",
"name": "",
"lore": []
}
}

Automatically displays bounty board tasks with formatting and click actions.

{
"id": "task_list",
"type": "bounty_task_list",
"position": {"x": 0, "y": 1},
"enabled": true
}

GUIs can have multiple states, each showing different slots and layouts. This lets you build multi-page or multi-mode GUIs in a single file.

{
"gui_id": "shop",
"title": "<gold>{state_title}",
"size": "9x6",
"states": {
"browse": {
"title": "Browse Items",
"slots": [
{
"id": "buy_tab",
"type": "button",
"position": {"x": 0, "y": 0},
"item": "minecraft:emerald",
"name": "<green>Buy",
"action": {"type": "set_state", "state": "buy"}
}
]
},
"buy": {
"title": "Buy Items",
"slots": [
{
"id": "back_tab",
"type": "button",
"position": {"x": 0, "y": 0},
"item": "minecraft:arrow",
"name": "<yellow>Back",
"action": {"type": "set_state", "state": "browse"}
}
]
}
}
}

The GUI starts in the first defined state. Buttons with set_state actions switch between states, updating the displayed slots and title.


Watchers are MoLang expressions that are evaluated periodically. When a watcher’s value changes, the GUI updates automatically.

{
"watchers": [
{
"id": "party_size_watcher",
"expression": "q.player.player_party().size()",
"interval": 20,
"on_change": "refresh"
}
]
}
FieldDescription
idUnique watcher identifier
expressionMoLang expression to evaluate
intervalTicks between evaluations
on_changeAction when value changes: "refresh" (re-render GUI) or "close"

Slot names, lore, and enabled conditions can use MoLang expressions wrapped in ${}:

{
"id": "level_display",
"type": "display",
"position": {"x": 4, "y": 0},
"item": "minecraft:experience_bottle",
"name": "<gold>Level ${q.player.levelable_level('trainer_rank')}",
"lore": [
"<gray>XP: <yellow>${q.player.levelable_experience('trainer_rank')}",
"<gray>Mode: <yellow>${q.player.levelable_mode()}"
],
"enabled_condition": "q.player.has_levelable('trainer_rank')"
}

The enabled_condition field accepts a MoLang expression. When it evaluates to 0.0, the slot is hidden.


GUIs can inherit from other GUIs using extends. The child GUI starts with all parent slots, then overrides or adds its own.

{
"gui_id": "custom_journal",
"extends": "journal",
"title": "<blue>My Custom Journal",
"slots": [
{
"id": "custom_header",
"type": "display",
"position": {"x": 4, "y": 0},
"item": "minecraft:nether_star",
"name": "<gold>Custom Header"
}
]
}

This creates a journal that looks like the default but with a custom header item. Any slot with the same id as a parent slot replaces it; new IDs are added.


Task/Journal: {task_name}, {task_description}, {objectives}, {progress}, {target}

Party: {party_name}, {party_leader}, {party_size}, {party_max}, {member_name}, {member_role}

Bounty Board: {board_name}, {board_description}, {available_tasks}, {max_tasks}

Navigation: {prev_page}, {next_page}, {current_page}, {max_pages}

State: {state_title}, {state_id}


All slots share these fields:

FieldTypeDescription
idStringUnique slot identifier
typeStringSlot type name
position{x, y}Slot position (x: 0-8, y: 0-5)
enabledBooleanWhether slot is active
enabled_conditionStringMoLang condition for dynamic visibility
itemStringItem ID for display
customModelDataIntegerCustom model data for resource packs
nameStringItem name (supports MiniMessage, placeholders, and ${} MoLang)
loreArrayItem lore lines
glowBooleanEnchantment glow effect
countIntegerStack count (1-64)

After editing GUI files:

/journey reload guis

  • Place navigation buttons consistently on the bottom row
  • Use empty strings "" in lore for blank lines
  • Use meaningful item icons: barrier for close, arrow for navigation, book for info
  • Use glow: true to highlight important items
  • Keep GUIs as small as needed — don’t use 9x6 when 9x3 is enough
  • Use extends to customize built-in GUIs without rewriting them from scratch
  • Use enabled_condition to show/hide slots based on player state
  • Use watchers to keep GUIs updated when player data changes