Skip to content

Support Notion page tables across all layouts - #137

Open
mvletter wants to merge 2 commits into
usetrmnl:masterfrom
mvletter:agent/notion-page-table-support
Open

Support Notion page tables across all layouts#137
mvletter wants to merge 2 commits into
usetrmnl:masterfrom
mvletter:agent/notion-page-table-support

Conversation

@mvletter

@mvletter mvletter commented Aug 18, 2026

Copy link
Copy Markdown

Summary

  • Add support for rendering table blocks in Notion pages.
  • Fetch each table's table_row child blocks from the Notion API.
  • Render tables consistently across full, half-horizontal, half-vertical, and quadrant layouts.
  • Preserve existing page rendering and overflow behavior for pages without tables.
  • Isolate table API failures so one unavailable table does not fail the entire page.

User-visible behavior

Notion page tables now support:

  • Column headers and row headers as configured in Notion.
  • Equal-width columns and equal-height rows.
  • Multi-line cell content with explicit ellipsis when text does not fit.
  • Scale-aware typography and spacing using the TRMNL Framework variables.
  • An importance convention: when any line in a cell starts with !, that cell is rendered with inverse colors.
  • Headings and other page blocks above a table without TRMNL's column overflow engine reordering them.
  • A single-column presentation for pages containing a renderable table; the Multi-Column Display setting remains unchanged for pages without tables.

Compact layouts show an explicit +N rows or +N cols summary instead of silently dropping content.

Layout limits

The limits below describe displayed rows and columns, including any overflow summary:

Layout Displayed rows Displayed columns
Full 12 8
Half horizontal 6 8
Half vertical 10 4
Quadrant 6 4

The full layout provides the largest table preview. Every layout reports when the source exceeds its available rows or columns.

Implementation notes

  • Table rows are fetched through get_page_blocks(table_id, page_size: 100).
  • Child responses are memoized per table id for the lifetime of the plugin instance.
  • Nil responses and per-table API exceptions degrade to an empty table while leaving other page blocks available.
  • Non-table_row children are ignored.
  • Notion's has_more state is preserved; a trailing + in a row summary marks the displayed count as a lower bound.
  • Rich-text fragments in each cell are combined into plain text.
  • Rows are normalized to Notion's declared table_width:
    • missing cells are padded;
    • excess cells are discarded;
    • the widest row is used as a fallback when table_width is absent.
  • Tables use semantic <table>, <thead>, <tbody>, <th>, and <td> markup.
  • CSS Grid is applied to the semantic table markup to guarantee equal row and column distribution.
  • Text and spacing follow --text-ui-scale and --content-scale.
  • Existing framework-managed columns remain unchanged for pages that do not contain tables.

Validation

  • Ruby syntax validation passes for lib/notion/notion.rb.
  • All Notion ERB templates compile successfully.
  • Targeted rendering checks cover:
    • child-row extraction;
    • nil responses and API exceptions;
    • per-table memoization;
    • malformed rich-text fragments;
    • rich-text combination;
    • emoji stripping;
    • row padding and truncation;
    • column and row headers;
    • importance highlighting;
    • exact layout boundaries;
    • row and column overflow summaries;
    • table and non-table page containers.
    • empty-table fallback to the framework overflow container;
    • pagination-aware lower-bound summaries.
  • Official trmnlp lint passes for the parity fixture.
  • All four layouts were rendered and visually inspected on the original 800×480 TRMNL dimensions.
  • TRMNL X was tested at 1872×1404 with both enlarged content scale and enlarged text scale.

Rollout note

This repository mirrors the native plugin implementation. If the production source of truth remains the TRMNL core repository, the corresponding change should be applied or synced there before announcing table support.

Help Center update required

The current Notion Help Center article still lists tables and their child blocks as unsupported and recommends avoiding tables.

When this change is deployed, please update that article using the copy below.

Ready-to-publish Help Center changes

1. Add after the “Page Display Type” section

Tables

Tables on Notion pages are supported. TRMNL fetches the rows belonging to a top-level table block and distributes the rows and columns evenly across the available screen space.

Supported table features include:

  • Column headers and row headers configured in Notion
  • Multi-line text within cells
  • Equal-width columns and equal-height rows
  • Scale-aware rendering across supported TRMNL devices
  • Important-cell highlighting: start any line in a cell with ! to display that cell using inverse colors

The Page Item Limit controls the number of top-level page blocks fetched. Table rows are fetched separately, up to 100 rows per table. If Notion reports additional rows beyond that response, the overflow summary uses a trailing + to indicate that its count is a lower bound.

Pages containing a renderable table use a single-column presentation so headings and table geometry remain in source order. The Multi-Column Display setting continues to apply to pages without tables.

The full-screen layout provides the largest table preview. Smaller mashup layouts display a more compact preview. When rows or columns do not fit, the final displayed row or column reports the omitted amount using +N rows or +N cols.

Long cell content may be shortened with an ellipsis to keep the table within the available screen space.

2. Replace “Notion Block Support Details” with

Notion Block Support Details

The plugin fetches and displays most top-level Notion page blocks, including text, headings, lists, images, and tables.

  • Nested Content

    • Nested block children are generally not displayed.
    • table_row children belonging to a supported top-level table block are fetched and displayed.
    • Children inside toggle blocks are not displayed.
    • Tables nested inside another block are not displayed.
  • Unsupported Types

    • table_of_contents
    • unsupported types returned by the Notion API
    • synced_block
    • breadcrumb
    • column_list
  • Links

    • Some links may not display properly, particularly links to other Notion pages. This depends on the response provided by the Notion API.
  • Numbered Lists

    • Numbers are not displayed in numbered lists due to API limitations. Numbered lists appear as bullet points instead.
  • People Mentions

    • People mentions display as @anonymous due to Notion API privacy restrictions.
  • Emojis

    • Emojis are stripped from text due to TRMNL platform limitations.
    • This also applies to text inside table cells.

3. Replace “Best Practices” with

Best Practices

  • Use simple, flat page structures for the most predictable results.
  • Keep table cell content concise.
  • Use the full-screen layout for the largest available table preview.
  • Use mashup layouts when a compact table preview is sufficient.
  • Use ! at the beginning of a line only when the entire cell should be highlighted.
  • Consider using a Notion database instead of a table when you need filtering, sorting, or structured properties.

@mvletter
mvletter marked this pull request as ready for review August 18, 2026 08:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant