PART 1 - Intro
PART 2 - Making it actually work
PART 3 - Some notes
Making It Actually Work (The Stuff That Matters)
The basic SOOT pattern is neat in theory, but let’s be honest—nobody wants to manually create unified table rows every time they add an event or task. That’s where automation comes in, along with some patterns I’ve developed for keeping complex docs maintainable.
Automate the Boring Parts
The cleanest approach is an “upsert” button (insert or update) that you can call from anywhere. Add this button to each source table:
coda
WithName(
[OOT].Filter(
SwitchIf(
thisTable = Events, CurrentValue.Event = thisRow,
thisTable = Tasks, CurrentValue.Task = thisRow,
thisTable = Training, CurrentValue.Training = thisRow,
false
)
).First(),
Existing,
If(Existing.IsBlank(),
AddRow([OOT], SwitchIf(
thisTable = Events, [OOT].Event, thisRow,
thisTable = Tasks, [OOT].Task, thisRow,
thisTable = Training, [OOT].Training, thisRow
)),
ModifyRows(Existing, /* update logic */)
)
)
Then create automations that run this button whenever rows are added or changed in your source tables. Boom—your unified view stays current without manual work.
Pro tip: make this button idempotent (safe to run multiple times). If you’re paranoid like me, add a nightly “healer” automation that runs through all your source tables to catch any missed cases.
VIBE: Validation That Actually Helps
Here’s a pattern I use everywhere now: Valid + Invalid Because (VIBE). Every table gets two columns:
Invalid Because (IB) collects all the things wrong with a row:
coda
ListCombine(
If(thisRow.RequiredField.IsBlank(), "Missing required field", ""),
If(thisRow.Amount < 0, "Amount can't be negative", ""),
If(thisRow.StartDate > thisRow.EndDate, "Start after end", "")
).Filter(_ != "").BulletedList()
Valid? is just thisRow.IB = ""
The magic happens when you filter all your views to Valid? = true. Users never see broken data, but you get clear diagnostics when building. Add conditional formatting to highlight invalid rows during development, then hide these columns in production.
I call it VIBE because it keeps the mood positive—broken data doesn’t make it to user-facing views, but developers can quickly see what needs fixing.
Standard Methods with std_ Buttons
Sometimes you want more than unified data—you want unified behavior. Different types of records might all need a “Complete” action, but the implementation varies by type.
Here’s the pattern: add buttons with standard names to each source table. std_Complete on Events might close the event and notify attendees. std_Complete on Tasks might update status and log completion time. Different behavior, same name.
Then on your unified table, add proxy buttons:
coda
thisRow.Source.[std_Complete]
Coda’s dot-notation automatically calls the right implementation based on which source the row points to. No branching logic needed—the dispatch happens automatically.
This gives you object-oriented-style polymorphism in a no-code tool. Pretty neat, right?
FAN: Making Abstract Tables Readable
One more pattern that’s saved me countless debugging hours: Format Abstract Names (FAN). Any table that exists mainly to connect other tables (like your unified table) needs a good display column.
Use Format() instead of string concatenation because it preserves clickable row references:
coda
Format(
"{1} {2} — {3}",
thisRow.kind_.Icon,
thisRow.Source, // This stays clickable
thisRow.Start.ToText("DD MMM")
)
Now your unified table rows show as “
Pizza Training Session — 15 Jan” with the middle part clickable to jump to the source. Infinitely more usable than “Row 47 in Unified Table.”
Maintenance and Evolution
The beauty of this pattern is how it handles change. Need a new type? Add it to Kinds, implement the unified fields, add a lookup column to your hub table. Everything else just works.
Want to change how things display? Edit the icon or template in Kinds once—every unified row updates automatically.
Need to deprecate a type? Set Active? = false in Kinds and hide it from new selections. Historical data stays valid.
Coming up in Part 3: What computer science concepts am I actually using here? How does this compare to other approaches? What are the performance and scaling considerations I should know about?
Questions for you: Are you dealing with automation across multiple docs? How do you handle permissions when source tables have different access levels? What other validation patterns would be useful to standardize?
Are you struggling with these Coda challenges?
-
Need to show Events, Tasks, and Projects in one calendar but they’re in separate tables?
-
Want to combine different table types in a single view without messy mega-tables?
-
Frustrated that Coda doesn’t have UNION functionality like SQL?
-
Looking for a way to merge multiple tables into unified boards, timelines, or dashboards?
-
Need one view for different data types that updates instantly and stays fast?
The SOOT Pattern solves this. It’s a systematic approach to create unified views across different tables without losing performance, native Coda functionality, or data integrity. Used successfully in production docs ranging from pizza shop operations to complex project management systems.
Search terms: Coda union tables, combine multiple tables, unified calendar view, merge different table types, single board for events tasks projects, Coda table consolidation