> ## 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.

# Bootstrap & Schema

> getBootstrap returns current user context; getSchema returns the app's entity/field definitions.

## getBootstrap(signal?)

Returns context about the current user, their role, the app, and plan limits. Call this once during initialization and cache the result — it does not change mid-session.

```javascript theme={null}
const bootstrap = await sdk.getBootstrap();

// bootstrap.user   — { id, name, email }
// bootstrap.role   — 'viewer' | 'org_admin_viewer' | 'editor' | 'admin'
// bootstrap.app    — { id, name, type }
// bootstrap.limits — { maxPageSize, maxRecordCount, rateLimitPerMinute }
```

### Role

Use `bootstrap.role` to conditionally show or hide editing controls:

```javascript theme={null}
const canEdit = ['editor', 'admin'].includes(bootstrap.role);
const isAdmin = bootstrap.role === 'admin';
```

See [Roles & Permissions](/app-builder/reference/roles) for the full role capability matrix, and the [Role-Based UI guide](/app-builder/guides/role-based-ui) for patterns.

### User

Use `bootstrap.user` to personalise the UI or pre-fill the current user's details:

```javascript theme={null}
document.getElementById('welcome').textContent = `Hello, ${bootstrap.user.name}`;
```

### Limits

`bootstrap.limits` is a key-value map of plan limits for the authenticated user:

| Key                  | Description                                  |
| -------------------- | -------------------------------------------- |
| `maxPageSize`        | Maximum allowed `pageSize` for `listRecords` |
| `maxRecordCount`     | Maximum records allowed per app on this plan |
| `rateLimitPerMinute` | API requests allowed per minute              |

```javascript theme={null}
const { maxRecordCount } = bootstrap.limits;
if (currentCount >= maxRecordCount) {
  showMessage('Record limit reached. Contact your admin to upgrade.');
}
```

`getBootstrap()` is a read operation and is allowed during maintenance mode.

***

## getSchema(signal?)

Returns the entity schema for the current app — all entities and their fields. Use this for dynamic form rendering or runtime field discovery.

```javascript theme={null}
const schema = await sdk.getSchema();
// schema.data — SchemaEntity[]
```

### SchemaEntity

```javascript theme={null}
{
  key: string,           // e.g. 'tasks'
  name: string,          // e.g. 'Tasks'
  display_field: string | null,
  fields: SchemaField[],
}
```

### SchemaField

```javascript theme={null}
{
  key: string,           // e.g. 'status'
  name: string,          // e.g. 'Status'
  type: string,          // e.g. 'select'
  required: boolean,
  read_only: boolean,
  options: string[] | null,  // only set for select / multi_select fields
  sort_order: number,
}
```

### Example — dynamic form rendering

```javascript theme={null}
const schema = await sdk.getSchema();
const tasksEntity = schema.data.find(e => e.key === 'tasks');

tasksEntity.fields.forEach(field => {
  if (field.type === 'select') {
    renderSelectField(field.key, field.name, field.options, field.required);
  } else if (field.type === 'text') {
    renderTextField(field.key, field.name, field.required);
  }
});
```

See [Field Types](/app-builder/reference/field-types) for all field type strings and their stored formats.

`getSchema()` is a read operation and is allowed during maintenance mode.
