Repository navigation
Tiny Sunny: slim the integration files so they read easily - #49
Merged
Merged
Conversation
- 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>
✅ Deploy Preview for sunny44-builder ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
✅ Deploy Preview for base44-platform-starter ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
- 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>
- 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>
- 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>
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>
- 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>
- 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>
# Conflicts: # examples/white-label-minimal/.env.example # examples/white-label-minimal/components/Builder.tsx # examples/white-label-minimal/components/Question.tsx # examples/white-label-minimal/lib/base44/client.ts # examples/white-label-minimal/lib/server/api-handler.ts # examples/white-label-minimal/lib/server/app-service.ts # examples/white-label-minimal/package.json # examples/white-label-minimal/tests/server.test.ts
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>
- 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>
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>
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>
- 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>
- 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>
- 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>
- 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>
- 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>
- 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>
- 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>
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>
- 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>
- 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>
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>
- 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>
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>
- 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>
- 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>
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>
Ports #54 onto the new structure: - useBuildTurn stops waiting on Send chat message once the build is running - chat-state counts a code edit only from the latest turn - both tests kept; the readiness and pending-prompt unit tests, lost with conversation.test.ts, return in messages.test.ts Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
amitbardos
marked this pull request as ready for review
October 4, 2026 18:12
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>
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.
Makes the Tiny Sunny (
examples/white-label-minimal) integration files shorter and easier to read for people copying them. Behavior is unchanged except where noted below.Changes
lib/server/api-handler.ts: the actionswitchis now a table with one line per action. Each line validates and returns the arguments for theAppClientmethod of the same name. Any request field an action doesn't read is rejected, so there's no separate list of allowed fields to keep in sync.lib/base44/http.ts(new): one fetch helper forclient.tsandidentity.ts. It handles timeouts,redirect: "error",no-store, and errors that are safe to show. Each caller maps HTTP statuses to its own messages.lib/base44/static-preview.ts(new): derives the static preview URL and checks that it serves a page.lib/base44/client.ts: a hint table, a sharedposthelper, and explicittoApp/toMessagemapping. Size: 219 → 125 lines.lib/base44/identity.ts: uses the shared fetch helper; short comments on the non-obvious parts (fixed ID, row lock, best-effort revoke). Size: 151 → 119 lines.config.tschecks for a bare HTTPS origin in one condition, the page size is a named constant, and the README's copy list includes the new files.UI components (second commit)
Workspace.tsx: the active app name is derived from the app on the stage; removed an unused ref; the connect call moves tobuilder-api.ts.Question.tsx: onebuildPayloadhelper (returnsnullwhile nothing is filled in) and a smalltogglehelper.Builder.tsx: onecomposerDisabledflag drives both the send guard and the composer.Base44Preview.tsx: removed theonStatusChangeprop, which nothing passed.ToolActivity.tsx.client.tsas a pure Base44 wrapper (third commit)http.ts, next to the transport.lib/server/static-preview.tsand is applied inapp-service.ts.client.tsand the README link to Base44's OpenAPI spec.Single-account model (fourth and fifth commits)
Base44's tenancy docs describe one integration account that owns every app, authenticated with its personal access token. Tiny now follows them:
Authorization: Bearer <PAT>andX-Active-Workspace-Id, andcreateAppsendsorganization_id, so apps get the workspace's design system, skills and plan.identity.ts, the connection route, theBase44Linkmodel, the connect/disconnect UI and the identity tests. The fourth commit (re-mint instead of refresh) is superseded by this one.BASE44_ACCESS_TOKENandBASE44_WORKSPACE_ID, which replaceBASE44_ORG_ID.BASE44_SVC_KEYstays, but only for live updates: socket sessions (Live builder updates in Tiny Sunny with @base44/platform #50) accept only a workspace key with theapps:watchscope.Behavior changes
not_started.Verification
npm run minimal:typecheckandnpm run minimal:testpass.npx playwright testpasses (23/23).🤖 Generated with Claude Code