diff --git a/docs/html-pages/example.md b/docs/html-pages/example.md
index fce5619f..6c920cc8 100644
--- a/docs/html-pages/example.md
+++ b/docs/html-pages/example.md
@@ -1,5 +1,5 @@
---
-description: A complete, minimal HTML Page example — initialize the SDK, read rows from the base, render them, and write new linked rows back on submit.
+description: A complete, minimal HTML page example — initialize the SDK in a Context module, read rows from the base, render them, and write new linked rows back on submit.
---
# Example: a form that reads and writes
@@ -15,115 +15,25 @@ flowchart LR
C --> D[on submit: batchAddRows + addRow]
```
-It assumes the three tables described in [Getting Started](getting-started.md): **Products**, **OrderItems** (link to Products), and **Orders** (link to OrderItems).
-
-## Single-file version (non-modular)
-
-This is the complete page. It loads the SDK from a CDN, so everything lives in one `index.html` — the non-modular style. Styling is omitted for clarity.
-
-```html
-
-
-
-
- Product Order
-
-
-
-
-
-
-
-
-
-
-```
+It assumes the three tables described in [Developer setup](getting-started.md): **Products**, **OrderItems** (link to Products), and **Orders** (link to OrderItems).
-!!! tip "Linking rows"
+!!! tip "Just need a single file?"
+
+ If your page is one `index.html` loading the SDK from a CDN — no build step — start
+ from the [low-code quickstart](low-code-quickstart.md) instead. This example covers the
+ **modular** developer structure: SDK imported from npm, logic split into modules.
+
+!!! note "One file or modules — a maintainability choice, not a capability one"
- Notice the two-step write: first create the `OrderItems` rows with `batchAddRows`, then read their `_id` values from `res.data.rows` and pass them as an array to the `Orders` row's link column. Link columns always take an array of linked row IDs — see [`addRow`](sdk/rows.md#add-rows).
+ Modules do not unlock anything a single file cannot do — the
+ [low-code quickstart](low-code-quickstart.md) reads and writes linked tables from one
+ `index.html` too. Splitting into modules pays off as a page *grows*: easier to
+ navigate, test and reuse. Reach for them when the file gets unwieldy, not when the
+ logic gets ambitious.
-## Modular version
+## Wrap base access in a Context class
-For anything beyond a simple page, split the logic into modules and import the SDK from the npm package. The template's `src/esm` directory does exactly this. A common pattern is to wrap all base access in a single `Context` class, keeping SDK calls out of your UI code:
+As a page grows, split the logic into modules and import the SDK from the npm package. The template's `src/esm` directory does exactly this. A common pattern is to wrap all base access in a single `Context` class, keeping SDK calls out of your UI code:
```js
import { HTMLPageSDK } from "seatable-html-page-sdk";
@@ -171,6 +81,13 @@ document.addEventListener("DOMContentLoaded", async () => {
});
```
+!!! tip "Linking rows"
+
+ Notice the two-step write in `submitOrder`: first create the `OrderItems` rows with
+ `batchAddRows`, then read their `_id` values from `res.data.rows` and pass them as an
+ array to the `Orders` row's link column. Link columns always take an array of linked
+ row IDs — see [`addRow`](sdk/rows.md#add-rows).
+
## Next steps
- [SDK Reference: Rows](sdk/rows.md) — full parameters and return shapes for every row method.
diff --git a/docs/html-pages/getting-started.md b/docs/html-pages/getting-started.md
index b4c1fcf8..b3a0cbaa 100644
--- a/docs/html-pages/getting-started.md
+++ b/docs/html-pages/getting-started.md
@@ -1,10 +1,16 @@
---
-description: Set up, develop, build and upload a SeaTable HTML Page. Walks through the simple form template with Vite, the SDK, and the uploadable ZIP package.
+description: Set up, develop, build and upload a SeaTable HTML page with the full developer toolchain. Walks through the simple form template with Vite, the SDK, and the uploadable ZIP package.
---
-# Getting Started
+# Developer setup
-This guide walks through building an HTML Page from the official [simple form template](https://github.com/seatable/seatable-html-page-template-simple-form): a form that writes submitted records into a base. By the end you will have a packaged ZIP that you can upload to a Universal App.
+This is the **developer setup**: you clone the official template and use a full JavaScript toolchain (Node.js, npm, a Vite dev server with live reload, and a build step). It suits larger or more complex pages.
+
+!!! tip "Prefer no toolchain?"
+
+ If you just want a form or a small tool, you can build a page in a visual editor with no Node.js or npm at all — see the [Low-code quickstart](low-code-quickstart.md). You can always move up to this setup later.
+
+This guide walks through building an HTML page from the official [simple form template](https://github.com/seatable/seatable-html-page-template-simple-form): a form that writes submitted records into a base. By the end you will have a packaged ZIP that you can upload to a Universal App.
The template ships the build configuration and project structure you need. It supports two development styles:
@@ -23,11 +29,11 @@ Choose the approach that fits the complexity of your page. Both produce the same
Create them in your base before running the page, or adapt the table and field names in the template's source.
-## Before you start: add an HTML Page in the app
+## Before you start: add an HTML page in the app
In your Universal App, add a new page and choose **Add HTML page**. This creates the empty page you will later upload your build to, and it surfaces the `server`, `appUuid` and `pageId` values you need for local development ([step 3](#3-configure-local-development)).
-
+
## 1. Get the template
@@ -69,11 +75,11 @@ These values are registered to `window.__HTML_PAGE_DEV_CONFIG__` and picked up b
!!! note "Where the values come from"
- `accountToken` — an API token you generate in the base in advance. See [how to create API tokens](https://seatable.com/help/create-api-tokens/).
- - `server`, `appUuid` and `pageId` — shown under **HTML Page development information** in the page's configuration (see below).
+ - `server`, `appUuid` and `pageId` — shown under **HTML page development information** in the page's configuration (see below).
-The HTML Page configuration shows these values ready to copy, alongside the upload area you will use later:
+The HTML page configuration shows these values ready to copy, alongside the upload area you will use later:
-
+
## 4. Run the development server
@@ -99,7 +105,7 @@ This single command cleans the output, runs the Vite build (into `dist`), and pa
## 6. Upload and test
-1. In SeaTable, open the configuration of the HTML Page in your Universal App.
+1. In SeaTable, open the configuration of the HTML page in your Universal App.
2. Drag the generated ZIP into the **Upload HTML page file** area (the same configuration shown in [step 3](#3-configure-local-development)).
3. Open the app preview, fill in the form, and submit it.
4. Return to the base and confirm that the corresponding records were created.
diff --git a/docs/html-pages/index.md b/docs/html-pages/index.md
index c7327551..08f8903a 100644
--- a/docs/html-pages/index.md
+++ b/docs/html-pages/index.md
@@ -1,22 +1,22 @@
---
-description: Build interactive HTML Pages for SeaTable Universal Apps. Learn how a page reads and writes base data through the seatable-html-page-sdk.
+description: Build interactive HTML pages for SeaTable Universal Apps. Learn how a page reads and writes base data through the seatable-html-page-sdk.
---
-# HTML Pages
+# HTML pages
-Starting with SeaTable 6.2, a Universal App can contain a new page type: the **HTML Page**. You upload a packaged HTML/JavaScript/CSS bundle, and SeaTable renders it as a full page inside the app.
+Starting with SeaTable 6.2, a Universal App can contain a new page type: the **HTML page**. You upload a packaged HTML/JavaScript/CSS bundle, and SeaTable renders it as a full page inside the app.
-A static bundle on its own can only display fixed content. To turn an HTML Page into a real application — a custom form, a dashboard, a calculator — it needs to read from and write to the base. That data exchange runs through the [`seatable-html-page-sdk`](https://www.npmjs.com/package/seatable-html-page-sdk).
+A static bundle on its own can only display fixed content. To turn an HTML page into a real application — a custom form, a dashboard, a calculator — it needs to read from and write to the base. That data exchange runs through the [`seatable-html-page-sdk`](https://www.npmjs.com/package/seatable-html-page-sdk).
This section is written for developers. It covers how to set up a project, how to develop and package a page, and the full SDK reference.
## Architecture
-An HTML Page is rendered in a sandboxed context inside the Universal App. It never talks to the base directly. Instead, the SDK provides a messaging bridge to the app, which performs the actual data operations.
+An HTML page is rendered in a sandboxed context inside the Universal App. It never talks to the base directly. Instead, the SDK provides a messaging bridge to the app, which performs the actual data operations.
```mermaid
flowchart LR
- A[HTML Page] -->|seatable-html-page-sdk| B[Universal App]
+ A[HTML page] -->|seatable-html-page-sdk| B[Universal App]
B -->|API| C[(Base)]
C --> B
B --> A
@@ -30,15 +30,44 @@ The SDK offers:
## Prerequisites
- SeaTable 6.2 or later.
-- A Universal App with an HTML Page added to it.
-- An API token generated in the base (used during local development).
-- Node.js and npm for building the page.
+- A Universal App with an HTML page added to it.
+
+The developer setup additionally needs Node.js and npm, and an API token generated in the base for local development. The low-code approach needs neither.
+
+## Two ways to build
+
+The same kind of page can be built two ways. Pick the one that matches how you like to work — both produce the same uploadable ZIP and use the same SDK.
+
+
+
+- :material-cursor-default-click:{ .lg .middle } __Low-code quickstart__
+
+ ---
+
+ Design the page in any visual (WYSIWYG) HTML editor, connect it to your base with ready-made copy-paste snippets, and upload. No Node.js, no npm, no dev server.
+
+ Best for forms, dashboards and small tools.
+
+ [:octicons-arrow-right-24: Low-code quickstart](low-code-quickstart.md)
+
+- :material-code-tags:{ .lg .middle } __Developer setup__
+
+ ---
+
+ Clone the official template and use a full toolchain: modular files, a live-reload dev server, npm scripts and a real build.
+
+ Best for larger or more complex pages.
+
+ [:octicons-arrow-right-24: Developer setup](getting-started.md)
+
+
## Where to start
-- [Getting Started](getting-started.md) — set up the project, develop locally, build and upload a page. We follow the official [simple form template](https://github.com/seatable/seatable-html-page-template-simple-form) end to end.
+- [Low-code quickstart](low-code-quickstart.md) — build a page with a visual editor and copy-paste snippets, no toolchain.
+- [Developer setup](getting-started.md) — set up the project, develop locally, build and upload a page. We follow the official [simple form template](https://github.com/seatable/seatable-html-page-template-simple-form) end to end.
- [SDK Reference](sdk/initialization.md) — installation, initialization, and the full API for rows, files and images.
!!! tip "Example project"
- The [`seatable-html-page-template-simple-form`](https://github.com/seatable/seatable-html-page-template-simple-form) repository contains a complete, buildable form page. It is the running example used throughout this section.
+ The [`seatable-html-page-template-simple-form`](https://github.com/seatable/seatable-html-page-template-simple-form) repository contains a complete, buildable form page. It is the running example used throughout the developer setup.
diff --git a/docs/html-pages/low-code-quickstart.md b/docs/html-pages/low-code-quickstart.md
new file mode 100644
index 00000000..f35c7164
--- /dev/null
+++ b/docs/html-pages/low-code-quickstart.md
@@ -0,0 +1,388 @@
+---
+description: Build a custom-looking SeaTable HTML page without a build toolchain. Clone one working single-file page, rename it to match your base, zip it and upload — no Node.js, no npm.
+---
+
+# Low-code quickstart
+
+You do not necessarily need Node.js, npm or a development server to build an HTML page. If you can edit an HTML file and change a few names, you can publish a **custom-looking page that reads from and writes to your base** — a styled form, a landing page, a simple read-and-submit tool.
+
+The fastest way in is not to build one from scratch. It is to **copy a page that already works and rename it** to match your base.
+
+!!! tip "What this approach is good for"
+
+ Custom-looking **forms, lists and info pages** that read and write the base in
+ simple ways — the kind of page where the value is the *design* and *simple
+ read/write*, not complex logic. If parts of your page need to **react to each
+ other** (a running total, a list that reloads when a dropdown changes,
+ conditional fields), that is a real application — jump to the
+ [developer setup](getting-started.md) instead. See
+ [When this approach stops](#when-this-approach-stops) below.
+
+## What this page does
+
+The example below is a small **event sign-up page**. It:
+
+1. reads a list of upcoming **sessions** from your base and shows them as styled cards;
+2. lets a visitor pick a session, type their name and email, and click **Sign up**;
+3. writes that as a new row in a **Signups** table, linked back to the chosen session.
+
+
+
+That is the whole loop: **read a table → show it → write a row back**. Everything else on this page is styling.
+
+## Required tables
+
+The page expects two tables. Create them as below, or rename the code (in [step 3](#3-change-the-names-to-match-your-base)) to match tables you already have.
+
+**Sessions** — the events people can sign up for.
+
+| Name | Type | Description |
+| -------- | -------- | ---------------------------------------- |
+| Title | text | the session name shown on the card |
+| Time | date | when the session takes place |
+| Duration | duration | how long it runs (comes back in seconds) |
+
+**Signups** — one row is written here per sign-up.
+
+| Name | Type | Description |
+| ------- | ----- | ------------------------ |
+| Name | text | the visitor's name |
+| Email | email | the visitor's email |
+| Session | link | link to **Sessions** |
+
+## What you need
+
+- A **text or visual HTML editor** — anything from Notepad/TextEdit to a WYSIWYG editor. You only need to change some text.
+- A way to make a **ZIP** file (built into Windows, macOS and Linux).
+- A **Universal App** where you can add an HTML page ([step 5](#5-add-an-html-page-to-your-app)).
+
+You do not need an API token for this approach — the page gets its connection from the app once it is uploaded.
+
+## The recipe at a glance
+
+Building the page is eight short steps. Each one is detailed below.
+
+1. **Copy** the code into a text editor.
+2. **Save** it as `index.html`.
+3. **Change** the table and column names to match your base.
+4. **Zip** it — with `index.html` at the top level.
+5. **Add** an HTML page to your Universal App.
+6. **Upload** the ZIP.
+7. **Grant** the page access to its tables.
+8. **Open** the page and use it.
+
+The two steps people miss are **3** (some names are changed differently from others) and **7** (skip it and the page loads blank). Both are spelled out below.
+
+## 1. Copy the code into a text editor
+
+This is the complete, working page. Copy all of it into a plain text editor (or paste it into your visual editor's code view).
+
+```html
+
+
+
+
+
+ Event sign-up
+
+
+
+
+
Upcoming sessions
+
+
+
+
+
+
+
+
+
+```
+
+## 2. Save it as `index.html`
+
+Save the file with the exact name **`index.html`**. The name matters — this is the file SeaTable opens first. You can now edit and preview it like any web page.
+
+## 3. Change the names to match your base
+
+This is the one step where you touch the code — and the part where a first page usually goes wrong. **You only change names.** The rest — the whole `loadTable` helper, the structure, the `sdk` calls — stays exactly as it is.
+
+There are **three kinds of names**, and they are changed *differently*:
+
+| In the code | What it is | How to change it |
+| ------------------------------- | ------------------------------ | -------------------------------------------------- |
+| `"Sessions"`, `"Signups"` | **table names**, in quotes | replace the text **inside** the quotes |
+| `s.Title`, `s.Time` | **columns you read** | keep the `s.` — replace **only** `Title` / `Time` |
+| `Name:`, `Email:`, `Session:` | **columns you write** | replace the whole word **before the `:`** |
+
+!!! warning "Keep the `s.`"
+
+ `s` means "the current session row"; `.Title` is the column on it. So `s.Title`
+ becomes `s.YourColumn` — **not** `YourColumn`. This one trips everybody up.
+
+!!! note "Why `Session` is wrapped in `[ ]`"
+
+ `Session` is a **link** column (it points at the Sessions table). A link column is
+ always written as a **list of row IDs**, even for a single link — that is what the
+ `[ ]` around the value is. The value inside (`...select-select").value`) is the id
+ of the chosen session.
+
+ Two more value facts, for when you adapt the page:
+
+ - **Single-select / multi-select** values come back as the option **text** you see
+ in SeaTable, not a hidden code.
+ - For every operation and value shape, see the [SDK Reference](sdk/rows.md).
+
+The look — all the HTML and CSS in `