> ## Documentation Index
> Fetch the complete documentation index at: https://university.triggr-app.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Introduction to internal apps

> Build pages that Triggr hosts for your team or clients, which can upload files and start your workflows.

An internal app is one or more HTML pages, with your own CSS and JavaScript, hosted by Triggr. Use one when a [form](/studio/forms/introduction) isn't enough: your own layout, several pages, or buttons that start [workflows](/studio/workflows/introduction).

<Frame caption="Build an internal app: a one-page app that sends a message to a workflow, shared with a password and used from its link (1:22).">
  <video controls preload="none" playsInline className="w-full aspect-video rounded-xl" poster="/images/videos/studio-internal-apps.jpg" src="https://mintcdn.com/triggr/GxrCQFDFNLmEMyJ1/images/videos/studio-internal-apps.mp4?fit=max&auto=format&n=GxrCQFDFNLmEMyJ1&q=85&s=a45f3304e9d83871672a07b2e20c6dcc" data-path="images/videos/studio-internal-apps.mp4" />
</Frame>

<Frame caption="The app editor: pages along the top, HTML on the left, a live preview on the right.">
  <img src="https://mintcdn.com/triggr/_d7ojda9vf8IHE31/images/studio/internal-apps/designer.png?fit=max&auto=format&n=_d7ojda9vf8IHE31&q=85&s=aa2a31216371d715e781ca556a62498c" alt="The Service desk messages app in Design: Settings, SDK, Hide Preview and Saved in the header, a Home page tab with Add Page, Edit Page and Delete Page, the page HTML in the editor and a preview of a Message the service desk page with a text box and a Send button." width="2880" height="1368" data-path="images/studio/internal-apps/designer.png" />
</Frame>

## Build your first app

A one-page app your team uses to send a message to a workflow. You need an active workflow with a step that uses `{{ ctx.params.message }}`; copy its ID from the address bar (`app.triggr-app.com/workflows/<id>/design`).

<Steps>
  <Step title="Create the app">
    In Internal Apps, click **New App**, enter a Name and click Create App.

    <Frame>
      <img src="https://mintcdn.com/triggr/_d7ojda9vf8IHE31/images/studio/internal-apps/new-app.png?fit=max&auto=format&n=_d7ojda9vf8IHE31&q=85&s=33d054d0a18ca4fa345300d7757948dd" width="512" alt="The Create New Internal App dialog with Name Service desk messages, an empty optional Description, and Cancel and Create App buttons." data-path="images/studio/internal-apps/new-app.png" />
    </Frame>
  </Step>

  <Step title="Write the page">
    Click **Design** on the app's row, click Add Page, name the page and click Create Page. Paste this into the editor, replace `WORKFLOW_ID` with your workflow's ID and click Save.

    ```html theme={null}
    <!doctype html>
    <html>
    <head>
      <style>body { font-family: sans-serif; padding: 24px; }</style>
    </head>
    <body>
      <h1>Message the service desk</h1>
      <textarea id="message" rows="4" cols="40"></textarea>
      <p><button id="send">Send</button></p>
      <p id="status"></p>
      <script>
        document.getElementById('send').addEventListener('click', async () => {
          const status = document.getElementById('status');
          try {
            const { executionId } = await triggr.runWorkflow('WORKFLOW_ID', {
              message: document.getElementById('message').value
            });
            status.textContent = 'Sent (run ' + executionId + ')';
          } catch (err) {
            status.textContent = err.message;
          }
        });
      </script>
    </body>
    </html>
    ```
  </Step>

  <Step title="Secure it">
    Click **Settings**, choose Password as the Authentication Type and enter a password. Under Workflows pages can run, tick your workflow, then click Save Settings.

    <Frame>
      <img src="https://mintcdn.com/triggr/XztmSfsoAUpshfIO/images/studio/internal-apps/settings.png?fit=max&auto=format&n=XztmSfsoAUpshfIO&q=85&s=41d272158160f9f05e0cee2770683417" alt="The App Authentication panel with Password selected, Hide top bar and List on Homepage off, a masked Password, Allow file uploads off, and Service desk message ticked under Workflows pages can run." width="838" height="2000" data-path="images/studio/internal-apps/settings.png" />
    </Frame>
  </Step>

  <Step title="Test and share it">
    Back on Internal Apps, click **Share** on the app's row, then Open in new tab. Enter the password and send a message: the run appears under Executions. Click Copy and send your team the link and password.

    <Frame>
      <img src="https://mintcdn.com/triggr/XztmSfsoAUpshfIO/images/studio/internal-apps/share-app.png?fit=max&auto=format&n=XztmSfsoAUpshfIO&q=85&s=77f94d11c64cb426d950f2f6819bdc49" alt="The Share App dialog with a Public App URL on forms.yourmsp.com, a Copy button and an Open in new tab link." width="1040" height="384" data-path="images/studio/internal-apps/share-app.png" />
    </Frame>
  </Step>
</Steps>

## Who can open an app

New apps start as Internal: your Studio team opens them at `https://app.triggr-app.com/telescope/apps/<org-id>/<app-id>` with their staff sign-in (**Support > Copy Org ID** in the top bar gives the first ID; the second is in the designer's address bar). None, Password, Microsoft and Google work as they do for [forms](/studio/forms/introduction#who-can-open-a-form) and add a Share link. A Microsoft or Google visitor's workflows run for their client.

Allow file uploads needs Microsoft, Google or Internal authentication. Hide top bar shows only the first page, full-screen.

## The Triggr SDK

In the live app (the Share link, or the Internal app URL above), each page gets `window.triggr`, which acts as the signed-in visitor: `runWorkflow` starts a ticked workflow and returns its `executionId`, and `upload`, `pickAndUpload`, `list` and `fileUrl` handle files when Allow file uploads is on. Preview and Open show a page's layout, not its calls, so test calls in the live app. Click **SDK** in the editor for the quick reference.

<Frame>
  <img src="https://mintcdn.com/triggr/XztmSfsoAUpshfIO/images/studio/internal-apps/sdk-panel.png?fit=max&auto=format&n=XztmSfsoAUpshfIO&q=85&s=55b02ff9fc56f1bed40f461492602cdb" width="436" alt="The Triggr SDK popover opened from the SDK button in the app editor, listing triggr.ready, upload, pickAndUpload, fileUrl, list and runWorkflow with what each returns, a FileRef example, a short upload-and-run code sample, and notes that uploads and workflows need Settings and that runWorkflow is unavailable in the preview." data-path="images/studio/internal-apps/sdk-panel.png" />
</Frame>

* [SDK reference](/studio/internal-apps/sdk): every call, its limits and errors, and when to use a workflow's webhook instead.
* [Example: build an uptime monitor](/studio/internal-apps/example-uptime-monitor): workflows on a schedule, results in a database, and a page that shows them.

## Troubleshooting

<AccordionGroup>
  <Accordion title="this app is not allowed to run that workflow">
    Tick the workflow under **Settings > Workflows pages can run** and click Save Settings, and check the ID in the page matches the workflow's.
  </Accordion>

  <Accordion title="workflow is not active">
    On Workflows, click Edit on the workflow's row, set Status to Active and click Save Changes.
  </Accordion>

  <Accordion title="“triggr is not defined” or “Triggr is not available on this page”">
    The page was opened with Open, which shows it without the SDK. Use **Share > Open in new tab**, or the Internal app URL above.
  </Accordion>

  <Accordion title="New App is missing">
    Ask an admin for permission to edit internal apps.
  </Accordion>
</AccordionGroup>

Next: [Example: build an uptime monitor](/studio/internal-apps/example-uptime-monitor).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.