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

# Role-Based UI

> Show or hide editing controls based on the current user's role from sdk.getBootstrap().

HASP apps receive the current user's role from `sdk.getBootstrap()`. Use it to conditionally show or hide editing controls so viewers see a read-only interface while editors and admins get the full UI.

## Getting the Role

Always call `getBootstrap()` before rendering the UI:

```javascript theme={null}
const bootstrap = await sdk.getBootstrap();
const { role } = bootstrap;
// role: 'viewer' | 'org_admin_viewer' | 'editor' | 'admin'

const canEdit = ['editor', 'admin'].includes(role);
const isAdmin = role === 'admin';
```

## Hiding Controls from Viewers

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

  if (canEdit) {
    document.getElementById('create-btn').style.display = 'block';
  }

  loadRecords();
}
```

Alternatively, use CSS classes:

```javascript theme={null}
if (!canEdit) {
  document.body.classList.add('readonly');
}
```

```css theme={null}
.readonly .edit-controls { display: none; }
```

## Inline Edit Controls

Show edit and delete buttons only for editors/admins:

```javascript theme={null}
function renderRecord(record, canEdit) {
  return `
    <div class="record">
      <h3>${escapeHtml(record.title)}</h3>
      ${canEdit ? `
        <div class="actions">
          <button onclick="openEdit('${record.id}')">Edit</button>
          <button onclick="deleteRecord('${record.id}')">Delete</button>
        </div>
      ` : ''}
    </div>
  `;
}
```

## Proactive Check Before Write

Even if the UI hides write controls for viewers, always handle `AccessDenied` errors gracefully in case the role changes mid-session:

```javascript theme={null}
const { ErrorCode, HaspSDKError } = HaspSDK;

try {
  await sdk.createRecord('tasks', data);
} catch (error) {
  if (error instanceof HaspSDKError && error.code === ErrorCode.AccessDenied) {
    showMessage('You do not have permission to create records.');
  }
}
```

## Bootstrap Data

`getBootstrap()` returns more than just the role:

```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 }
```

You can use `bootstrap.user` to personalize the UI or pre-fill the current user's email in a form.
