Skip to content

Assessment: Airtable Interface Designer Pattern for ObjectUI #823

@hotlong

Description

@hotlong

1. Understanding the Airtable Pattern

From the screenshots, Airtable's Interface Designer implements a Design → Stage → Publish workflow:

image2List View Interface: A customer management list page with a left sidebar navigation, configurable view (Sort, Filter, Group), and a right-hand property panel controlling Page type, Data binding, Appearance, and User Actions.

image1Dashboard Interface: A performance dashboard with KPI cards, charts (Line, Bar, Pie), and a right-hand property panel for chart configuration (Source, Axes, Appearance).

Key observations from both screenshots:

Feature Detail
Publish Status "No changes · Last published Feb 21, 2026" / "Interface has unpublished changes · Last published Feb 18, 2026"
Workflow Design (edit mode, blue dashed borders) → Stage (preview as "Yourself") → Publish (red button)
Navigation Hierarchical sidebar: App → Sections → Pages
Right Panel Context-aware property inspector (changes based on selected element)
View Types List, Chart, Dashboard (composable elements)
Share Model "Share interface" — published interfaces are shared independently

2. Evaluation: Do We Need This?

YES — This is a Core Requirement

This is not a "nice-to-have". The Design → Stage → Publish pattern is essential for ObjectUI's positioning as a "JSON-to-Shadcn" SDUI engine. Here's why:

Reason Explanation
Enterprise Readiness No enterprise will deploy UI changes directly to production. A staging/publish gate is table stakes.
Our Differentiator Airtable's Interface Designer proves the market wants visual, metadata-driven UI building. We provide the same experience but with Shadcn-quality output instead of Airtable's locked-in components.
Schema-Driven by Nature Our JSON protocol (UIComponent) already IS the "staged" artifact. We just need to formalize the lifecycle around it.
Backend Agnostic Unlike Airtable (tied to its own DB), we can connect to any data source — making our version more powerful.

Risk if we DON'T implement:

  • ObjectUI becomes "just a renderer" — a commodity.
  • No competitive moat against Retool, Appsmith, or ToolJet.

3. Architecture Design: Interface Lifecycle Protocol

3.1 The Three-Phase Lifecycle

┌─────────┐     save      ┌─────────┐    publish    ┌─────────────┐
│  DESIGN │ ────────────► │  DRAFT  │ ────────────► │  PUBLISHED  │
│  (edit) │               │ (staged)│               │ (immutable) │
└─────────┘               └─────────┘               └─────────────┘
     ▲                         │                          │
     │          revert         │       rollback           │
     └─────────────────────────┘◄─────────────────────────┘
Phase Description Storage
Design Active editing. Blue dashed borders (as in screenshots). Auto-saved to draft. Mutable draft record
Draft (Staged) Preview-ready snapshot. "Interface has unpublished changes" banner. Versioned draft snapshot
Published Immutable, live version. "Last published Feb 21, 2026". End-users see this. Immutable version record

3.2 Protocol Additions to @objectstack/spec

Let me first check the current state of both repositories:Now let me look at the existing UI protocol schemas in the spec repo and the current packages structure in objectui to understand the current state:Now let me dig deeper into the specific interface and designer-related schemas and the gap analysis document to understand the current state of the publish/staging flow.Now let me check the current state of the app.zod.ts in the spec repo since the gap analysis document mentions it was superseded, and also look at the plugin-designer package for the existing design-time tooling:Now I have a comprehensive picture of both repositories. Let me synthesize this into a thorough assessment.


Assessment: Airtable-Style App Design Pattern for ObjectStack

Overview: What You're Asking

Based on the Airtable screenshots (Image 1: Customer List Interface with Grid/Tabs, Image 2: Performance Dashboard with Charts), you're evaluating the Design → Stage → Publish lifecycle pattern — specifically:

  1. Design Mode — Drag-and-drop interface builder with right-panel property inspector
  2. Staging — "Unpublished changes" state where edits are buffered before going live
  3. Publish — One-click deployment to end-users (Airtable's red "Publish" button)

1. Current State Assessment

✅ What's Already Done (Spec Protocol — objectstack-ai/spec)

The spec repo has extensive schema coverage for the Airtable Interface model. Per the gap analysis doc:

Area Status Schema Location
Interface as first-class entity InterfaceSchema in src/ui/interface.zod.ts
16 page types (grid, list, dashboard, kanban, etc.) PageTypeSchema in src/ui/page.zod.ts
Element palette (text, number, image, divider, button, filter, form, record_picker) PageComponentType extensions
Per-element data binding ElementDataSourceSchema
Record Review workflow RecordReviewConfigSchema
Free-form canvas BlankPageLayoutSchema
Builder config (snap, zoom, palette, layers) InterfaceBuilderConfigSchema
Sharing & embedding SharingConfigSchema, EmbedConfigSchema
Interface page config (hierarchy, filters, appearance) InterfacePageConfigSchema
App → Interface navigation bridge App.interfaces[], InterfaceNavItemSchema

❌ What's Missing — The Draft→Published Lifecycle

This is the critical gap. The Airtable screenshots clearly show:

  • Image 1: "No changes · Last published Feb 21, 2026" — a clean published state
  • Image 2: "Interface has unpublished changes · Last published Feb 18, 2026" — a dirty draft state with "All changes saved" auto-save

This versioning/staging/publish lifecycle is explicitly listed as a Phase D (v4.1) TODO in the roadmap:

"Interface versioning (draft → published → archived lifecycle)"Section 7.4

❌ What's Missing in ObjectUI (Runtime — objectstack-ai/objectui)

The objectui repo has the AppCreationWizard (4-step wizard for creating apps) and WorkflowDesigner with save/publish buttons, but lacks:

Gap Description
Interface Builder UI Drag-and-drop canvas is not built (confirmed: "Implement Studio Interface Builder UI — runtime task")
Draft/Publish state management No useDesignerState() hook or store for tracking dirty/clean/published states
Auto-save mechanism Airtable auto-saves all design changes to a draft — no such mechanism exists
Publish flow No "Publish" button that snapshots current draft to a published version
Version comparison No diff between published and draft versions
Preview mode DesignPreviewSchema defined in spec but not built in runtime

2. Recommended Architecture for Design → Stage → Publish

2.1 Protocol Layer (spec repo)

We need a new Interface Versioning Protocol. Here's the proposed schema:

// Proposed: packages/spec/src/ui/interface-lifecycle.zod.ts

import { z } from 'zod';

/**
 * Interface Lifecycle Status
 * Models Airtable's "No changes / Unpublished changes / Last published" states.
 */
export const InterfaceLifecycleStatus = z.enum([
  'draft',       // Never published, work in progress
  'published',   // Live version matches last edit (clean)
  'modified',    // Has unpublished changes (dirty)
  'archived',    // Soft-deleted / historical
]);

/**
 * Interface Version Snapshot
 * Immutable snapshot of an interface at a point in time.
 */
export const InterfaceVersionSchema = z.object({
  /** Version number (auto-incrementing) */
  version: z.number().int().min(1),

  /** Snapshot of the full interface definition (pages, elements, config) */
  snapshot: z.any().describe('Serialized InterfaceSchema at publish time'),

  /** Who published this version */
  publishedBy: z.string().optional(),

  /** When this version was published */
  publishedAt: z.string().datetime(),

  /** Optional release note */
  changeNote: z.string().optional(),
});

/**
 * Interface Draft State
 * Tracks the working copy and its relationship to the published version.
 */
export const InterfaceDraftStateSchema = z.object({
  /** Current lifecycle status */
  status: InterfaceLifecycleStatus,

  /** Working copy (auto-saved, mutable) */
  draft: z.any().describe('Current working InterfaceSchema'),

  /** Last published version number */
  publishedVersion: z.number().int().optional(),

  /** Last published timestamp */
  lastPublishedAt: z.string().datetime().optional(),

  /** Last auto-save timestamp */
  lastSavedAt: z.string().datetime().optional(),

  /** Whether the draft differs from the published version */
  hasUnpublishedChanges: z.boolean().default(false),

  /** Version history (ordered newest first) */
  versionHistory: z.array(InterfaceVersionSchema).optional(),
});

2.2 Runtime Layer (objectui repo)

A. State Store (Zustand)

// Proposed: packages/plugin-designer/src/stores/useInterfaceDesigner.ts

import { create } from 'zustand';

interface InterfaceDesignerState {
  // === Lifecycle ===
  status: 'draft' | 'published' | 'modified' | 'archived';
  publishedVersion: number | null;
  lastPublishedAt: string | null;
  lastSavedAt: string | null;
  hasUnpublishedChanges: boolean;

  // === Draft ===
  draft: InterfaceSchema | null;
  
  // === Actions ===
  /** Update draft (triggers auto-save debounce) */
  updateDraft: (partial: Partial<InterfaceSchema>) => void;
  
  /** Publish current draft → new published version */
  publish: () => Promise<void>;
  
  /** Revert draft to last published version */
  revertToPublished: () => void;
  
  /** Load interface (hydrate from server) */
  loadInterface: (id: string) => Promise<void>;
}

B. Auto-Save Hook

// Proposed: packages/plugin-designer/src/hooks/useAutoSave.ts

/**
 * Auto-save hook that debounces draft changes and persists them.
 * Mirrors Airtable's "All changes saved" behavior.
 */
export function useAutoSave(draft: InterfaceSchema | null, options?: {
  debounceMs?: number;  // default 2000
  onSave?: (draft: InterfaceSchema) => Promise<void>;
  onStatusChange?: (status: 'saving' | 'saved' | 'error') => void;
}) {
  // Debounced save logic
  // Returns: { saveStatus: 'saving' | 'saved' | 'error', lastSavedAt: Date | null }
}

C. Publish Flow UI

The top bar should mirror Airtable's pattern:

┌─────────────────────────────────────────────────────────────────┐
│  Previewing as: [Yourself ▼]                                    │
│                                                                 │
│  [status indicator]                         [Publish] [Share ▼] │
│  "Interface has unpublished changes ·                           │
│   Last published Feb 18, 2026"                                  │
└─────────────────────────────────────────────────────────────────┘

States to render:

  • Clean: "No changes · Last published {date}" — Publish button disabled
  • Dirty: "Interface has unpublished changes · Last published {date}" — Publish button red/active
  • Saving: "All changes saved" indicator (green checkmark)
  • Never published: "Draft · Never published" — Publish button active

2.3 Data Flow

┌──────────────┐     Auto-Save (2s debounce)     ┌──────────────┐
│  User edits  │ ──────────────────────────────── │ Draft (DB)   │
│  in Designer │                                  │ status:      │
│              │                                  │ 'modified'   │
└──────────────┘                                  └──────────────┘
                                                         │
                                                   [Publish] click
                                                         │
                                                         ▼
                                                  ┌──────────────┐
                                                  │ Published    │
                                                  │ Version N+1  │
                                                  │ (immutable   │
                                                  │  snapshot)   │
                                                  └──────────────┘
                                                         │
                                                    Rendered to
                                                    end-users
                                                         │
                                                         ▼
                                                  ┌──────────────┐
                                                  │  Runtime     │
                                                  │  Renderer    │
                                                  │  (published  │
                                                  │   version    │
                                                  │   only)      │
                                                  └──────────────┘

3. Gap-by-Gap Implementation Plan

# Gap Where Effort Priority
L1 InterfaceLifecycleStatus + InterfaceVersionSchema specsrc/ui/interface-lifecycle.zod.ts 1 week 🔴 P0
L2 InterfaceDraftStateSchema with version history spec → same file 1 week 🔴 P0
L3 useInterfaceDesigner Zustand store objectuipackages/plugin-designer 2 weeks 🔴 P0
L4 Auto-save hook (useAutoSave) objectuipackages/plugin-designer 1 week 🔴 P0
L5 Publish flow UI (top bar + confirmation dialog) objectuipackages/plugin-designer 1 week 🔴 P0
L6 Version history panel (view past snapshots) objectuipackages/plugin-designer 1 week 🟡 P1
L7 Revert to published version objectuipackages/plugin-designer 3 days 🟡 P1
L8 Diff view (draft vs published) objectuipackages/plugin-designer 2 weeks 🟡 P1
L9 "Preview as" user impersonation objectuipackages/plugin-designer 2 weeks 🟡 P1
L10 Interface Builder drag-and-drop canvas objectuipackages/plugin-designer 6–8 weeks 🔴 P0

Total estimated effort: ~12–16 weeks for full Airtable-parity design/stage/publish lifecycle.


4. Verdict: Is It Needed?

Yes, absolutely — this is a P0 strategic requirement.

Reasoning:

  1. It's the Add metamodel interfaces for ObjectQL/ObjectUI contract #1 differentiator for low-code platforms. Every competitor (Airtable, Retool, Appsmith, Salesforce Lightning) has a design → preview → publish flow. Without it, ObjectUI is a component library, not an app builder.

  2. The spec is already 80% there. Phases A, B, and C of the Airtable gap analysis are largely complete in the spec repo. The missing 20% is the lifecycle protocol (draft/publish) and the runtime builder UI.

  3. It directly maps to your screenshots. Both images show the exact UX pattern — the top bar with publish state, right-panel property inspector, left sidebar navigation tree — all of which have spec schemas but no runtime implementation.

  4. The existing plugin-designer package is the natural home. It already has AppCreationWizard, which proves the wizard/design pattern. Extending it with the Interface Builder + Publish flow is architecturally clean.

How to Prioritize

Phase What Timeline
Phase 1 Define InterfaceLifecycleStatus protocol in spec. Build useInterfaceDesigner store + auto-save + publish flow in objectui. 4 weeks
Phase 2 Build Interface Builder canvas (drag-and-drop elements from palette, property panel). This is the biggest chunk. 6–8 weeks
Phase 3 Version history, diff view, preview-as-user, revert. 4 weeks

Would you like me to create issues in one or both repos to track this work?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions