← All guided builds

Guided build · 02

Developer quickstart: model to dashboard

Load a portable revenue model, follow its named outputs into a Layout surface, and prove the UI stays synchronized after one source change.

You will finish with: A working revenue dashboard whose tiles read reactive model bindings instead of duplicating calculations.

15 minBeginnerSource checked for Grid 0.61.0Reviewed 2026-08-25
Related canonical example12-surface-revenue-dashboard.grid
Get Grid
Starter modelrevenue-dashboard-starter.gridInputs and semantic outputs, ready for the Layout configuration in step 2.

Watch it in Grid

See the workflow before you build it.

Follow the finished interaction, then use the written steps below to build and inspect it yourself.

Companion film

One truth, four lenses

Flip the same portfolio model through Source, Author, Debug, and LaTeX while its live results remain unchanged.

21 secGrid 0.61.0
Open film page
On this page

What you will build

A small revenue model with two named outputs and a Layout dashboard. The formulas remain the backend; the surface only presents their current values.

1. Load the model layer

Download the starter model above, or open the canonical Revenue Dashboard example. Its model layer begins with five monthly values and an open-pipeline value:

MonthlyRevenue = [120000, 135000, 142000, 150000, 168000]
Pipeline = 186000
Forecast IS currency = SUM(MonthlyRevenue#) + Pipeline
AverageMonth IS currency = AVERAGE(MonthlyRevenue#)

Checkpoint: Forecast = 901,000 and AverageMonth = 143,000.

MonthlyRevenue# names the complete spilled array. Forecast and AverageMonth are semantic bindings that a sheet, API, rule, or surface can read without reproducing either formula.

2. Add the presentation boundary

The complete example declares a Layout surface:

Dashboard!type = "layout"

Its tiles bind to model outputs:

[[tiles.static]]
title = "Forecast"
formula = "=Forecast"

[[tiles.static]]
title = "Average Month"
formula = "=AverageMonth"

Checkpoint: the dashboard shows Forecast 901,000 and Average Month 143,000.

The configuration chooses labels and placement. It does not calculate revenue.

3. Prove the binding is live

Change the last monthly value from 168000 to 180000 and leave the tile configuration untouched.

Checkpoint: Forecast = 913,000 and AverageMonth = 145,400; both dashboard tiles show the same new values.

The change moved through one path: source array → named formulas → bound tiles.

4. Add one backend KPI

Before END MODEL, add:

Annualized IS currency = AverageMonth * 12

With the changed monthly value, Annualized = 1,744,800.

Add a third tile inside Dashboard!config:

[[tiles.static]]
title = "Annualized Run Rate"
x = 8
y = 0
w = 4
h = 2
formula = "=Annualized"

Checkpoint: the new tile shows 1,744,800; the formula exists once, in the model.

Try it yourself

Change Pipeline from 186000 to 200000.

Checkpoint: Forecast = 927,000; AverageMonth = 145,400; Annualized = 1,744,800.

Explain why the pipeline edit changes the forecast tile but not the average-month or annualized tiles.

You are done when

  • The two original outputs match the baseline checkpoint.
  • One monthly edit updates both formulas and both bound tiles.
  • The Annualized calculation lives in Grid source rather than Layout configuration.
  • You can name the source, model, and presentation layers.
Build statusReached the expected checkpoint?