Skip to content

Seating and the Export

Austin Stanfield edited this page Sep 27, 2026 · 2 revisions

Seating and the Export

Who sits where, who is being fed, and the sheet you hand the caterer.

The seating chart lives at Admin → Seating. It is one plan shown two ways, and it ends in an Export that prints as paper or downloads as a spreadsheet.

The two views

Switch between them in the page header.

  • Canvas — draw the room, drop tables into it, drag people from the guest panel into chairs. Tables can be round, rectangular or a sweetheart table. A party is coloured so you can see when one invitation has been split across two tables. The guest panel is a Guests / Hide guests toggle: a column from tablet width up, a drawer below it.
  • List — the same plan as a roster, grouped by table (rows are people, with a Not seated block on top) or by guest (rows are whole parties). Click, ⌘/Ctrl-click and Shift-click to multi-select, then use the bulk bar to move people to a table, unseat them, swap two people, gather a split party or auto-seat everyone into free chairs. Double-click a seat to rename it, which is how Anna's guest 1 becomes a person.

Below 768px the page opens on the List view, because a pan-and-zoom canvas on a 400px screen is no way to seat anybody. On a phone the workflow is select, then the bulk bar — touch has no drag-and-drop.

A party takes one chair per person, minus anyone who answered not attending.

Who can be seated

Where they come from Takes a chair Counted as invited
Guests The guest list Yes Yes
The couple The guest list, marked as the couple Yes No
Vendors The Vendors tab No No

Adding the couple

The two of you need to be on the guest list so the chart can give you chairs and the kitchen can count your plates — but you were not invited to your own wedding, so you are not counted as guests.

  1. Go to Admin → RSVPs & Guests → Guest List.
  2. While you are not on the list, a banner offers Add the couple. Click it.
  3. One row is created, holding both of you, with the names taken from Settings → Bride / Groom.
  4. Click Edit on that row to change anything — including the names, which is how settings saying "Heaven" becomes a place card saying "Heaven Lucas" — and to set each of your dietary restrictions, exactly as for any guest.

The row is pinned to the top of the guest list with a 💍 badge. It is left out of Total Invited, missing RSVPs and the other statistics, out of the mailing export (nobody posts themselves an invitation), and its dietary answers do not appear as a reply on the RSVPs tab.

Both of you then show up in the seating panel as separate people to drag.

Vendors

The photographer, the DJ, the planner. They are at the wedding working, they are often being fed, and none of it is an invitation — so they are kept entirely apart from the guest list.

  1. Go to Admin → RSVPs & Guests → Vendors.
  2. + Add vendor, then fill in name, role, company, email, phone.
  3. Leave Needs a meal ticked if their contract includes a plate. Untick it and they stay on the sheet but stop counting toward the vendor plates.
  4. Set their food preference with the same pills the guest cards use. Nothing selected means the standard plate — the chicken.
  5. Notes is for arrival time, where they set up, anything the planner needs.

One row is one person. A DJ who brings an assistant is two rows sharing a company, because one row with a headcount of two cannot say which of them is the one who eats no gluten.

Vendors never appear on the floor plan and never take a chair.

The export

Export in the seating page header. Options on the left, a live preview of the actual sheet on the right — the preview is the same component the printer gets, laid out at the real printable width of A4, so what you approve is what comes out.

Options

What to include

  • By table — seating order, a block per table
  • Alphabetical list — every guest A–Z by surname, for finding a name at the door
  • Both — the two as two sections

Level of detail

  • Every name — the full roster
  • Counts only — headings and numbers, no names. The sheet you pin up in the kitchen
  • Names + counts — both

Also show

Option What it adds
Kitchen summary Whole-wedding totals on page one
Household Which invitation each person came in on
Side Bride's or groom's
Empty seats How many chairs at each table are still free
Not seated yet Attending people holding no chair
Vendors The vendor block, and the vendor half of the plate count
New page per table One table per sheet, for a place-card table
Entrée choice Disabled — the RSVP form has never asked for one

Format — Print / PDF (opens the printer dialog; choose "Save as PDF" there) or Spreadsheet (.csv).

What prints

  • For the kitchen — two rows of tiles with the same nine columns, so a number reads straight down. Guests: plates, then one tile per answer (the five restrictions, Kids meal, Not eating), then Chicken. Vendors: the same columns again — their Not eating is counted from the Needs a meal checkbox rather than from a dietary answer. Underneath, the grand total — "114 plates in total — 110 guests and 4 vendors (not eating: 1 guest, 1 vendor)". Guests and vendors are counted apart because a vendor meal is usually its own line on its own contract, and often a cheaper plate.

    The first tile is plates, not chairs. They are the same number until somebody is marked not eating, and then they are not — a caterer handed the headcount would cook one too many. The chairs are on each table's own heading.

  • The legend — what each restriction code means.

  • A block per table — name, type, occupancy, the counts line, and the roster if names are on. Restriction codes in the counts line are drawn as the same bordered, coloured chips the legend defines, so a green boxed VGN under a table and a green boxed VGN in the legend are visibly the same mark.

  • Not seated yet — if asked for.

  • Vendors — if asked for. In Every name and Names + counts it is a full roster: role, name, company, whether they are eating, restrictions. In Counts only it collapses to the tally plus the one thing a count cannot carry — who is not getting a plate.

The seven answers

Five of them are restrictions — things that change what is on a plate: Vegetarian, Vegan, Gluten free, Nut allergy, Other (with a free-text note).

Two of them decide the plate itself:

  • Kids meal — a child's plate instead of the adult one. Still a plate, so it still counts toward the total; it is simply not the chicken. It can sit alongside a restriction, because a child can be gluten free too.
  • Not eating — a chair with no plate against it. The baby whose food comes with their mother. They are still seated, still on the roster, still counted in "seated of" on their table — they are just not a meal. Ticking it clears the other answers and greys them out, in both the RSVP form and the admin card: restrictions on a plate that is not being served say nothing, and "not eating, vegetarian" leaves the kitchen to guess which half was meant.

"Chicken", not "no restrictions"

A plate carrying no answer at all prints as Chicken, because the standard plate is the chicken. This is the whole of what can honestly be said: the RSVP form has never asked for an entrée, so the sheet cannot tell you how many want the fish. Someone who would have chosen the fish is currently indistinguishable from someone who wanted the chicken.

A kids' meal and a not eating are not counted as chicken — both are answers, so neither falls into the no-answer bucket.

Counts only fits on one page

Counts only is meant to be one sheet, so it is fitted to one page.

The layout does most of the work — three columns once there are more than eight tables, and no vendor roster. A thirteen-table wedding comes to 997px against the 1032px A4 gives you inside its 12mm margins, and prints at full size.

Past that the sheet is measured and shrunk by exactly the amount it is over: 31 tables print on one page at 61%. It will not shrink below 60%, because a sheet nobody can read across a kitchen has not fitted on one page in any sense worth having — so 51 tables reports "2 pages — too much for one, even shrunk" rather than producing something illegible.

The dialog header says which it is before you reach the printer: "13 tables · 131 people · fits one page", or fits one page, shrunk to 61%, or the page count.

Fitting is skipped when New page per table is on, which is a request for many pages.

The spreadsheet

One row per person — never one per party, because a caterer counting plates counts rows. Each restriction is its own yes/blank column so a pivot table totals them without anyone parsing anything.

Columns: Table, Seat, Name, (Household), (Side), (Role, Meal), RSVP, the seven answers (five restrictions, Kids meal, Not eating), Note. Role and Meal appear only when Vendors is on — a vendor's role is not a household, and "is this one eating" is a question no guest column asks. A guest row is Meal = yes unless they are marked not eating, so totalling that column counts every plate in the file. Note that this is the printed grand total plus anyone not seated yet: the sheet counts chairs, the spreadsheet counts people.

The file is named seating-chart-YYYY-MM-DD.csv, so a folder of them sorts by date.

Where the numbers come from

Dietary answers live on the RSVP (rsvps.dietary_restrictions), one entry per attending person, matched to a seat by name. Each entry is a set of booleans — vegetarian, vegan, gluten_free, nut_allergy, other (+ other_text), kids_meal, no_meal. That is the only thread tying a chair to a restriction, which is why renaming someone in the guest list carries the rename to both their chair and their dietary answer.

A vendor's answer is on the vendor's own row instead, in the same shape, so the same counting code handles both.

What it still cannot do

  • No entrée count. See "Chicken", not "no restrictions" above. Adding a meal question to the RSVP form means re-asking the households who have already answered.
  • It prints rosters, not the room. There is no drawing of the floor plan on the export — tables as they actually sit, for a planner's walk-through. The canvas is a React Flow surface whose DOM does not print, so that would be a separate renderer drawn from the table coordinates.

Both are tracked in docs/parkinglot.md in the repository.

Clone this wiki locally