DuskByte

Google Workspace Add-on · Google Sheets

Turning a spreadsheet into the front end of a data warehouse

The Sheets add-on that owns the data side: comparable-property records, the schema that defines them, bulk import from external sources, and the map definitions the report renders.

Binny Chanchal, Founder & Principal Architect

Client
StartDeck
Surface
Google Sheets sidebar and dialogs
Stack
TypeScript, Google Apps Script (V8)
Data
Per-tenant BigQuery, accessed via the platform
Status
In production, actively developed

Problem

Every appraisal rests on comparable properties: recent sales, leases, and expense records that justify a valuation. That data is the firm's real asset. It arrives from external providers in inconsistent formats, accumulates over years, and has to be searchable, editable, and defensible.

Warehouses are good at holding it. Appraisers are not warehouse users. They work in spreadsheets, and any system that made them leave one to query comps would go unused, the same constraint that shaped the platform, applied one layer down.

The spreadsheet had to become a legitimate interface to a warehouse, without the appraiser ever knowing that is what they were using.

Approach

Warehouse access through the platform, not from the add-on. Every data operation goes through the core platform. The add-on renders the interface and keeps the sheet in step with the schema; the platform owns credentials, query cost, tenancy boundaries, and the authority to say what a valid record is. The rule is deliberate: a constrained, hard-to-update client should never hold anything security-sensitive or business-critical. Both add-ons follow it, by design rather than by accident.

The schema is data, not code. The appraisal data schema lives in a centrally-hosted spreadsheet, loaded and cached at runtime. It is not compiled into either add-on.

That single decision pays repeatedly. The schema can be extended without a release, in a tool the domain experts already use. One schema drives different field subsets per record type, so records that overlap share definitions and diverge only where they genuinely differ. And because the same definition flows through to the report, a field is described once rather than three times in three places that can drift apart.

Importing data that was never meant to fit. Comp data arrives as whatever the source provides. The import subsystem maps arbitrary incoming columns onto the schema, flags unmapped and invalid columns visually in the sheet, and walks the user through reconciling free-text values against the permitted options.

Two constraints shaped it. Rows are copied in bounded chunks so a large import cannot hit the execution ceiling mid-write. And because the reconciliation flow spans several dialogs, and Apps Script keeps no memory between them, the work in progress is persisted as a queue that survives each interaction. The user sees a conversation; the runtime sees a series of unrelated invocations.

Maps: defined here, drawn there. Location maps are a good illustration of the seam between the two add-ons. Tables does not generate map images. It captures the appraiser's selection of markers, addresses, and map style, validates it, and writes it into the sheet as a structured, named block. Writer picks that block up at merge time and renders the actual image into the report.

Neither add-on calls the other. The spreadsheet is the contract, which means either can be deployed, debugged, or rewritten without touching the other.

Beyond this client

Push authority to the component that can change. Apps Script add-ons are slow to deploy, hard to observe, and tightly quota-limited. Anything that needs to evolve, whether schema, credentials, or business rules, belongs on the server, and the add-on should be as close to a rendering layer as the product allows.

Letting the schema live in a spreadsheet sounds like a shortcut. It was the opposite: it put the definition where the domain experts could maintain it, and removed a deploy from the critical path of every change.

The seam

One platform, two add-ons, and the seam that holds them together

StartDeck automates commercial appraisal reports. It is not one product but three codebases: a central platform that owns identity, data, and billing, and two independent Google Workspace add-ons that do the actual editing work inside Docs and Sheets.

The add-ons never call each other. What connects them is a shared spreadsheet: one prepares the data, the other renders it into the report. That seam is the architecture, and everything interesting follows from it.

Questions

Common questions

Can a Google Sheets add-on query BigQuery?
It can, but it should not hold the credentials to do so. Route data operations through a server that owns credentials, query cost, and tenancy boundaries, and keep the add-on as a rendering layer.
How do you keep state across multiple Apps Script dialogs?
Apps Script keeps no memory between invocations, so multi-step flows need work in progress persisted as a queue that survives each interaction.
How do you import large datasets without hitting the Apps Script time limit?
Copy rows in bounded chunks so a large import cannot be killed mid-write.

Platform metrics as reported by the client. Add-on performance figures are deliberately omitted pending verification against a production-scale report.

Have something like this to build?

Book a call and tell us where you're stuck. We'll tell you honestly what it takes.