# Apps (/docs/apps)



Apps belong to one workspace.

Each app stores:

* `name`
* `handle`
* optional `description`
* `code`

App URL [#app-url]

Every app is published at:

```txt
/w/[handle]/apps/[appHandle]
```

The page renders the saved JSX inside a sandboxed iframe for signed-in workspace members.

Code contract [#code-contract]

For now, `code` must be a single JSX module that exports a default React component.

When editing an existing app, fetch the current saved app first and treat that code as the source of truth.

* Preserve the current design and structure unless the user explicitly asks for a redesign.
* Make focused improvements instead of replacing the whole UI.
* Reuse existing `@andibase/ui` components and their default styles wherever possible.
* Avoid custom CSS and Tailwind unless they are strictly needed for layout or functionality.

```jsx
import { useState } from "react";
import { Button } from "@andibase/ui/button";

export default function App() {
  const [count, setCount] = useState(0);

  return (
    <main style={{ minHeight: "100vh", padding: 24 }}>
      <h1>Counter</h1>
      <Button onClick={() => setCount((value) => value + 1)}>Count: {count}</Button>
    </main>
  );
}
```

The renderer loads React from `esm.sh`, transpiles the JSX in-browser, and mounts the default export into the iframe root.

UI guidance [#ui-guidance]

Use `@andibase/ui` first.

* Import from `@andibase/ui` or component subpaths such as `@andibase/ui/button`, `@andibase/ui/input`, and `@andibase/ui/card`.
* Prefer the shared `shadcn/ui` primitives from `@andibase/ui` over custom-built elements.
* Keep styling minimal and close to the existing app so updates feel like refinements, not replacements.

File uploads in custom apps [#file-uploads-in-custom-apps]

Use `FileUpload` from `@andibase/ui/file-upload` when your app needs to:

* upload a local file into the workspace file API
* create a new text or markdown file directly from the app
* save to either a user-entered workspace path or a fixed path chosen by the app

Inside embedded apps, the component already uses `window.andibase.fetch(...)`, so no extra fetch wrapper is required.

Simplest usage [#simplest-usage]

```tsx
import { FileUpload } from "@andibase/ui/file-upload";

export default function App() {
  return (
    <main style={{ padding: 24 }}>
      <FileUpload />
    </main>
  );
}
```

Upload only to a fixed path [#upload-only-to-a-fixed-path]

```tsx
import { FileUpload } from "@andibase/ui/file-upload";

export default function App() {
  return (
    <main style={{ padding: 24 }}>
      <FileUpload
        mode="upload"
        path="imports/customers.csv"
        heading="Customer import"
        description="Upload the latest customer CSV."
      />
    </main>
  );
}
```

Create a new markdown file [#create-a-new-markdown-file]

```tsx
import { FileUpload } from "@andibase/ui/file-upload";

export default function App() {
  return (
    <main style={{ padding: 24 }}>
      <FileUpload
        mode="new"
        defaultPath="notes/today.md"
        defaultNewFileContent={"# Notes\n\n"}
        heading="Daily notes"
      />
    </main>
  );
}
```

Handling the saved file [#handling-the-saved-file]

```tsx
import { useState } from "react";
import { FileUpload } from "@andibase/ui/file-upload";

export default function App() {
  const [savedPath, setSavedPath] = useState<string | null>(null);

  return (
    <main style={{ padding: 24 }}>
      <FileUpload
        onSuccess={(result) => {
          setSavedPath(result.path);
          console.log(result.file.id, result.file.path);
        }}
      />
      {savedPath ? <p>Saved to {savedPath}</p> : null}
    </main>
  );
}
```

See [UI Components](/docs/ui-components) for the full `FileUpload` component reference.

API endpoints [#api-endpoints]

Apps are documented in the generated API reference:

* `GET /api/v1/apps`: list apps for the current workspace
* `GET /api/v1/apps/:id`: get one app by id with full stored data, including `code`
* `POST /api/v1/apps`: create an app in the current workspace
* `PATCH /api/v1/apps/:handle`: update an app in the current workspace
* `DELETE /api/v1/apps/:handle`: delete an app from the current workspace

Use the full request and response schemas here:

* [Apps API reference](/docs/api-reference/apps)

Auth model [#auth-model]

* `/w/[handle]/apps/[appHandle]` renders the app inside the workspace shell for signed-in members.
* Signed-in non-members receive a 404.
* The iframe uses the normal first-party session cookie.
* `window.andibase.fetch(path, init?)` sends `credentials: "include"` and the app workspace handle automatically.
* Workspace management endpoints use the resolved workspace.
* Session requests should send `x-workspace-handle` when needed.
* Manual API keys still need `apps.read` or `apps.write`.

Host actions from iframe apps [#host-actions-from-iframe-apps]

The embedded runtime also exposes host-action helpers from `@andibase/hooks`.

These helpers let iframe apps ask the host workspace UI to open native drawers on top of the iframe, instead of re-implementing those flows inside the app.

```tsx
import { openDataRecordForm, openInlineAgentChat } from "@andibase/hooks";

openDataRecordForm({
  definitionHandle: "customer",
  defaultValues: { firstName: "Ada" },
});

openDataRecordForm({
  mode: "edit",
  definitionHandle: "customer",
  recordId: "rec_123",
  defaultValues: { firstName: "Ada" },
});

openInlineAgentChat({
  agentHandle: "support-assistant",
});
```

Refreshing after host drawers close [#refreshing-after-host-drawers-close]

If your app needs to refresh after the user returns from a host-managed drawer or chat, use `useAndibaseRefreshOnReturn()` from `@andibase/hooks`.

```tsx
import { useEffect, useState } from "react";
import { useAndibaseRefreshOnReturn } from "@andibase/hooks";

export default function App() {
  const [items, setItems] = useState([]);

  async function loadData() {
    const response = await window.andibase.fetch("/data-definitions/customer/query");
    const payload = await response.json();
    setItems(payload.items ?? []);
  }

  useEffect(() => {
    loadData();
  }, []);

  useAndibaseRefreshOnReturn(() => {
    loadData();
  });

  return <main>{items.length} customers</main>;
}
```

Avoid unconditional `window.addEventListener("focus", ...)` refresh handlers in iframe apps. The iframe's first user click usually gives it focus, so a raw focus listener can look like a full app reload even when the user only opened local UI inside the app.

See [Embedded Host Actions](/docs/embedded-host-actions) for the full API.


## Documentation Navigation
Use these paths to traverse the relevant docs and generated API reference files for the app.
- Apps [current] -> `/docs/apps` (source: `content/docs/apps.mdx`)
- andibase Overview -> `/docs` (source: `content/docs/index.mdx`)
- Get started (for AI Agents) -> `/docs/agent-get-started` (source: `content/docs/agent-get-started.mdx`)
- Agent Tools -> `/docs/agent-tools` (source: `content/docs/agent-tools.mdx`)
- Agents -> `/docs/agents` (source: `content/docs/agents.mdx`)
- Agent Auth -> `/docs/api-reference/agent-auth`
- Get agent login request -> `/docs/api-reference/agent-auth/get-api-v1-agent-auth-requests-usercode`
- Exchange agent login -> `/docs/api-reference/agent-auth/post-api-v1-agent-auth-exchange`
- Start agent login -> `/docs/api-reference/agent-auth/post-api-v1-agent-auth-requests`
- Approve agent login -> `/docs/api-reference/agent-auth/post-api-v1-agent-auth-requests-usercode-approve`
- Deny agent login -> `/docs/api-reference/agent-auth/post-api-v1-agent-auth-requests-usercode-deny`
- Agents -> `/docs/api-reference/agents`
- Delete workspace agent -> `/docs/api-reference/agents/delete-api-v1-agents-id`
- List workspace agents -> `/docs/api-reference/agents/get-api-v1-agents`
- Get workspace agent -> `/docs/api-reference/agents/get-api-v1-agents-id`
- List agent chats -> `/docs/api-reference/agents/get-api-v1-agents-id-chats`
- Get agent chat -> `/docs/api-reference/agents/get-api-v1-agents-id-chats-chatid`
- Update workspace agent -> `/docs/api-reference/agents/patch-api-v1-agents-id`
- Create workspace agent -> `/docs/api-reference/agents/post-api-v1-agents`
- Send agent message -> `/docs/api-reference/agents/post-api-v1-agents-id-chats-chatid-messages`
- Apps -> `/docs/api-reference/apps`
- Delete app -> `/docs/api-reference/apps/delete-api-v1-apps-id`
- List workspace apps -> `/docs/api-reference/apps/get-api-v1-apps`
- Get app by id -> `/docs/api-reference/apps/get-api-v1-apps-id`
- Update app -> `/docs/api-reference/apps/patch-api-v1-apps-id`
- Create app -> `/docs/api-reference/apps/post-api-v1-apps`
- Automations -> `/docs/api-reference/automations`
- Delete workspace automation -> `/docs/api-reference/automations/delete-api-v1-automations-id`
- List workspace automations -> `/docs/api-reference/automations/get-api-v1-automations`
- Get workspace automation -> `/docs/api-reference/automations/get-api-v1-automations-id`
- List automation runs -> `/docs/api-reference/automations/get-api-v1-automations-id-runs`
- Get automation run -> `/docs/api-reference/automations/get-api-v1-automations-id-runs-runid`
- Update workspace automation -> `/docs/api-reference/automations/patch-api-v1-automations-id`
- Create workspace automation -> `/docs/api-reference/automations/post-api-v1-automations`
- Run automation -> `/docs/api-reference/automations/post-api-v1-automations-id-run`
- Trigger automation webhook -> `/docs/api-reference/automations/post-api-v1-automations-webhooks-publicid-secret`
- Channels -> `/docs/api-reference/channels`
- Delete channel -> `/docs/api-reference/channels/delete-api-v1-channels-channelid`
- List channels -> `/docs/api-reference/channels/get-api-v1-channels`
- Get channel -> `/docs/api-reference/channels/get-api-v1-channels-channelid`
- Update channel -> `/docs/api-reference/channels/patch-api-v1-channels-channelid`
- Create channel -> `/docs/api-reference/channels/post-api-v1-channels`
- Data -> `/docs/api-reference/data`
- Data Definitions -> `/docs/api-reference/data-definitions`
- Delete data definition -> `/docs/api-reference/data-definitions/delete-api-v1-data-definitions-id`
- List data definitions -> `/docs/api-reference/data-definitions/get-api-v1-data-definitions`
- Get data definition -> `/docs/api-reference/data-definitions/get-api-v1-data-definitions-id`
- Update data definition -> `/docs/api-reference/data-definitions/patch-api-v1-data-definitions-id`
- Create data definition -> `/docs/api-reference/data-definitions/post-api-v1-data-definitions`
- Data SQL Query -> `/docs/api-reference/data-sql-query`
- Run SQL query against workspace data -> `/docs/api-reference/data-sql-query/post-api-v1-data-sql-query`
- Get data by id -> `/docs/api-reference/data/get-api-v1-data-definitions-definitionid-data-id`
- Select all data row ids -> `/docs/api-reference/data/get-api-v1-data-definitions-definitionid-data-select-all`
- List data -> `/docs/api-reference/data/get-api-v1-data-definitions-definitionid-query`
- Patch many data rows -> `/docs/api-reference/data/patch-api-v1-data-definitions-definitionid-data-patch-many`
- Delete many data rows -> `/docs/api-reference/data/post-api-v1-data-definitions-definitionid-data-delete-many`
- Upsert many data rows -> `/docs/api-reference/data/post-api-v1-data-definitions-definitionid-data-upsert-many`
- DuckDB Query -> `/docs/api-reference/duckdb-query`
- Run a DuckDB query against registered sources -> `/docs/api-reference/duckdb-query/post-api-v1-duckdb-query`
- Explorer -> `/docs/api-reference/explorer`
- Delete explorer folder -> `/docs/api-reference/explorer/delete-api-v1-workspace-nodes-nodeid`
- List explorer nodes -> `/docs/api-reference/explorer/get-api-v1-workspace-nodes`
- List explorer folders -> `/docs/api-reference/explorer/get-api-v1-workspace-nodes-folders`
- Rename explorer folder -> `/docs/api-reference/explorer/patch-api-v1-workspace-nodes-nodeid-rename`
- Create folder -> `/docs/api-reference/explorer/post-api-v1-workspace-nodes-folders`
- Move explorer node -> `/docs/api-reference/explorer/post-api-v1-workspace-nodes-nodeid-move`
- Files -> `/docs/api-reference/files`
- List workspace files -> `/docs/api-reference/files/get-api-v1-files`
- Read file content -> `/docs/api-reference/files/get-api-v1-files-fileid-content`
- Create file -> `/docs/api-reference/files/post-api-v1-files`
- Complete file upload -> `/docs/api-reference/files/post-api-v1-files-fileid-complete`
- Presign multipart parts -> `/docs/api-reference/files/post-api-v1-files-fileid-parts`
- Update file content -> `/docs/api-reference/files/put-api-v1-files-fileid-content`
- Messages -> `/docs/api-reference/messages`
- List channel messages -> `/docs/api-reference/messages/get-api-v1-channels-channelid-messages`
- List thread messages -> `/docs/api-reference/messages/get-api-v1-channels-channelid-threads-threadid-messages`
- Create channel message -> `/docs/api-reference/messages/post-api-v1-channels-channelid-messages`
- Create thread message -> `/docs/api-reference/messages/post-api-v1-channels-channelid-threads-threadid-messages`
- Notifications -> `/docs/api-reference/notifications`
- List notification devices -> `/docs/api-reference/notifications/get-api-v1-notifications-devices`
- Check Expo notification receipts -> `/docs/api-reference/notifications/post-api-v1-notifications-receipts`
- Send workspace notifications -> `/docs/api-reference/notifications/post-api-v1-notifications-send`
- Runs -> `/docs/api-reference/runs`
- List workspace runs -> `/docs/api-reference/runs/get-api-v1-runs`
- Get workspace run -> `/docs/api-reference/runs/get-api-v1-runs-runid`
- Threads -> `/docs/api-reference/threads`
- List channel threads -> `/docs/api-reference/threads/get-api-v1-channels-channelid-threads`
- Get thread -> `/docs/api-reference/threads/get-api-v1-channels-channelid-threads-threadid`
- Create thread -> `/docs/api-reference/threads/post-api-v1-channels-channelid-threads`
- Workflows -> `/docs/api-reference/workflows`
- Delete workflow definition -> `/docs/api-reference/workflows/delete-api-v1-workflows-id`
- List workflow definitions -> `/docs/api-reference/workflows/get-api-v1-workflows`
- Get workflow definition -> `/docs/api-reference/workflows/get-api-v1-workflows-id`
- Update workflow definition -> `/docs/api-reference/workflows/patch-api-v1-workflows-id`
- Create workflow definition -> `/docs/api-reference/workflows/post-api-v1-workflows`
- Workspaces -> `/docs/api-reference/workspaces`
- Delete workspace API key -> `/docs/api-reference/workspaces/delete-api-v1-workspaces-workspacehandle-api-keys-keyid`
- Delete workspace credential -> `/docs/api-reference/workspaces/delete-api-v1-workspaces-workspacehandle-credentials-credentialid`
- Delete workspace invitation -> `/docs/api-reference/workspaces/delete-api-v1-workspaces-workspacehandle-invitations-invitationid`
- Delete workspace user -> `/docs/api-reference/workspaces/delete-api-v1-workspaces-workspacehandle-users-userid`
- List my workspaces -> `/docs/api-reference/workspaces/get-api-v1-workspaces`
- List workspace API keys -> `/docs/api-reference/workspaces/get-api-v1-workspaces-workspacehandle-api-keys`
- List workspace credentials -> `/docs/api-reference/workspaces/get-api-v1-workspaces-workspacehandle-credentials`
- List workspace credential tools -> `/docs/api-reference/workspaces/get-api-v1-workspaces-workspacehandle-credentials-credentialid-tools`
- List workspace invitations -> `/docs/api-reference/workspaces/get-api-v1-workspaces-workspacehandle-invitations`
- List workspace users -> `/docs/api-reference/workspaces/get-api-v1-workspaces-workspacehandle-users`
- Create workspace -> `/docs/api-reference/workspaces/post-api-v1-workspaces`
- Create workspace API key -> `/docs/api-reference/workspaces/post-api-v1-workspaces-workspacehandle-api-keys`
- Create workspace credential -> `/docs/api-reference/workspaces/post-api-v1-workspaces-workspacehandle-credentials`
- Invite user to workspace -> `/docs/api-reference/workspaces/post-api-v1-workspaces-workspacehandle-invitations`
- Create workspace user -> `/docs/api-reference/workspaces/post-api-v1-workspaces-workspacehandle-users`
- Authentication -> `/docs/authentication` (source: `content/docs/authentication.mdx`)
- Building Blocks -> `/docs/building-blocks` (source: `content/docs/building-blocks.mdx`)
- Data Model -> `/docs/data-model` (source: `content/docs/data-model.mdx`)
- Embedded Host Actions -> `/docs/embedded-host-actions` (source: `content/docs/embedded-host-actions.mdx`)
- Introduction -> `/docs/introduction` (source: `content/docs/introduction.mdx`)
- Recipes -> `/docs/receipes` (source: `content/docs/receipes/index.mdx`)
- Construction Site Visit Agent -> `/docs/receipes/construction-site-visit-agent` (source: `content/docs/receipes/construction-site-visit-agent.mdx`)
- Daily Lead Qualification Agent -> `/docs/receipes/daily-lead-qualification-agent` (source: `content/docs/receipes/daily-lead-qualification-agent.mdx`)
- Day Planner Agent -> `/docs/receipes/day-planner-agent` (source: `content/docs/receipes/day-planner-agent.mdx`)
- Expense Tracker -> `/docs/receipes/expense-tracker` (source: `content/docs/receipes/expense-tracker.mdx`)
- Legal Case Tracker -> `/docs/receipes/legal-case-tracker` (source: `content/docs/receipes/legal-case-tracker.mdx`)
- Spare Parts Request Agent -> `/docs/receipes/spare-parts-request-agent` (source: `content/docs/receipes/spare-parts-request-agent.mdx`)
- Weekly Report Email Agent -> `/docs/receipes/weekly-report-email-agent` (source: `content/docs/receipes/weekly-report-email-agent.mdx`)
- UI Components -> `/docs/ui-components` (source: `content/docs/ui-components.mdx`)