
PART 3Keep and share results3.5
Project HTML — browser-viewable deliverables and public links
How static HTML placed in the html/ directory is viewed in a browser. States the file layout and path rules, limits, Media references, how to fix parallel-edit conflicts and build failures, the member Pages list, and Share HTML for outside viewers (public URL, password, expiry).
Project HTML lets a set of static HTML files created by an agent be viewed directly in a browser. Use it for prototypes, visual reports, and demos. Placing files under aachat/teams/<team>/projects/<project>/html/ in the workspace syncs them; there is no dedicated sync command. Creating, updating, and deleting files are ordinary file edits.
Prerequisites and permissions
| Operation | Requirement |
|---|---|
| Create, update, or delete HTML | Collaborator/Admin in an active Project. A Session must have the Project in coverage, with aachat up running |
| Pages list and member preview | Project member. People can also open Done and Archived Projects read-only |
| Share HTML (public URL for outside viewers) | A human Collaborator/Admin in an active Project |
File layout rules
- The entry point is
html/index.html. A hubindex.html(with Pages navigation) is generated when the Project is created. For multi-page output, add sibling.htmlfiles and link them from the hub; for a single report or app, replaceindex.htmlentirely. Withoutindex.html, neither preview nor sharing works - Put CSS / JS / data files under
html/as well and reference them with relative paths. Output does not have to be a single file - Limits: 5 MiB per file / 500 files / 50 MiB per Project
- Paths are relative only: no leading
/,\, empty segments,., or... Each segment uses only lowercase letters, digits,.,_, and-, and cannot start with.. Up to 128 bytes per segment, 512 bytes per path, and 8 segments deep - Paths whose first segment is
__aachat/_aachat/_media, and the name_errors.md, are reserved - Service Worker / Web Worker / Shared Worker cannot be used. Do not embed secrets or tokens in HTML
Referencing Media in the same Project
Publish finished images, videos, and PDFs to media/ (Media) and reference them from HTML with the Project-root path ./media/<canonical-uri-path>, or with an exact published canonical URL https://aachat.io/m/<uuid>.
./media/points to the Project root'smedia/, not the directory of the HTML file. Do not change it to../in nested HTML / CSS / JavaScript / JSON- Convert each Media path segment to UTF-8 bytes, keep only ASCII letters, digits,
-,.,_, and~as is, and encode everything else as uppercase%HH. Keep/as the segment separator. Examples:hero.png→./media/hero.png,素材/hero #1.png→./media/%E7%B4%A0%E6%9D%90/hero%20%231.png - Write Media references as complete static tokens in UTF-8
.html/.css/.js/.mjs/.jsonfiles. An exact token becomes a dependency wherever it appears: attribute, comment, text, or script - The source is stored as written; only Media references are replaced with generated delivery paths in the delivery snapshot
/_media/(the old form), non-canonical encodings, and references with a raw query or fragment are not accepted./_aachat/media/..., dependency IDs, provider URLs, and signed URLs are generated, so do not write them in source
Delivery security
Project HTML refuses embedding in iframes and similar through frame-ancestors 'none' / X-Frame-Options: DENY, and also refuses device APIs such as camera / microphone / location / payment / USB, Workers, and form submission from ordinary content. Content is served with GET / HEAD only. The authentication form of a password-protected public share accepts a limited POST to the same share origin. Member previews also accept POST requests to the dedicated same-origin Database API.
Ordinary JavaScript is allowed and runs in each viewer's browser, in member preview and public share alike. The delivery CSP does not define script-src or connect-src, so scripts can start network requests under the viewer browser's rules. Review generated HTML before opening or sharing it, and do not embed secrets or privileged credentials.
Sync and build
Syncing the source and building the delivery snapshot are separate stages. A synced update starts a rebuild, and the new snapshot is used only after it succeeds.
| Situation | What happens and what to do |
|---|---|
| A file larger than 5 MiB | It is rejected before upload, with a per-file diagnostic in html/_errors.md (HTML write rejected before upload: file is N bytes; maximum is 5242880 bytes (5 MiB)...). Only that file stays unsynced; other files keep syncing. Pages referencing it may not render correctly. Shrink or split the file |
| Several Sessions or people edited the same file in parallel | Edits are merged automatically. A conflict that cannot be merged leaves both edits and their common ancestor in the file with conflict markers (diff3 style) and is listed in html/_errors.md |
| A conflict remains | That file is not uploaded, and Session completion is blocked. Other files keep syncing, and the served version stays. Fix the same file to the content you want and save it; the conflict clears when it matches the latest server content or the save succeeds. Do not edit baselines or _errors.md to clear it |
| The build failed (not Media) | The previous good snapshot keeps being served. Could not publish the latest HTML in the HTML tab shows the failing path and reason (reference format, size over the limit after Media rewriting, and so on). Fix it and save again |
| Referenced Media is missing or not ready | Source sync is accepted and the build fails. The diagnostic names the first reference and the count as "(and N more)". Once the Media is ready, HTML rebuilds automatically. For missing, failed, or deleted Media, publish a replacement: reuse the same path for a path reference, or update an ID reference to the new Media ID and sync again |
Read html/_errors.md before reporting HTML work as complete.
View HTML pages (members)
The Project's HTML tab separates browser-openable pages from supporting files.
- Pages lists each
.htmlby file name and path.index.htmlis marked Entry. Selecting a row opens that page in a new tab on an origin separate from aachat - Assets shows CSS, JavaScript, images, and similar files as a folder tree, collapsed by default
Updatedis the last source update accepted by aachat, not when a delivery snapshot was published- When there are Media references, "N media dependencies" and their kinds are shown
A page row opens only when index.html exists and a snapshot built from the latest source is being served. During a rebuild, Publishing the latest HTML is shown and rows cannot be opened until the new snapshot is served. If a build fails, the previous good snapshot is still served, but the list does not open it as the latest source. Without index.html, index.html is missing is shown.
Share — Share HTML (public URL for outside viewers)
To let outside people view it with just a URL, click Share in the HTML tab to open the Share HTML dialog.
- There is only one public URL per Project. Choose the expiry under Expires after (1, 7, or 30 days; default 7), optionally turn on Require a generated password, and click Enable and copy
- A generated password is shown only once. Copy it with the URL while Save the generated password is displayed. If it is lost, reset it
- After enabling, you can copy the URL, Extend to 30 days (Renew for 30 days when expired), Add password / Reset password / Remove password, Reset link, and Stop sharing. The state is shown as Active / Expired / Unavailable
- The URL is on a sharing subdomain (
h<key>.html.aachat.io). Reset link invalidates the old URL immediately and creates a new one - Agents do not issue public URLs; people decide and operate publication. An agent points the person to the
html_management_urlit receives in a Session (the HTML tab with?dialog=share-html)
Starting an Archive of the Project deletes its public HTML share. Returning the Project to active does not restore it, so enable sharing again if needed and hand out the new URL (Projects).
Share HTML publishes the Project's entire built HTML, not just one page. Review every file, data file, script, and Media dependency before enabling it. Later successful builds are also reflected to viewers. While the latest build is failing, the public URL keeps serving the previous snapshot.
Sharing subdomains on the old h<key>.html.aachat.work domain are retired and return 403. Replace URLs you handed out earlier by copying the current URL from the Share HTML dialog.
Build a small report
With aachat up running, save the following as aachat/teams/acme/projects/customer-research/html/report.html, replacing the Project path with yours, and also save html/report.css. No backend or external script is needed.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Customer research</title>
<link rel="stylesheet" href="report.css">
</head>
<body>
<main>
<h1>Customer research</h1>
<p>Customers need a clear delivery date before ordering.</p>
<details><summary>Next action</summary>
<p>Confirm the proposed wording with the project owner.</p>
</details>
</main>
</body>
</html>html/report.css:
body { margin: 0; font: 1rem/1.6 system-ui, sans-serif; color: #172033; }
main { max-width: 48rem; margin: auto; padding: 2rem; }
summary { cursor: pointer; font-weight: 600; }Add <a href="report.html">Customer research</a> to the existing html/index.html hub and keep links to other pages. For a Project with only one report, you can save the report itself as html/index.html. The CSS path is relative to the HTML file, so update it if you move files into a subdirectory.
After sync and build succeed, open HTML → Pages → report.html. Expect the heading, centered readable body text, and a Next action section that opens when selected. Members do not need a public share to view it. To show ready Media, use the reference rules above; a local image name alone does not mean it has been published.
Use Database from a member preview
HTML opened with Open HTML can read and write the same Project's Database by sending JSON {sql, params} to POST /_aachat/database/query. Use this root-relative path from nested pages too. Authentication uses the existing preview Cookie and checks the viewer's current Project membership on every request. Viewers can SELECT; Collaborators and Admins can also INSERT, UPDATE, and DELETE. Public shares, including password-protected shares, cannot perform any Database operations.
Database operations from preview are for Human members. Agents use the existing Session Database API, which checks their own running Session and current coverage. Agents can still view HTML and Media.
Input accepts only a sql string and an optional params array of strings, with a 1 MiB body limit. Success returns statement_kind, columns, column-ordered rows, changes, last_row_id, and duration_ms. Failures return an HTTP status and error.code / error.message. Zero changed rows is a successful result. Existing Project Database SQL restrictions and migrations apply; HTML cannot change the schema.
HTML JavaScript, including external scripts, can operate with the viewer's permissions. The HTML author implements save controls, validation, duplicate-click prevention, conflict detection, and refresh. Display database values using textContent or another safe rendering method. OPERATION_OUTCOME_UNKNOWN, project_html_database_transport_error, connection loss, abort, or JSON parsing failure can mean a write already happened. Check with SELECT instead of automatically resending it.
Project HTML hosts static files. It does not start a server, inject credentials, or give viewers the author's Project API permissions. To include DB results in a public share, prepare a static data file and review its contents before sharing.
Check update and sharing failures
If a page is missing, check the Project path, edit permission, path rules and file limits, html/_errors.md, and the HTML tab diagnostics. The Publishing state is the period between source acceptance and a usable new build. Seeing the previous good snapshot is not evidence that new source was applied.
If a public reader cannot open it, check the expiry, password, Reset link / Stop sharing state, Project status, whether index.html exists, and the latest build. Stop sharing ends publication but does not retrieve copies the recipient already saved. To share a single document instead, see Sharing.