Boardflare Notebook Changelog
Release notes and API evolution.
This changelog records public API, protocol, and runtime contract changes across Boardflare releases.
Python for Sheets removed from the repository
What changed
- Python for Sheets Removed: The Google Sheets add-on source is not in the Boardflare repository. It is archived at git tag
sheets-archive. The published Google Workspace Marketplace Editor add-on remains available and frozen on its pinned deployments, and no further updates are planned.
October 2026 release (v1.4.1)
What this release ships
- Workbook Tables: Declare editable tables with
bf.table(...). Users add, edit, and delete rows in the table, and the notebook reads the current rows through.dataframe. - Several Tables per Notebook: A notebook can declare more than one table. Each table is keyed by its name, and declaring a table again with the same name replaces the older one.
- Notebook Code Sheet Format Version 2: The
_BOARDFLAREsheet records a workbook instance ID in cellH12. See Workbook Editing.
Details
bf.tableEditor and.dataframe: Display the table as a cell’s last expression. Displaying it connects to the workbook and creates the table on its worksheet if the table is missing..dataframehas_idfirst, then the declared columns in declaration order. A checkbox isTrueorFalse. Blank text, blank booleans, and extra columns areNone, and blank number columns areNaN. A cell that reads.dataframereruns when rows change, whether the change came from the editor or from the sheet. A read covers at most 100,000 cells (rows times columns,_idincluded). Adding a row in Excel requires ExcelApi 1.15.- Tables Need Their Editor Displayed: A table that is never displayed never connects, so a cell that reads its
.dataframewaits until the editor connects. - Table Column Names:
bf.tablerejects column names that duplicate another column name regardless of case, and reserved column names. - Workbook Instance ID: The add-in writes a random UUID to
H12at the workbook’s first notebook save. It is used for analytics and is not written on open. Sheets at format version 1 load, and the next save writes format version 2.
Unreleased
- Connector Reads through
bf.inputs:bf.connector.microsoft_graph(scopes=[...])declares delegated Microsoft Graph access, andgraph.get(path, params=...)describes a GET read thatbf.inputs(...)performs. See Workbook Design: Connector reads andbf.connector. - One Sign-in per Connector: Reads through the same connector declaration share one sign-in, started with Connect in the Workbook Inputs section. Until then, the cell stops with a sign-in message.
- In-Memory Token: Microsoft Graph tokens are held in memory only, so reloading the add-in requires signing in again.
October 2026 release (v1.4.0)
What this release ships
- Reactive Inputs & Selections: Read workbook inputs with
bf.inputs(...), cell and table references withbf.ref(...), and capture active grid selections withbf.selection(...). See Workbook Design: Reading Workbook Inputs. - Pre-Bundled Packages: Import 15 curated companion packages directly in the zero-network runtime, with no dependency declarations (notebooks have no PEP 723 script block; see Imports and Dependencies). See Python Notebooks: Pre-bundled Companion Packages.
- Worksheet Code Sheet & AI Edit Loop: Inspect, modify, and reload notebook code directly in Excel through the
_BOARDFLAREworksheet and the AI edit handshake (increment cellH1, read cellH2). See Workbook Editing. - Google Sheets Add-in: Run reactive Marimo notebooks inside Google Sheets with workbook input synchronization via
bf.inputs(), manual Refresh, and pre-bundled packages.
Details
bf.selectionTable Selections: Active table selections can be tracked usingbf.selection("TableName"), returning a pandas DataFrame with the table’s headers and at most one row: the row at the user’s active cell (the cell the cursor is on), even when a larger range is highlighted. The result is empty when the active cell is outside the table’s body rows or columns, on another sheet, on the header or total row, or on a hidden or filtered row. Rows carry values rather than positions. Limits: the cursor must be on a table cell, because cells beside the table select no row; filtering that hides the active row does not refresh the value until the next selection event.- One
bf.inputsper Notebook: Enforced at most onebf.inputs(...)widget per notebook. Declaring more than one raisesRuntimeError("Only one bf.inputs(...) is allowed per notebook; use one bf.inputs(...) with all inputs"). - Notebook Source on Code Sheet: Notebook code is stored in the hidden
_BOARDFLAREworksheet (format version 1), allowing chat assistants (Copilot, ChatGPT, Claude) and external tools to edit code and workbook data together. Template provenance (templateIdandtemplateVersion) is stored directly in cellsH10:H11. Excel workbooks with a Custom XML notebook migrate on opening: the source is written to the code sheet, read back, and only then is the Custom XML part removed. The task pane has no built-in AI editor; notebook code is edited directly on the code sheet. - Zero-Network Execution Sandbox: Notebook code has no direct external network access. Dynamic package installation over the network is disabled; dependencies are served from Boardflare via pre-bundled companion packages in the Pyodide lockfile, and notebooks cannot make external HTTP requests.
- Blank header cells are
None: When reading ranges withheaders=True, blank header cells areNone, not the string"nan". This matches Python in Excel (xl()) behaviour and usespd.Index(..., dtype=object). - Duplicate headers: Range inputs containing duplicate column header labels are handled by normalizing columns by position index.
- Publication Value Property Raises RuntimeError: Accessing
.valueon abf.publish(...)result raisesRuntimeErrorpointing authors topublication.consumers. - Timezone-aware datetime error: Publishing a timezone-aware
datetimeraises an actionable error message explaining that Excel stores wall-clock values and providing a concrete conversion snippet (value.astimezone(zone).replace(tzinfo=None)).