Technical docs

Building Websites, Forms, and Dashboards

Overview

Use this reference when a business user asks you to build a website, dashboard, report, calculator, questionnaire, checklist, or other interactive page in Alloy Docs.

Alloy website previews are secure, storage-backed static sites. Build the site as a folder of HTML, CSS, JavaScript, data, and asset files in organization Storage. The user opens the site through Docs in Website mode.

Choose the right use case

This format works well for:

  • informational microsites and internal guides
  • dashboards and visual reports built from bundled data
  • calculators, estimators, and decision aids
  • filters, search, tabs, charts, and other browser-side interactions
  • questionnaires, checklists, and forms that process input only in the current page

Do not use a Docs website preview when the result must:

  • accept and persist form submissions
  • write changes back to JSON or another Storage file
  • call an external API or load an external CDN
  • authenticate users inside the page
  • embed another website, open popups, or navigate to an external site
  • provide a permanent public website URL

The preview serves static files with `GET` and `HEAD` only. Form navigation is blocked, network connections are limited to the preview's own origin, and the preview URL is short-lived. If the use case needs persistence, external integrations, or automation, design a workflow or another supported integration separately instead of implying that the static site can provide it.

Plan before building

Clarify:

  1. The business purpose and intended audience.
  2. The Storage folder where the site should live.
  3. The pages, sections, filters, calculations, or form interactions required.
  4. The source data and who will maintain it.
  5. Whether the output is read-only or must persist submissions or changes.
  6. The expected desktop and mobile behavior.

For a non-trivial request, summarize the proposed folder structure and interaction model before creating files. Explicitly call out any requirement that the secure static preview cannot support.

Required site structure

Every site has a case-sensitive entry file named exactly `index.html`. The folder containing that file becomes the site root.

```text sales-dashboard/ ├── index.html ├── styles.css ├── app.js ├── data.json └── assets/ └── logo.svg ```

Opening `sales-dashboard/index.html` starts the site at `/`. Opening another `.html` file in the same tree makes Alloy search that file's directory and then its parent directories for the nearest `index.html`. Keep a separate `index.html` in each folder that should act as an independent site root.

Use relative paths for site files:

```html <link rel="stylesheet" href="./styles.css"> <script type="module" src="./app.js"></script> <img src="./assets/logo.svg" alt="Company logo"> ```

A directory URL can resolve to that directory's `index.html`, so a multi-page site can use folders:

```text project-portal/ ├── index.html └── reports/ └── index.html ```

Link to it with `<a href="./reports/">Reports</a>`.

Supported website resources

The website server supports these resource types:

UseExtensions
Pages`.html`, `.htm`
Styles`.css`
Scripts`.js`, `.mjs`
Structured data`.json`, `.webmanifest`, `.xml`
Tabular and text data`.csv`, `.tsv`, `.txt`
Images`.png`, `.jpg`, `.jpeg`, `.gif`, `.webp`, `.avif`, `.svg`, `.ico`
Fonts`.woff`, `.woff2`, `.ttf`, `.otf`

JSON is the preferred bundled data source because it can be fetched from the same site and parsed directly:

```js const response = await fetch('./data.json') if (!response.ok) throw new Error(`Could not load data: ${response.status}`) const data = await response.json() ```

CSV, TSV, XML, and plain text can also be fetched and parsed in browser-side JavaScript.

YAML files (`.yaml` and `.yml`) can be edited in Docs, but they are not served as website resources. Do not use YAML as a runtime data source for a preview site. Convert it to JSON or another supported format first.

Bundled audio, video, PDF, and office-document extensions are also outside the website resource allowlist. Other unsupported extensions return an unsupported-resource response. Keep every runtime dependency in a supported file inside the site root.

Security and runtime constraints

Build for the preview's enforced sandbox:

  • Scripts can be inline or loaded from the same site origin.
  • Styles can be inline or loaded from the same site origin.
  • `fetch` and other network connections can access only the same site origin.
  • Images can use same-origin files, `data:` URLs, or `blob:` URLs.
  • Fonts must come from the same site origin. The policy permits `blob:` media URLs, but bundled audio and video files are not served by the website resource allowlist.
  • External scripts, styles, fonts, images, APIs, and CDNs are blocked.
  • Nested frames, workers, plugins/objects, popups, external navigation, and downloads from links are blocked.
  • Native form actions are blocked. Site resources are read-only and cannot be updated with `POST`, `PUT`, `PATCH`, or `DELETE`.
  • Hidden path segments and symlinks are not served.
  • Resources are not cached by the preview server and are not indexed by search engines.

Bundle libraries locally only when their license permits it and their files use supported extensions. Prefer small, dependency-free HTML, CSS, and JavaScript when practical.

Never put secrets, API keys, tokens, or confidential credentials in the site's source or data files. Browser-side code and bundled data are visible to anyone who can open that preview.

Build forms correctly

A form in a Docs website can validate input, calculate results, filter local data, reveal recommendations, or update the current page. It cannot submit to a server or persist entries.

Use browser-side handling and make the limitation clear to the user:

```html <form id="estimator"> <label> Monthly volume <input id="volume" name="volume" type="number" min="0" required> </label> <button type="submit">Calculate</button> </form> <p id="result" aria-live="polite"></p>

<script> const form = document.querySelector('#estimator') const result = document.querySelector('#result')

form.addEventListener('submit', (event) => { event.preventDefault() const volume = Number(form.elements.volume.value) result.textContent = `Estimated annual volume: ${volume * 12}` }) </script> ```

Do not label a form as submitted or saved unless a separate, supported persistence path actually exists and has been tested.

Build dashboards from bundled data

For a dashboard:

  1. Normalize source data into `data.json`, `.csv`, or another served format.
  2. Keep display logic in `app.js` and presentation in `styles.css`.
  3. Show loading, empty, and error states.
  4. Validate data before rendering and handle missing fields safely.
  5. Use accessible tables or text summaries alongside visual charts.
  6. Format dates, currency, percentages, and units explicitly.
  7. Make filters and controls keyboard-accessible and responsive.

A bundled data file is a snapshot. Updating the Storage file causes an open Website preview to reload, but the site cannot update that file itself.

Create and update files

Use Storage file operations to create the site folder and files. Write text resources such as HTML, CSS, JavaScript, and JSON as text files. Use binary file operations for supported images or fonts when needed.

Keep all referenced resources under the site root. Do not rely on local filesystem paths, package installation, build servers, or files outside the site folder at runtime.

When changing source while the site is open, Docs saves the source first and reloads the preview after Storage changes. The user can switch between `Open source code` and `Open website`, and use `Back`, `Forward`, and `Restart` in Website mode.

Test before handing off

Open `index.html` in Docs and test in Website mode. Verify:

  • the site starts at the intended entry page
  • every internal link and directory route works
  • CSS, JavaScript, JSON, images, and fonts load without blocked-resource errors
  • no YAML, unsupported file type, external CDN, or external API is required at runtime
  • forms perform only the promised browser-side behavior
  • loading, empty, invalid-input, and missing-data states are understandable
  • layouts work at narrow and wide widths
  • keyboard navigation, labels, focus states, contrast, and alternative text are usable
  • source edits save and the preview reloads as expected

If Website mode reports `Site entry not found`, verify that the site root contains exact lowercase `index.html`. If a resource fails while source files remain editable, verify that its extension is in the website resource allowlist and that its path stays inside the site root.

Handoff

Tell the user:

  • which Storage folder contains the site
  • which file is the entry point
  • which files hold data and presentation logic
  • how to open Website and Source modes
  • which interactions are browser-only
  • any requirement that still needs a workflow, API integration, or persistent system of record

Start building your AI team