Building Menus with GUI Extension
This guide walks you through creating menus of increasing complexity — from a basic 3-slot menu to a full multi-frame dashboard with persistent storage.Table of Contents
- Your First Menu — Simple layout, 3 slots, interactions
- Grid Patterns — Using
count,direction,gap,repeatY - Scrollable Menus — Long lists with scroll buttons
- Multi-Frame Dashboards — Independent scrollable zones
- Paginated Collections — Multi-page browsing
- Persistent Storage — Saving items across sessions
- Vanilla GUIs — Anvil, Enchanting, Smithing
- Full Example: Shop Menu — Putting it all together
Your First Menu
A minimal menu with 3 clickable slots.Architecture
Page JSON
Key Concepts
x,y: Slot position on the 9x6 grid (0-indexed)interactionList: Per-slot click actions. Each entry has atype(LEFT, RIGHT, etc.),commands, and optionalcloseMenu%player%: Engine placeholder resolved to the player’s namegui:close: Built-in command to close the menu (automatically added whencloseMenu: true)
Grid Patterns
Usecount, direction, gap, and repeatY to create grids without writing every position.
Architecture
Page JSON
Position Logic
| Field | Value | Effect |
|---|---|---|
x, y | 0, 0 | Start at top-left |
count | 9 | 9 items in the direction (fills width) |
direction | right | Each item is +1 in X |
gap | 1 | 1 slot between items (standard) |
repeatY | 3 | Repeat the row 3 times vertically |
Example: Navigation Bar
Scrollable Menus
When content exceeds the visible area, use a ScrollableLayout.Architecture
Page JSON
Key Concepts
virtualHeight: Total scrollable height (in slots). The viewport shows 6 rows (SIZE_54) or 3 (SIZE_27).buttons: Scroll buttons are anchored to the viewport — they don’t move with contentid: Required for each scrollable layout. Used internally for scroll tracking- Left/Right scroll: Set
virtualWidth> 9 and add LEFT/RIGHT buttons
Multi-Frame Dashboards
Divide the screen into independent zones, each with its own scrolling content.Architecture
Critical: Each scrollable zone must have a unique id. Without unique IDs, scroll events from zone B will incorrectly target zone A.
Page JSON
Frame Fields
| Field | Description |
|---|---|
id | Frame identifier (for referencing) |
x, y | Frame position in the inventory grid |
width, height | Frame dimensions in slots |
layout | Child layout (usually scrollable) |
Paginated Collections
Multi-page browsing with next/previous buttons.Architecture
Page JSON
Persistent Storage
Save items in GUI slots that persist across sessions and server restarts.Architecture
Required Setup
- Create the artifact entry:
- Add
storageto any layout slot:
Storage Placeholders
| Placeholder | Resolves to |
|---|---|
{stored_name} | Item display name (empty if slot is empty) |
{stored_amount} | Current count (0 if empty) |
{stored_max} | Max capacity (from maxAmount, ∞ if unlimited) |
Group-Based Storage
Share items between players (team bank, island chest):Accumulation Mode
Track progress towards a goal:onReachRequired triggers fire and items are consumed.
[!WARNING] Do not leaverequiredItemas an empty object. In Typewriter’s editor, if you add arequiredItemfield but leave it empty (no components), it resolves toMaterial.AIRat runtime. The slot will reject all items silently, because no item matches AIR. Either omitrequiredItementirely (for standard storage with no item restriction) or set it to a specific item type.
Click Configuration
Default click mappings (configurable globally viagui_settings):
| Action | Default Click |
|---|---|
| Place one | LEFT |
| Place all | SHIFT_LEFT |
| Take one | RIGHT |
| Take all | SHIFT_RIGHT |
| Take stack | SWAP_OFFHAND |
| Fill from inv | DOUBLE_CLICK |
| Drop all | DROP |
Vanilla GUIs
Use Minecraft’s built-in GUI types for native behavior.Available Types
guiType | Use Case |
|---|---|
ANVIL | Rename/repair items |
ENCHANTING_TABLE | Enchant items |
SMITHING | Upgrade gear to Netherite |
STONECUTTER | Precise block cutting |
GRINDSTONE | Repair/disenchant |
LOOM | Banner patterns |
CARTOGRAPHY | Map editing |
MERCHANT | Villager trades |
BOOK | Display text |
Example: Anvil Rename
Note: Vanilla GUIs have fixed slot positions. Layout items are informational only.
Full Example: Shop Menu
A complete shop menu combining SimpleLayout, Storage, interactions, and navigation.Architecture
Full JSON
What This Example Demonstrates
| Feature | Used In |
|---|---|
| Grid background | Gray glass panes with count=9, repeatY=3 |
| Storage with placeholders | All 4 chest slots use {stored_name}, {stored_amount}, {stored_max} |
| Different max amounts | 10, 64, 5, 1 — each slot has its own capacity |
forceStorage | All storage slots accept any item type |
isGhost | Info book can be clicked but not taken |
| Helpful lore | Each slot shows click instructions |
Best Practices
- Always use unique IDs for scrollable layouts in multi-frame menus
- Include click instructions in slot lore so users know what to do
- Use
{stored_max}in lore — when max=0 or unlimited, it shows∞ - Set
forceStorage: truefor slots that may hold tools or non-stackable items - Test with all inventory sizes — SIZE_27 (3 rows), SIZE_54 (6 rows)
- Use grid patterns (
count/direction/repeatY) instead of duplicating items - Group storage with a GroupEntry for team-based inventories
onFill/onEmptytriggers for reactive menus that change when items are deposited