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

# Getting Started

> Understand the App Builder platform and build your first workflow app.

## What is a HASP App?

A HASP app is a **static HTML/JS bundle** that runs in the browser and calls the HASP Data API to read and write structured data. There are two app types:

* **Utility Apps** — static tools with no server-side data (calculators, converters, reference tools)
* **Workflow Apps** — data-driven apps that store records via entities and the Data API

This documentation covers **Workflow Apps**.

## Architecture

Your app runs on the **same origin** as HASP — no CORS needed. Authentication is handled by HASP — your app never implements login. The SDK reads `appId` from `window.__HASP__` — never hardcode it. All Data API calls go through the SDK — never use raw `fetch()` for those.

## Two identifiers: `appId` and app URL

HASP uses two different identifiers for the same app, and each has a specific purpose:

| Identifier     | Example        | Where you see it                                                                | When to use it                                                                                 |
| -------------- | -------------- | ------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- |
| `appId` (ULID) | `01JA7QG2...`  | `window.__HASP__.appId`, `X-Hasp-AppId` header, outbound webhook `app_id` field | SDK requests, webhook handlers, anywhere the API contract requires a stable machine identifier |
| App slug       | `task-tracker` | The `/apps/task-tracker/...` URL in the admin UI, shared links, bookmarks       | Navigation, linking, anything a human reads                                                    |

**The ULID is frozen per app** — it never changes, even if the owner renames the app. **The slug can change** when an admin renames the app. Old URLs (both the previous slug AND the ULID form `/apps/{ulid}/...`) continue to resolve automatically.

<Warning>
  **Common mistakes:**

  * ❌ Storing the admin URL in your integration database — store `appId` instead
  * ❌ Passing the slug to the SDK — the SDK reads `appId` from the bootstrap
  * ❌ Parsing the URL to extract an identifier — use `window.__HASP__.appId`
</Warning>

## Building Your First App

### 1. Design your schema

Decide what data your app needs to store. Each concept becomes an **entity** (like a database table), and each property becomes a **field**.

For example, a task tracker might have one entity:

| Entity | Key     | Fields                                                                    |
| ------ | ------- | ------------------------------------------------------------------------- |
| Tasks  | `tasks` | `title` (text, required), `status` (select: open/done), `due_date` (date) |

See [Field Types](/app-builder/reference/field-types) for all available types.

### 2. Write your app

Load the SDK and use it to read/write records:

```html theme={null}
<!DOCTYPE html>
<html>
<head>
  <title>My App</title>
</head>
<body>
  <script src="https://sdk.usehasp.com/v1.js"></script>
  <script>
    const sdk = new HaspSDK();

    async function init() {
      const bootstrap = await sdk.getBootstrap();
      const canEdit = ['editor', 'admin'].includes(bootstrap.role);

      const result = await sdk.listRecords('tasks', { sort: 'due_date:asc' });
      console.log(result.data);
    }

    init();
  </script>
</body>
</html>
```

See [SDK: Records](/app-builder/sdk/records) for the full CRUD reference.

### 3. Set up your schema in HASP

1. Log in to [app.usehasp.com](https://app.usehasp.com)
2. Click **New App**, give it a name, and choose **Workflow App**
3. Open the **Schema Builder** and create each entity with its fields

### 4. Upload your app

Drop your HTML/JS/CSS files directly into the upload area (or zip them first). Your app **must** have an `index.html` at the root.

### 5. Publish

Click **Publish** to make your app live.

## What NOT to Do

* **Never hardcode `appId`** — the SDK reads it from `window.__HASP__` automatically
* Never call `fetch()` directly **for Data API requests** — always use the SDK
* **Never implement authentication** — HASP handles login/session
* **Never use offset pagination** — always use cursor-based pagination
* **Never include a backend** — HASP apps are static; the Data API is your backend
