Everything here is free. You copy a Google Sheet, connect it, and you're building lists.
Two free accounts, nothing else. You may already have most of these.
For Google Sheets and Apps Script. You almost certainly have one already.
Free at supabase.com. Only needed if you want to save rosters across devices.
This Sheet is your card database โ it's where every Character, Weapon, Armoury item, Special Order, and Keyword definition lives. The app reads it every time it loads. Making your own copy means you fully own and control it: you can add cards, fix typos, or update stats at any time, and the app picks up the changes immediately on the next refresh.
The template is a free download from the itch.io page. It took a fair amount of work to put together, so if you find it useful, a donation there is genuinely appreciated โ but it's entirely optional and nothing is held back if you don't.
You don't need to fill out the whole Sheet before the app works โ the example rows are enough to test the connection in Step 3. But you'll need to understand the structure before you start adding real cards. This section explains how every part of it works.
Each row in the List tab represents one card in the game. The Type column tells the app what kind of card it is โ Character, Armoury, Special Orders, Command Upgrades, Fireteam Upgrades, or Rules. Every other column is the data that shows up on that card in the app.
Columns explained:
UNSC, Banished). The app uses this for competitive faction validation.ODST, Jiralhanae). Leave blank for cards with no detachment restriction.Character, Armoury, Special Orders, Command Upgrades, Fireteam Upgrades, Rules.Energy Shield (2), Tactician (1)). The app matches these against the Keywords tab to show hover definitions. Extra text in parentheses like (2) is fine โ the match is flexible.Ranged,Close Combat, or Grenade), Name, Range, AP, and Keywords sub-column. For a character's built-in weapons, fill these in. For Armoury weapon rows, the app reads the weapon data from the same columns. See "Links in Weapon Names" below for attaching weapon images.The app can display card art and weapon images by reading a link embedded directly in the cell โ not from a separate column. Here's how it works:
The app checks whether a cell has a link attached to it. If it does, it uses that link as the image source. If it doesn't, it shows the default card placeholder. This means you can have a name like MA40 Assault Rifle display as text in the Sheet, but open as a card image inside the app.
The Keywords tab has two columns: Keyword (the name, exactly as it'll be referenced in the List tab's Keywords column) and Definition (the rules text that appears on hover inside the app).
Energy Shield (2) in a card's keywords will match the Energy Shield row in this tab.The Translations tab controls every piece of text in the app's UI โ button labels, error messages, modal titles, PDF export strings, everything. It ships with English and French columns already filled in. You don't need to touch this tab unless you want to:
The Key column (first column, locked) is what the app uses internally to find each string. Don't edit the Key column. The English and French values are what actually appear in the UI.
The Restrictions column controls when an item can be added to a roster, and for Special Orders, which competitive detachment context they appear in. Leave it blank if there are no restrictions. Multiple tokens are separated by | โ all conditions must be true.
Character & roster conditions โ who must be in the roster for this item to be available:
REQUIRES_CHAR_NAME_INCLUDES:value โ roster must include a character whose name contains this text (e.g. REQUIRES_CHAR_NAME_INCLUDES:master chief)REQUIRES_CHAR_FACTION_INCLUDES:value โ roster must include a character of this factionREQUIRES_CHAR_DETACHMENT_INCLUDES:value โ roster must include a character in this detachmentALL_CHARS_DETACHMENT:value โ every character in the roster must be this detachmentALL_CHARS_FACTION:value โ every character must be this factionSpecial Orders โ competitive detachment visibility โ use these instead of the Detachment column for Special Orders. The Detachment column on Special Order rows must stay blank (writing anything there pollutes the browse filter dropdown):
ALL_UNITS_ONLY โ this Special Order only appears in comp when "All Units" is selected; hidden for specific detachments like ODST or JiralhanaeDETACHMENT_ONLY:value โ this Special Order only appears in comp for this specific detachment (e.g. DETACHMENT_ONLY:ODST). Use multiple pipe-separated entries to allow more than one detachment: DETACHMENT_ONLY:ODST|DETACHMENT_ONLY:JiralhanaeWeapon-slot rules:
REQUIRES_WEAPON:value โ character must already have this weapon on their base card (used for replacement weapons like combat knives)BLOCKS_LEGEND โ item cannot be equipped by Legend-tier charactersEXEMPT_FROM_WEAPON_LIMIT โ item doesn't count against the weapon-per-character capThe full reference with worked examples is in the Restrictions Guide tab of your Sheet.
Apps Script is a small free Google service that connects your Sheet to the app. Think of it as a messenger: the app asks it "give me the card data from this Sheet," it reads the Sheet and sends the data back. The connector script (Code.gs) is already included inside your copied Google Sheet โ you don't need to download or paste anything for that part.
/exec. Save this somewhere โ you'll paste it into the app in Step 5.appsscript.json manifest into your Apps Script project before deploying sets the correct OAuth scopes in advance, which makes the authorisation step smoother and avoids unexpected permission prompts. To use it: in the Apps Script editor, go to Project Settings โ Show "appsscript.json" manifest file in editor, then replace the file's contents by pasting the text below. Click the button to copy it to your clipboard.
Paste this into the appsscript.json file in your Apps Script editor, replacing all existing content.
There's nothing to download or host โ the app is already online and ready to use. Open it, point it at your own Sheet, and you're done.
/exec.Your connection details are remembered on your device, so you'll go straight into the app next time rather than seeing the setup screen again.
This step adds cloud roster saves โ the ability to save a roster in the app and load it again on any device (your phone, your partner's tablet, a different computer). If you skip it, you can still save and share rosters as JSON files, which works with zero setup and never expires.
supabase-setup.sql script using the button below and paste it into the SQL Editor. Click Run. This creates the single table the app needs to save rosters.Paste this into the Supabase SQL Editor and click Run.
.supabase.co. Delete anything that comes after that (such as /rest/v1/) before pasting it into the app.
Before building your first list, go to Settings โ Sheet Health Check โ Run Health Check. This scans your card data for the most common setup problems: missing required fields, duplicate card names, keywords referenced in cards that don't exist in the Keywords tab, and broken image links.
A clean result (zero errors) means your Sheet is correctly structured and the app will behave as expected. If there are warnings, the Health Check tells you exactly which row and column to look at.
Short version: I can't see any of it. Here's exactly how it works, so you can judge that for yourself rather than taking my word for it.
I host the app itself and nothing more. Think of it as a page that knows how to read your spreadsheet โ the page is mine, everything it reads and writes is yours.
The app can be installed on both iPhone/iPad and Android devices so it opens like a native app โ full screen, no browser bar, with its own icon on your home screen.
This only works in Safari. Chrome and Firefox on iOS cannot install web apps to the home screen.
apple-touch-icon.png file in your GitHub repository is what gives the home screen icon its correct appearance on iOS โ without it, iOS falls back to a generic screenshot thumbnail.
On Android, installation works through Chrome and is even more straightforward โ Chrome often prompts you automatically.