Mobile-compatible Block UI
Build one standard or custom Block interface that stays usable in 320-pixel phone viewports through desktop.
Mobile-compatible Block UI
Build one Block contract for every size. Inputs, outputs, state, actions, permissions, and runtime do not change when the interface becomes compact. StillMade reorganizes standard controls automatically and keeps custom views in the existing opaque sandbox.
Standard UI
Prefer manifest.ui and manifest.uiLayout. The host owns field sizing, focus, touch targets, stacked preview/results, tab overflow, safe-area spacing, and software-keyboard behavior. Use uiLayout only to group complete inputs and outputs; do not create a second mobile manifest or split an editor into tiny Blocks.
Tabs and sections must retain every essential input and output. A compact layout may put secondary tools behind a labelled section or sheet, but the primary action and focused field must remain reachable. Resizing the preview does not run the Block and must not reset its values, selection, state, progress, or result.
Custom UI
Custom HTML, CSS, and JavaScript continue to use view and StillMade.run. Design from the view container rather than a device name:
.workspace { container: block-workspace / inline-size; min-width: 0; }
.layout { display: grid; grid-template-columns: minmax(0, 2fr) minmax(240px, 1fr); }
@container block-workspace (max-width: 600px) {
.layout { grid-template-columns: minmax(0, 1fr); }
}The sandbox supplies viewport-fit, safe-area padding, readable form defaults, 44-pixel ordinary controls, media containment, and focus styling. Authored CSS still owns specialized workspace layout. A 320 CSS-pixel phone viewport leaves less than 320 pixels inside the host's preview gutters. Size from the embedded view's actual container, avoid a 320-pixel minimum width, wrap long labels, and isolate intentional canvas/timeline panning from the surrounding toolbar. Provide visible buttons or menus for actions otherwise available by hover, drag, right-click, or keyboard shortcut. Label fields and announce loading, errors, and completed output with role="status", role="alert", or aria-live as appropriate. For deterministic custom-view checks, set data-stillmade-state="loading", "error", or "success" on the visible result area as each state occurs. The browser profile runs the local success fixture, then injects a local executor failure to exercise the same view's error path without calling a provider. Standard controls receive the same failure and must show their error result. A permanently mounted live region does not demonstrate that an error was actually shown. If the test never reaches a state, phone support remains unverified rather than inferred.
The maintained examples/custom-interface.stillmade.json demonstrates one custom workspace whose settings and result stack from the same state and action contract.
For deterministic browser checks, mark a custom form control with data-stillmade-input="portName" so the phone profile can enter the package's test fixture through the real UI before pressing its run action. This marker does not change the Block's input contract or grant access to host services. For a text-bearing object fixture such as {brief:{text:"…"}}, the profile enters its text into the marked text field. Mark the primary button with data-stillmade-action="run" when the view has more than one button. The existing data-stillmade-share marker is also recognized for shared text fields. A custom view without a reachable mapped control must not be counted as having passed its fixture's success interaction.
Preview and authoritative validation
The Create preview includes Compact (320), Phone (390), Tablet (768), phone landscape (844 × 390), and Desktop (1280) container presets. Changing a preset only changes available space. Its quick check helps find immediate host overflow and small touch targets; imported and published packages still run the authoritative profile in the real Block/Project Type host.
The SDK testPlatforms gate records the exact package digest plus SDK, renderer, and check versions. A trusted browser adapter covers Light, Dark, and White at 320, 390, 768, 1280, and phone landscape. It checks the main touch task, empty, populated, loading, error, success, long-label and enlarged-text states, and continuity through resize/rotation and panel toggles. Custom views must visibly enter each claimed state during the check; source markup alone is not evidence of a working error path. Fixture execution is local or mocked; the mobile UI profile never authorizes a provider call or spends credits.
Reports supplied inside a package are ignored. A changed package or changed renderer/check version needs a new report. Failures name the affected view, control, and CSS size and remain repairable in draft preview. Passing the profile does not make an unavailable desktop binary, local GPU, provider, or credential available on a phone; runtime capability checks remain separate.
For a local preview build, node scripts/platform-tests/run.mjs --engine=chromium --require-complete uses that same trusted embedded profile and saves per-size captures and a digest-bound report. Firefox and WebKit runs are exploratory layout checks; they cannot supply the profile's state and continuity evidence. A report from any local command does not grant a Marketplace support claim or replace StillMade's server-owned import review.
Before public release, StillMade also smoke-tests representative shared UI in real iOS Safari and Android Chrome. Gesture-heavy custom editors require a focused real-device check. Those operational checks complement the deterministic gate; they are not inferred from an author claim.