Everything you need to use the app and to import / export your data. The app runs entirely on your device β there is no account and nothing is uploaded unless you use Cloud Sync.
Quick start
- Add your games β My Games tab β import from BGG (cookie), or a CSV / XML file, or add manually.
- Add box dimensions β needed for packing. Import them, auto-fetch from BGG, or type them in the π Fix Dimensions tab.
- Define your shelves β My Shelves tab (or use a Kallax / Billy / Detolf preset).
- Pack β Packing Results tab β see what fits where, with a 2D map and a 3D view.
- Save & fine-tune β πΎ Save as Layout, then open it in the βοΈ Layout Editor to hand-arrange the last boxes.
- Back up β My Games β πΎ Backup (save all), and/or β Cloud sync to share across devices.
The tabs
| Tab | What it does |
| π¦ My Games | Import / add games, filter & sort the collection, edit a game's profile (size, expansion flag, note), backup & cloud sync. |
| π Fix Dimensions | Focused side-by-side editor for typing box sizes β list of games on the left (β Missing only / All games), entry panel on the right. |
| ποΈ My Shelves | Define shelf / box dimensions β outer size, wall thickness, type, and the wider rim of a tapered plastic tote. Presets for IKEA Kallax, Billy, Detolf. |
| π Packing Results | 3D bin-packs your collection across all shelves; per-shelf fill %, 2D map, 3D view, β Swap / π Make room, and πΎ Save as Layout. |
| π Moving House | Packs the whole collection into cardboard moving boxes and estimates how many boxes you need. Box types here are session-only β they are not saved to My Shelves. |
| βοΈ Layout Editor | Full editor for one layout: move games between boxes, resize a box, choose a packing strategy, and β Arrange each game by hand in 2D and 3D. |
| π My Layouts | Your saved layouts β container cards (AβZ, with expansions stored inside a base-game box listed under it), π Rooms β tabs under the Saved Layouts title (All / each room / Unsorted / οΌ Add room); picking a room lays the same layout list out on that room grid (columns Γ stacking levels, bottom row = the floor). β Room setup picks which layouts are in the room, βοΈ Arrange drags them into place, a big 3D view, unassigned games, rename / note / open in the editor. |
Getting your games in
1. From BoardGameGeek (Live API)
BGG now requires you to be logged in to use its API. So:
- Paste your BGG session cookie in β Settings β BGG account. This loads your collection (public or private). See BGG API notes for how to get the cookie.
- A BGG API key (separate) is required for search and auto-fetch of dimensions. Paste it in β Settings β π API key (name + value). Get one at boardgamegeek.com/applications β Tokens.
2. From a file (CSV or XML)
- CSV β export your collection from BGG (Collection page β Export β CSV), then My Games β CSV tab.
- XML β a BGG collection XML, or a "collection with dimensions" export. My Games β XML tab.
3. Manually
Use the "Add game" form to type a name and dimensions directly.
Box dimensions
Packing needs each game's box size (width Γ depth Γ height, stored in mm). Ways to get them:
- A "collection with dimensions" XML (e.g. a
bgg.xml export that has <width>/<depth>/<height> on each game) β import via the XML tab; sizes come in with the names.
- A dimensions file (CSV or JSON) β import via π Restore backup β "Dimensions only", which merges sizes into your existing games by BGG id / name.
- BGG API key (β Settings β π API key) β auto-fetch from BGG's version data (partial coverage β not every edition has sizes).
- Manually β the π Fix Dimensions tab: pick a game on the left (β Missing only by default), type W/D/H on the right. A β marker and the edit date are recorded on every size you type yourself.
Tip: any value imported in inches or cm is auto-converted to mm.
Which games "need" dimensions
A game is only counted as missing dims when the packer actually needs its size. Expansions marked
stored in the base game's box and games you have excluded are skipped β
they are never packed on their own, so they don't need a size and they don't appear in the β counter.
Measuring boxes to submit to BGG? Use My Games β Missing dims β incl. in-box.
It ignores that rule and lists every game and expansion with no numbers on record, in-box and
excluded included, so you can measure them anyway. It also overrides the β Hide in-box exps checkbox.
Finding games (filters & sorts)
The filter bar above the My Games table. βΊ Reset clears search, every filter and the sorting.
| Control | Options / what it does |
| Search | Matches the game name. |
| Type | All / base games only / expansions only. |
| Dimensions | All dims Β· Has dimensions Β· Missing dims (what the packer needs) Β· Missing dims β incl. in-box (raw: anything with no W/D/H at all). |
| BGG info | β BGG info missing / β loaded β whether the full BGG details (players, time, categories, edition languages) have been pulled for that game. |
| Edit state | Hand-edited dims β every size you typed yourself (the β games). Use this to review your own numbers, e.g. before submitting them to BGG. Or Not hand-edited for everything still on BGG's values. |
| Edition | Filter by a BGG edition language recorded on the game. |
| β Hide in-box exps | Hides expansions stored inside a base game's box. |
| Sort | Name, size, volume, group by exact / similar size, and recently hand-edited first. Clicking the W / D / H column headers sorts by that dimension. |
The app records that you edited a size, but not what BGG originally said β so it can list
your hand-edited games, not the difference from BGG's value.
Shelves & boxes
You enter outer dimensions plus a wall thickness; the usable interior is
computed as outer β 2Γwall on each axis. That inner size is what the packer fills, and it's the
big number on the shelf card (the outer size and wall are shown underneath).
- ποΈ Shelf / π¦ Cardboard box β straight walls, nothing else applied.
- π§ Plastic tote β these flare wider at the top. Enter the rim (top) width & depth
and the app packs the real slanted-wall volume, so a box that is too wide for the floor can still rest
higher up where the tote has opened out. Leave the rim blank and it falls back to a flat 88 % estimate of
the floor β worth filling in, it's usually several extra games.
- Depth is optional β leave it empty for an open shelf with unlimited depth.
- β§ Duplicate copies a shelf; β Remove is the only thing that deletes one.
Using a shelf in a layout does not consume it β the layout takes a copy.
Your shelves stay in ποΈ My Shelves. (Two consequences: an empty box is dropped from a layout when
you save it, and resizing a shelf later does not resize boxes in layouts you already saved.)
How packing works
- Every game is expanded by its quantity. Games with no dimensions, games in a base box, and excluded
games are skipped β and reported in the summary rather than silently dropped.
- Shelf 1 is packed with everything, then shelf 2 with what's left, and so on. Shelf order matters β
the first shelf gets first pick. Whatever survives every shelf is listed under Games that didn't fit.
- Inside one box, all 6 orientations are tried per game, biggest first, each placed at the lowest position
it fits. Tapered totes use a separate packer that can stand boxes on edge against the slanted wall.
Store as changes which orientations are allowed:
- π² Auto β all six, the packer decides.
- π₯ Flat β boxes lie flat, biggest footprint on the floor (a pyramid).
- π Upright β boxes stand on edge, spine out, like books.
The gap is applied once between neighbours, not around every face β two 60 mm boxes at a
5 mm gap sit at 0β60 and 65β125.
Fill % is volume-based, so 60 % can already be physically full β boxes don't tessellate.
3D packing is a hard problem and a careful human still beats the algorithm on the last box or two; that's
what β Arrange is for.
Layout Editor & hand-arranging
Open a saved layout in the βοΈ Layout Editor (or from π My Layouts β βοΈ Open in Layout Editor).
Per box you can rename/resize it (π Edit box), move games in and out, set the packing strategy, and open
β Arrange to place each game yourself.
In β Arrange
- 2D view β click a box to select it, drag to move it. It snaps to walls, the floor and
neighbouring edges. The flat view hides itself when the pack has more than one depth layer, because it
can only honestly show one.
- 3D view β tap to fade a box, double-tap to select, drag to slide it along the floor.
The same selection is shared with the 2D panel, and the controls appear on the 3D scene when it's open.
- π Pin a box to keep it exactly where it is; auto-fill and re-pack work around pinned boxes.
- Games that don't fit are staged outside the box (to its right) instead of being piled
inside other games. That's a working state, not a failure β outside games are excluded from overlap and
"doesn't fit" warnings.
- π§© Fill space drops the leftover/overlapping games into the gaps while keeping what you
placed; π Auto-pack rearranges everything from scratch; π Search harder tries
many arrangements and smaller gaps; β¬ Hard first places the games that didn't fit first;
β¬
Empty box moves everything outside so you can add games back one at a time.
- βΆ Undo / β· Redo per box, and per-game orientation (π₯ / π / π²) either on one row or on
several ticked rows at once.
- Boxes that intersect are reported as β N overlapping with the names listed β inside the
panel and on the box header.
If you change a game's box size after saving a layout, reopening the layout updates that
game inside the arrangement automatically (keeping its orientation) and tells you how many games changed.
Check the overlap banner afterwards β a box that grew may now clash with its neighbours.
Backup & Restore
One JSON file holds everything β games, dimensions, shelves and saved layouts.
- πΎ Backup (save all) β downloads
shelf-calculator-backup.json.
- π Restore backup β pick a JSON backup; it then asks what to import:
- Everything β replace games, shelves & layouts
- Collection only β games + shelves
- Dimensions only β merge box sizes into your current games (matched by BGG id / name)
- Layouts only β just the saved layouts
Cloud sync
Move your data between your PC and phone without files. In My Games β β Cloud sync:
- On the first device, open β Settings, press π² Generate for a strong secret sync code (or type your own, β₯ 6 characters) and click ββ¬ Save.
- On the other device, enter the same code in β Settings and click ββ¬ Load.
If the cloud copy was saved from another device since this one last loaded or saved it, ββ¬ Save asks before overwriting it. Each save also keeps the one before it β β Settings β β© Load previous cloud save brings it back.
The sync code is the password β anyone who knows it can read or overwrite that data. Use π² Generate rather than a word you picked. Only board-game data is stored.
Backup JSON
What πΎ Backup writes and π Restore reads:
{
"v": 2,
"games": [
{ "id": 1, "bggId": "13", "name": "Catan",
"w": 295, "d": 295, "h": 75, "qty": 1,
"isExpansion": false, "inBaseBox": false }
],
"shelves": [ { "id": 1, "name": "Kallax", "w": 330, "d": 380, "h": 330 } ],
"nextId": 2,
"layouts": [ /* saved layouts */ ]
}
Dimensions w/d/h are in millimetres. bggId is used to match games on a "Dimensions only" import.
Dimensions CSV
The importer is flexible: it auto-detects the delimiter (, ; or tab), the unit (inches / cm / mm), and these column names:
| Meaning | Accepted column headers |
| BGG id | bggid, objectid, id |
| Name | name, objectname, title |
| Width | w, w_mm, width |
| Depth | d, depth, thickness |
| Height | h, height, length |
| Optional | qty, isExpansion, inBaseBox |
Example:
bggId,name,w_mm,d_mm,h_mm
13,Catan,295,295,75
9209,Ticket to Ride,295,295,70
BGG XML
Both BGG shapes are accepted on the XML tab:
- Collection β
<item objectid="β¦"><name>Catan</name>β¦</item>. Dimensions only if the export includes <width>/<depth>/<height> (in inches).
- Thing β
<item id="β¦"><name type="primary" value="Catan"/>β¦<versions>β¦<width value="β¦"/>β¦</versions></item>.
BGG XML API URLs
The data is split across two endpoints (replace YOU with your username; the app fills these in for you in the XML tab and β Settings):
- Owned base games β
https://boardgamegeek.com/xmlapi2/collection?username=YOU&own=1
- Owned expansions (a separate download β the default call excludes them) β
https://boardgamegeek.com/xmlapi2/collection?username=YOU&own=1&subtype=boardgameexpansion
- Add complexity "weight" + stats β append
&stats=1 to a collection URL β adds <averageweight>, player counts, rating. (Note: BGG "weight" = rules complexity 1β5, not physical mass.)
- Box dimensions are NOT in the collection feed β they live per-edition on the thing endpoint:
https://boardgamegeek.com/xmlapi2/thing?id=13,926,β¦&versions=1 β <width>/<length>/<depth> in inches. The app fetches these automatically after an import (π Fetch from BGG / auto), mapping widthβW, depthβD, lengthβH, preferring your owned edition.
Where your data is stored
- Web / installed app (PWA) β in the browser's
localStorage for this site. It's per-device and per-browser β Chrome and Firefox don't share, and phone and PC don't share, unless you use Backup files or Cloud sync.
- Windows desktop app β in files under
%APPDATA%\shelf-calculator\.
- Clearing your browser's site data, or uninstalling, removes the local copy β keep a Backup or use Cloud sync.
BGG API notes
Since late 2025 BGG locked its XML API behind authentication (the "XML API registration" change):
- Your own collection works with just a logged-in session cookie β no registration needed.
- Search and box-dimension lookup need a registered-app API key:
register an application at boardgamegeek.com/applications,
click Tokens, and paste just the token (a code like
e3f8c3ff-β¦, not the word "Bearer")
into β Settings β π API key.
- Your BGG password is never stored β only the username is kept. The desktop app asks for
the password once per session if you load a private collection.
- Windows only: private (password) collection fetch and writes back to BGG work in the
desktop app. On Android and in the browser, BGG is reached through a proxy, which supports public
collections only.
Getting your session cookie
In a desktop browser logged in to boardgamegeek.com: press F12 β Application β Cookies β https://boardgamegeek.com. Copy the values of bggusername, bggpassword and SessionID and paste them into the app as:
bggusername=YOU; bggpassword=...; SessionID=...
Treat the cookie like a password β it grants access to your BGG account until it expires. Don't share it. Re-paste a fresh one if loading stops working.
Board Game Shelf Calculator β local-first, no account required.