Esposter

Platform

The platform area is the cross-product integration program: everything is a resource with opt-in capabilities, surfaced through one Azure-portal-like Resource Explorer at /resources. A sheet, a survey, a program, a todo list, a dashboard, an email, a webpage, and a flowchart are all the same thing to the platform — an identity row, a content blob, and a definition — differing only in which blades and commands their type declares.

The standards the platform applies live in architecture: the layer model (/docs/architecture/platform), the resource model (/docs/architecture/resources), datasets (/docs/architecture/datasets), and publishing (/docs/architecture/publishing). The pages in this area describe the product surface built on them.

Key concepts

  • Resource — one Postgres identity row + one content blob in Azure Blob + one ResourceDefinitionMap entry. Single-owner, auth-gated, one contentVersion write path.
  • Capability — a cross-cutting mechanism a type opts into: Publishable (versioned snapshot + public /view/[type]/[id]), DatasetProvider (serves columns + rows through dataset.readDataset), Portable (import/export formats), FileAssets (hosted binary assets under {id}/files/… — see resource file assets).
  • Explorer — the Azure-portal-shaped shell: Home landing, /resources/all list, marketplace-style create flow, and a resource page composing blades. See resource explorer.
  • Blade — one panel of a resource page, addressed by route segment (/resources/[id]/[[blade]]). Every resource has a built-in Overview; types add their own (Sheet: Data + Settings, Survey: Responses, Program: Setup + Status, TodoList: Items + Calendar) and editor-backed types render their editor inline in the Editor blade.
  • Dataset — the read contract that lets one resource consume another's data: a Dashboard visual binds to a DatasetReference (dashboard data binding), an Email binds one for merge fields (email personalization), and a Program both binds one as its audience and serves one as its funnel status (program resource).

Feature pages

  • Resource explorer — the shell: Home, list, create flow, resource page, blades, command bar
  • List filters & views — the /all workbench: filter pills, URL-synced state, bulk operations, column chooser, grouping, CSV export
  • Summary view — the /all List/Summary toggle: per-type count cards over a grouped count procedure
  • Resource page parity — labeled command bar with overflow, Refresh, Duplicate, type-the-name delete guard, save-conflict surface
  • Share to esbabbler — Share command posting a published resource's public link into a room you pick
  • Notifications bell — session-scoped operation-outcome toasts + app-bar bell panel
  • TodoList due reminders — web-push when a TodoList item comes due, over the scheduled-job + push subsystems
  • Global search — grouped as-you-type dropdown, Ctrl+K command palette, keyboard chords, relevance-ranked results
  • Global search relevancepg_trgm trigram index and similarity() ranking, so a typo still finds its resource
  • Favorites & recents — server-side stars and Home tabs over recently viewed resources
  • Resource tags — name:value pairs in Essentials, edited in place, filterable on /all
  • Recycle bin — soft delete with restore, permanent purge, and a 30-day timer sweep
  • Activity log — the per-resource audit trail blade, in Azure Table Storage
  • Publish history — versioned snapshot blade with per-version view and restore-to-draft
  • Shell cohesion — the shared chrome primitives (page header, breadcrumbs, empty/loading states, launcher)
  • Sheet resource — CSV/JSON/XLSX files as resources with Data + Settings blades
  • Create from file — drop a CSV/JSON/XLSX on the Sheet create form and land in a ready Data blade
  • Survey resource — SurveyJS authoring, public respondent page, responses dataset
  • Program resource — the distribution orchestrator: audience + email + survey bindings, opaque participant tokens, funnel status
  • Note resource — a rich-text document type on Tiptap: JSON at rest, publishable generateHTML read view
  • Blueprint resource — a parameterized manifest of resources: deploy one blueprint, get a fully wired set with all the right cross-references
  • Blueprint capture — Save as blueprint on selected resources: contents captured, cross-resource ids rewritten to aliases automatically
  • Survey response controls — the accepting-responses toggle and the closed state that keeps participant links alive
  • Survey response modes — Anonymous or Identified identity, enforced at the write boundary
  • Survey response management — response detail, owner delete, response count on Overview
  • Published view analytics — best-effort view counts on public reads for every publishable type
  • Dashboard data binding — visuals bound to datasets with client aggregation and publish-time snapshots
  • Email personalization — merge fields, survey invite blocks, personalized HTML export
  • Dataset row-cap warning — "showing N of M" wherever a dataset read hits the 1000-row cap
  • Email web view — Email is Publishable: save-time HTML capture, /view/email/[id] browser copy
  • Flowchart publish — Flowchart is Publishable: read-only VueFlow render at /view/flowchart/[id]
  • Resource file assets — the FileAssets capability: hosted binary assets + GrapesJS Asset Manager
  • Webpage survey invite blocks — published surveys as drag-in invite buttons in both GrapesJS editors
  • Resource Explorer consolidation — the shipped six-phase program record

Open work is in the roadmap; the Azure-portal-parity designs it references live under proposals. Ideas we chose not to pursue are under deferred (with revisit triggers) and rejected.

Shipped

  • Dataset contract — dataset.readDataset + Sheet/SurveyResponses providers
  • Dashboard visual dataset binding — reference + query per visual, client aggregation, bind-to-data form, per-visual refresh
  • Document publish lifecycle — versioned snapshots + public /view/[type]/[id] (now the Publishable capability)
  • Email personalization — merge-field blocks, survey invite blocks, per-row personalized HTML export
  • Dashboard binding polish — multi-series editing, Sheet sources; published-view OG meta tags
  • Survey distribution fixes — publishing snapshots the model; the public respondent page serves that snapshot and 404s for unpublished surveys
  • Resource Explorer consolidation (Phases 1–6) — everything became a resource behind one explorer: resources + resource_publications tables, one ResourceAssets container replacing six, createResourceProcedures factory, the explorer shell, all editors migrated to inline blades, the surveys table folded in, and every per-editor page/picker/hub deleted. Zero new dependencies and zero new Azure services across all six phases.
  • Global search overhaul — ResourceSearchMenu grouped dropdown (inline Home mount + Ctrl+K palette), localStorage recents, G-chords + ? shortcuts overlay, prefix-match ranking in readResources
  • /all list workbench — filter pills (type/status/updated), URL-synced state, bulk select + batch delete, column chooser, group-by-type, chunked CSV export, real-link name cells, skeleton/empty/error states
  • Resource page command-bar parity — labeled commands with overflow, Refresh, duplicateResource, type-the-name/delete {n} destructive guards
  • Notifications bell — session-scoped notification store, app-bar bell + single snackbar queue, G N chord, stale-contentVersion save-conflict surface
  • File resource renamed to Sheet — pg enum value, sheet router, models/components/store, and the docs area (sheet-editor, sheet-resource); no backwards compat
  • End-to-end survey funnel — the send → view → respond → analyze loop closed: survey settings (accepting-responses toggle + Anonymous/Identified response mode) enforced at one server write boundary, the Program resource issuing opaque participant tokens and serving the identity-free ProgramStatus dataset, owner-side response detail/delete/count, and best-effort view counts on every publishable type's public read. One new Postgres enum value and two new Azure Tables; no new services. The café-scenario chain is covered end to end by surveyFunnel.integration.test.ts.
  • Explorer parity smalls — /all Summary lens over a grouped countsByType, the dataset row cap surfaced as "showing N of M" in every consumer (Dataset.totalRows + countEntities), Sheet create-from-file landing in a ready Data blade, and a Share command posting a published link into an esbabbler room
  • FileAssets capability — Survey's {id}/files SAS machinery promoted onto the resource factory, adopted by Email and Webpage through a GrapesJS Asset Manager adapter (hosted images instead of base64)
  • Publish parity for the remaining visual types — Email (/view/email/[id] browser copy via save-time MJML capture) and Flowchart (read-only VueFlow render) both opted into Publishable; Sheet and TodoList stay non-publishable by design
  • Survey invite blocks in the webpage editor — the email block builder moved to a shared core with per-editor markup wrappers
  • Note resource — a rich-text document ResourceType on the existing Tiptap dependency: { doc } JSON content (source of truth at rest), a writing-kit editor blade, and a Publishable /view/Note/[id] render through generateHTML sanitized at the boundary. One pg enum value, zero new dependencies or services. Also a live test of the one-ResourceType extensibility claim — the friction it surfaced (per-type router + registration, client mutation switch arm, exhaustive blade map, and three create-flow lists) is recorded on the Note resource page.
  • Blueprint resource + capture — a parameterized manifest resource: deployBlueprint substitutes {{parameter:key}}/{{entry:key}} tokens, validates every entry against its type's contentSchema, topologically creates the wired set (with mid-deploy compensating cleanup), and captureBlueprint turns a selection of live resources into that manifest by rewriting cross-resource ids to aliases. One Postgres enum value, no new services.
  • Storage-backed explorer features — resourceFavorites + Home Recent/Favorites tabs, tags jsonb with Essentials editing and an /all pill, deletedAt soft delete with a Recycle bin and a 30-day timer purge, pg_trgm relevance ranking, and the Azure Table activity blade. Three Postgres migrations, one new Azure Table, no new Azure services.
  • Publish history blade — a capability-gated built-in blade listing every retained {id}/published/{n} snapshot from a blob prefix listing (no history table), an owner-only ?version= preview on the view route, and a restore-to-draft copying a snapshot into the working copy. No new tables or Azure services.
  • TodoList due reminders — the first platform feature on the notification stack: a post-save due-date diff enqueues one scheduled Service Bus message per new or changed (itemId, dueAt), and the SendTodoReminder function re-reads the content blob at fire time (dropping deleted or re-dated items) before web-pushing 『{item}』 is due to the owner. Stateless — no Postgres row backs the reminder; the scheduled message is the state. One new Service Bus queue, no new services.