Repository navigation
Live builder updates in Tiny Sunny with @base44/platform - #50
Merged
Merged
Conversation
amitbardos
force-pushed
the
amitb/platform-package
branch
from
October 4, 2026 08:59
cfb4048 to
eeb4267
Compare
amitbardos
changed the base branch from
codex/white-label-builder-socket
to
main
October 4, 2026 08:59
amitbardos
force-pushed
the
amitb/platform-package
branch
from
October 4, 2026 13:05
eeb4267 to
8eaf865
Compare
✅ Deploy Preview for base44-platform-starter ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
✅ Deploy Preview for sunny44-builder ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
amitbardos
force-pushed
the
amitb/platform-package
branch
from
October 4, 2026 13:41
8eaf865 to
2309245
Compare
Replace chat polling in examples/white-label-minimal with the Base44 platform socket, through the Platform SDK (@base44/platform). Kept minimal on purpose: - server: lib/base44/socket-session.ts opens a read-only session for one app with the workspace key, behind the existing sign-in and ownership checks (openBuilderSession action). - browser: lib/chat/live-updates.ts subscribes; the snapshot replaces the chat, then message.updated / message.removed / app.status_changed. - React: components/useBuilderSocket.ts, same interface as the polling hook it replaces, so the UI is unchanged. Socket messages are converted to the shape the existing chat UI renders (lib/chat/live-messages.ts). Production follow-ups (closing the session, history beyond 50 messages, image placeholders) are listed in the README. Based on Oz Sayag's work in #31. Co-Authored-By: Oz Sayag <ozs@wix.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
amitbardos
force-pushed
the
amitb/platform-package
branch
from
October 4, 2026 13:41
2309245 to
5037c5a
Compare
amitbardos
marked this pull request as ready for review
October 4, 2026 14:04
This was referenced Oct 4, 2026
amitbardos
added a commit
that referenced
this pull request
Oct 4, 2026
- client.ts is ordered by the six steps of "The build turn", one commented section per step with a link to the docs - Publish button on the ready card: deploy, then read back the published URL and link to it (step 6), with a browser test - remove the unused REST conversation read (getConversation and the backward pager); the chat arrives over the live-updates socket since #50 - README opens with a table from each docs page to the file that implements it Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
amitbardos
added a commit
that referenced
this pull request
Oct 4, 2026
* Tiny Sunny: slim the integration files so they read easily
- api-handler: one action table replaces the switch; unread fields are rejected
- client and identity share one fetch helper (http.ts)
- static preview derivation and probe move to static-preview.ts; the probe
cache is now module-level, so it survives across requests
- smaller config check, named page size, README copy list updated
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Tiny Sunny: simplify the UI components
- Workspace: derive the active name from the stage app, drop an unused ref,
plain async load, connect call moves to builder-api
- Question: one buildPayload helper (null while empty) and a toggle helper
- Builder: one composerDisabled flag for the guard and the composer
- Base44Preview: drop the onStatusChange prop nobody passed
- remove unused CSS rules and an unreachable ToolActivity branch
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Tiny Sunny: make client.ts a pure 1:1 Base44 wrapper
- encode app IDs in every path instead of relying on the handler's check
- status hints move to http.ts, next to the transport
- static preview is Tiny's own derivation, so it moves to app-service
- share the conversation page size with the browser paging helper
- link the Base44 OpenAPI spec from the client and the README
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Tiny Sunny: re-mint service-user tokens instead of refreshing them
- the stored token is a cache: reuse it until a minute before expiry, then
mint a new one with the workspace key (same approach as main Sunny's remint)
- drops the OAuth refresh flow and the row lock (identity-repository.ts)
- one workspace key; .env.example and README name the two scopes it needs
- connection status returns only { linked }
- Disconnect button in the topbar; disconnect still revokes the refresh token
and keeps the service user so reconnecting restores the same apps
- README: mint rate limit and encrypt-at-rest note
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Tiny Sunny: use the documented single-account model
Base44's tenancy docs describe one integration account that owns every app,
called with its personal access token. Tiny now follows that model:
- every call sends Authorization: Bearer <PAT> and X-Active-Workspace-Id;
createApp sends organization_id so apps use the workspace's design system
- client.ts is a plain module object; no per-user client
- removes service users: identity.ts, the connection route, the Base44Link
model, the connect/disconnect UI and its tests
- builder isolation stays where the docs put it: Tiny's ownership table,
checked by the API handler before every app call
- README and .env.example describe BASE44_ACCESS_TOKEN and BASE44_WORKSPACE_ID
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Tiny Sunny: shorter origin check and body read in the API handler
- origin check is one rule: BUILDER_ORIGIN when hosted, a loopback Host locally
(refuses DNS-rebinding pages; request.url is not used because Next rewrites it)
- read the body with request.text() plus a size check instead of a chunked reader
- log unexpected errors before replacing them with a safe message
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Tiny Sunny: render chat parts with assistant-ui's component API
- ThreadPrimitive.Messages with UserMessage / AssistantMessage, and
MessagePrimitive.Parts components={{ Text, tools: { Fallback } }} instead of
one render function with role and part-type branches
- tool parts read appId and onAnswer from a small context, because
assistant-ui renders part components itself
- answers still go through onAnswer, not assistant-ui's resume(), so failures
reach the Question and its retry-the-original-answer flow keeps working
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Tiny Sunny: say why a live-updates session was refused
Every 401/403 used to read "needs apps:watch", which hid the other causes.
Base44's error code now picks the message: missing scope, sockets not enabled
for the workspace, or a key that cannot watch the app. A missing
BASE44_SVC_KEY is reported before any request is made.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Tiny Sunny: follow the docs' build turn, add Publish
- client.ts is ordered by the six steps of "The build turn", one commented
section per step with a link to the docs
- Publish button on the ready card: deploy, then read back the published URL
and link to it (step 6), with a browser test
- remove the unused REST conversation read (getConversation and the backward
pager); the chat arrives over the live-updates socket since #50
- README opens with a table from each docs page to the file that implements it
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Tiny Sunny: show the latest build through the documented embed API
App cards used a static preview URL Tiny derived from the slug and then probed.
They now ask Base44 for it, as "Embed the app" documents: provision the builder
as an app user, mint a one-time sign-in token with target latest_preview, and
load the returned embed_url. Private apps open signed in as the builder.
- new lib/base44/embed.ts; removes lib/server/static-preview.ts and
BASE44_STATIC_PREVIEW_DOMAIN
- PreviewFrame fetches a fresh URL on mount and after each build; the static
iframe is no longer lazy, since the token expires in 60 seconds
- before the first build (app_has_no_slug) the card shows the screenshot
- BASE44_SVC_KEY also needs Provision app users and Mint embed sign-in tokens
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Tiny Sunny: sign the builder into the live preview too
The live preview now comes from "Embed the app" with target live_preview, like
the latest build in the cards. The builder is no Base44 user, so a private app
would otherwise show its own sign-in page inside the frame. Removes the
sandbox/preview-url call and the undocumented URL parameters Tiny added to it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Tiny Sunny: every Base44 call in client.ts
- the embed and live-updates calls move into client.ts as their own sections,
next to the build-turn steps; embed.ts and socket-session.ts are removed
- http.ts had one caller left, so its request() moves to the bottom of
client.ts; it takes an optional auth header for the workspace-key calls
- Base44Error keeps Base44's error.code, which picks the live-updates message
- lib/base44 is now client.ts plus config, error and custom instructions
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Tiny Sunny: one name for live updates, end to end
- openSocketSession / openBuilderSession -> openLiveUpdates (server function,
API action and browser call); watchApp -> watchLiveUpdates;
useBuilderSocket -> useLiveUpdates, whose resume() is now reconnect()
- live-messages.ts merges into live-updates.ts: one browser file for the flow
- the hook names its state for what it is (session, readySession) and says
when it is loading; behaviour is unchanged
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Tiny Sunny: a smaller Builder
- the ready card and its Publish step move to ReadyCard.tsx
- busy is the kind of action (create, send, answer), not its display text
- remove the "resume an existing app" flow: after an uncertain create the
ownership was never saved, so there was nothing it could resume; the
server's error already says the operation may still be running
- builder-api: drop the unused abort signal and notStarted flag
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Tiny Sunny: client.ts written like a guide
- AGENTS.md: style rules for the example (one call, one function; plain ifs;
guard only what matters; comments say why)
- client.ts: one exported function per Base44 call, each showing its path,
method and body; build-turn calls name their 120-second timeout; the
request helper is a plain fetch with the token, workspace header and
safe errors; status hints and defensive checks for impossible states removed
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Tiny Sunny: one file per docs page in lib/base44
- build-turn.ts: steps 1-6 of "The build turn"
- embed.ts: "Embed the app"
- live-updates.ts: the live-updates socket session
- request.ts: the fetch all three share, and the workspace key
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Tiny Sunny: the API handler as a plain switch
- one case per action: allowed fields, checked values, then the call
- small named checks (checkOrigin, readBody, onlyFields, checkId, checkText,
checkSkip) replace the field-tracking body reader and the action table
- the "outcome" field is gone: nothing reads it since the resume flow went
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Tiny Sunny: the builder reads one chat state
- lib/chat/chat-state.ts: getChatState() names where the build turn stands
(loading, paused, question, building, failed, ready, idle); the "has the
agent written code" check moves in from build-readiness.ts
- Builder decides with plain ifs on that state; the status line is a small
Progress component with one if per message
- BuilderChat takes the state instead of five booleans
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Tiny Sunny: server actions instead of a generic API endpoint
Pages call app/actions.ts directly. Each action checks the signed-in builder
and, for an app, that they own it, then calls Base44. Next.js checks the
request origin and decodes the arguments, so the endpoint and its checks go:
- removes app/api/base44/route.ts, lib/server/api-handler.ts,
lib/server/app-service.ts, lib/chat/builder-api.ts and BUILDER_ORIGIN
- actions return { data } or { error }, since Next.js hides thrown messages
in production; lib/chat/unwrap.ts turns an error back into an exception
- browser tests: the fixture aliases app/actions to fake-actions.ts, which
still sends each action to the mocked /api/base44 route
- server tests call the Base44 functions and the ownership check directly
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Tiny Sunny: each server action shows its checks
- every action reads: signed-in user, requireOwner for an app, then the Base44
call; the ownApp/signedIn wrappers are gone, one returnErrors remains
- lib/storage/ownership.ts replaces the app repository with four plain
functions: saveOwner, requireOwner (which also checks the ID is plain),
listOwnedApps, removeOwner
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Tiny Sunny: remove what server actions left behind
- App drops slug, logo_url and user_description: nothing shows them
- remove the unused AppPage type and the unused @/ path aliases
- stop exporting types and classes only their own file uses
- lib/server held only auth.ts, which moves to lib/auth.ts
- README's folder table names app/actions.ts and the current lib folders
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Tiny Sunny: one form per kind of question
Question.tsx follows "Answer the agent's questions": one small form for each
waiting_on.kind (ChoiceForm, SecretsForm, approve/reject), and Reject only
for a question it does not recognize. The main component sends the answer
and, after a failure, resends the same answer with the same request ID.
parseQuestion reads each kind with plain loops instead of throw-and-catch.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Tiny Sunny: server/ and client/ folders
- server/: Base44 calls (server/base44/), server actions, sign-in, ownership
and the database
- client/: everything that runs in the browser, components included
- app/: Next.js routes only (page, layout, the sign-in callback)
- types.ts: what both sides share
- the fixture aliases server/actions to its fake, as before
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Tiny Sunny: the browser's build turn in one hook
client/useBuildTurn.ts holds everything the browser does with Base44, in the
order of the docs: open live updates (the platform client is created there,
in plain sight), send a prompt or create the app, answer a question, and the
chat state. Builder.tsx only renders it.
- removes client/live-updates.ts and client/components/useLiveUpdates.ts
- message conversion and the pending prompt move to client/messages.ts
- the fixture also aliases ../server/actions, imported by the hook
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Tiny Sunny: a readable Workspace
- useApps: the builder's app list (load, remove, add, update) moves out
- AppsPage: loading, empty and list states as plain ifs
- EditorPanel: the assistant panel and its mobile open/close and focus
- Workspace keeps one "app in the assistant" state; the separate stage app
always held the same value
- a new app focuses the composer through autoFocus instead of a DOM query
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Tiny Sunny: one chat component
- BuilderChat merges into Builder: the nine pass-through props go; parts that
assistant-ui renders read the turn from one context
- no hidden-message filtering: live updates never send hidden messages
- the assistant-ui message conversion joins client/messages.ts
- tool arguments are formatted once, when a live message is converted
- ToolActivity and the status line read as plain ifs
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Tiny Sunny: one preview component
AppPreview replaces Base44Preview and PreviewFrame. It shows the latest build
and, while editing, loads the live sandbox behind it until it has loaded.
Refresh preview asks for new one-time URLs.
Removed with it: recovery through the undocumented preview:requestRefresh
message, its retries and timeout, and carrying URL parameters over from the
old sandbox preview URL. None of it applies to one-time embed URLs.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Tiny Sunny: link the API reference, not the platform host
Netlify's secrets scan failed every deploy preview since the README linked the
OpenAPI spec on the platform host, whose origin is the value of the secret
BASE44_PLATFORM_HOST. The README now links the Apps API reference in the docs.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Replaces chat polling in Tiny Sunny (
examples/white-label-minimal) with live updates over the Base44 platform socket, through@base44/platform(base44/javascript-sdk#301). Based on Oz's #31 and cut down to the minimal integration. Sunny itself (src/) is unchanged.lib/base44/socket-session.ts, 20 lines): a newopenBuilderSessionaction on the existing route, behind the existing sign-in and app-ownership checks. It opens a read-only session for one app with the workspace key (BASE44_SVC_KEYneedsapps:watch). Only the session token reaches the browser.lib/chat/live-updates.ts, 50 lines): subscribes. The snapshot replaces the chat on every (re)connect, thenmessage.updated,message.removedandapp.status_changedapply.components/useBuilderSocket.ts): same interface as the polling hook it replaces, soBuilder.tsxonly swaps the hook. There's one error with Reconnect live updates.lib/chat/live-messages.tsconverts socket messages to the shape the existing chat UI renders, so the UI components are untouched.Left out on purpose (listed in the README for production): closing the session on leave (it expires after an hour), history beyond the snapshot's 50 messages, and replacing image placeholders (
image.resolved).Tests: typecheck, unit tests (35, including new server and message-conversion tests) and the 22 Playwright tests pass locally against a local build of
@base44/platform. The browser tests now run against a fake Base44 socket that serves each fixture's conversation.package-lock.jsonpins the published@base44/platform@0.1.0.🤖 Generated with Claude Code