← Back to Superprez

AI prompt templates & Superprez zip packaging

Everything below is written so an assistant can understand Superprez hosting from the first run: Git/zip layout, build/start contracts, networking, entry HTML, and the two supported deployment patterns — plus copy-ready prompts.

Making a presentation compatible with Superprez

Superprez hosts your deck as a real web app cloned from GitHub. After you upload a zip (or connect a repo), our builders install dependencies, build if needed, and start a process that serves HTML to your audience. The human title of the presentation is set in the Superprez UI; your app's <title> tag is separate and should still be sensible.

You must satisfy both: Git / zip packaging rules (so the repo imports cleanly) and runtime rules (so Superprez and our hosting stack can reach your app and find an entry page). Failure on (1) is usually wrong folder nesting or missing required files. Failure on (2) is usually nothing listening on the right port, binding only to localhost, serving the wrong folder, or skipping build so no dist/ exists.

Superengine ports & examples

Decks run on Superengine-compatible layouts (manifest + compose templates, or Node build/start flows). Before authoring Pattern 1, skim Superengine documentation— official docs explain port manifests, compose.yaml.hbs, nginx/static patterns, and link to example repositories that match production expectations.

Tip: keep this page open next to your IDE — every numbered subsection maps directly to the one-shot prompt in section G.

A. Canonical zip / repository layout

Topology (most common failure)

Either: package.json at the root of the zip, or exactly one top-level folder that directly contains package.json. Do not double-nest (e.g. MyDeck/MyDeck/package.json).

Exclude from the archive

Do not commit: node_modules, dist, build, .next, coverage, other generated output, __MACOSX, .DS_Store, Thumbs.db, stray zip files.

Required at the project root (after unzip / clone)

FilePurpose
package.jsonMust define scripts (see below). Use engines if Node version matters.
package-lock.json or pnpm-lock.yamlCommitted lockfile; dependencies must install deterministically on Linux builders.
README.mdExact commands: install, build, start; which URL and port to open locally; note if the server binds 0.0.0.0.
picture.pngSmall cover image for the catalog (simple graphic is fine).
.env.exampleEvery environment variable your app or scripts read, with placeholders only (no secrets).
DockerfileInclude one only if your stack truly needs a container build. If present, it must match what README.md says.

Size

Keep the uncompressed project under ~12 MB before base64 upload limits.

Path characters

Use only safe path segments: [A-Za-z0-9._-] per segment (avoid spaces and exotic Unicode in file and folder names) so zip import sanitization does not strip or break paths.

B. Required package.json scripts

Your root package.json must expose:

"scripts": {
  "build": "...",
  "start": "..."
}

Contract

  • build — Produces runnable static assets and/or a runnable server build (e.g. dist/, .next, compiled output). It must exit 0 on a clean Linux machine with only repo + lockfile + npm install (or pnpm install) already run.
  • start — Starts the HTTP server your audience will hit. It must listen on process.env.PORT when PORT is set (recommended). If PORT is not set, document a single default port in README.md and use that consistently in code.

Order

Hosting runs npm install (or pnpm install), then npm run build, then npm run start (exact package manager depends on lockfile — document which one you use in README.md).

Critical: start must serve the tree that exists after build.

If HTML is only generated under dist/, start must serve dist/, and you must never rely on “there is already a dist/ in the zip” — generated folders must not be committed.

C. Networking (preview and live viewing)

Browsers reach your deck through Superprez; our API may fetch your app from the host/port advertised by our hosting/runtime layer.

Your server MUST

  • Listen on 0.0.0.0 (all interfaces), not only 127.0.0.1, unless our documentation for your specific template says otherwise.
  • Honor PORT from the environment when provided.
  • If you document a default port in README.md (e.g. 8080 or 4173), state clearly: “In production, Superprez sets PORT; locally you may use the default.”

D. Entry HTML and URL paths

After clone and build, our tooling must be able to resolve a useful index.html for the root URL of your server.

Practical rules

  • Prefer either index.html at the repository root and serve it from start, or index.html under dist/ (or build/) after build, and start must serve that folder as the site root.
  • Do not leave index.html only at repo root while start only serves dist/ unless build copies index.html (and assets) into dist/ every time.
  • All static assets you reference (JS, CSS, JSON, images) must be part of the repo or produced by build, with paths that work when served from your chosen root (avoid hard-coded absolute URLs to localhost).

E. Two supported patterns (choose one explicitly)

To avoid ambiguity for authors and for AI tools, Superprez documents two compatible patterns.

Pattern 1 — Superengine port (static site under public/, nginx)

Use this when you want maximum compatibility with our default “app port” flow: static files + official compose template.

You MUST include (names exact)

  • manifest.json — app-spec-version, subject, entitlements, templates listing at least compose.yaml.hbs (and any other required templates).
  • compose.yaml.hbs — Typically an nginx (or equivalent) service that bind-mounts ./public read-only to the web root inside the container.
  • public/ — Contains public/index.html and the rest of your static site (CSS, JS, data JSON, etc.).

package.json may still provide build: validate that public/index.html exists (or run a trivial static asset step). start: optional local static server serving public/ for development.

Do not require a committed dist/ for Pattern 1; the live docroot is public/.

Reference: align with official Superengine port examples — see Superengine documentation.

Pattern 2 — Node / framework app (build → output dir, then start)

Use this for Vite, Next, custom Node servers, etc.

You MUST

  • Implement build so the full site (including index.html at the served root) exists under a known directory (e.g. dist/, build/, .next with the correct start command for that stack).
  • Implement start so it serves that directory (or runs the framework production server documented in README.md).
  • Document Node version in engines and in README.md if relevant.

Pattern 2 fails most often when authors assume npm start alone is enough without a prior npm run build on the server, or when start serves the wrong folder.

F. Interactive decks and /data

If you ship JSON or CSV for charts:

  • Put files under a clear path (public/data/… for Pattern 1, or dist/data/… after build for Pattern 2).
  • Load them with relative URLs from your app root (e.g. /data/foo.json).
  • Document in README.md where authoring files live in Git vs where they appear after build.

G. AI / collaborator prompt

Paste into your AI assistant (ChatGPT, Claude, Copilot, Gemini, etc.). Same content ships in the Add presentation modal as “Copy prompt”.

You are packaging an interactive presentation as a web app for **Superprez drop-code (zip upload)**. The zip MUST work on **Superprez** (install → build → start / preview) and as a **Superengine-compatible port** (manifest + Handlebars compose templates). ## Public references (only these — do not assume access to any private repo) - Official Superengine ports catalog (study file shapes): https://software.superengine.tech/superengine/ - Superengine documentation: https://www.superengine.tech/docs - Port license (text for LICENSE.txt): https://www.superengine.tech/legal/software-license-agreement-for-ports On the ports catalog, open any published port (e.g. wordpress-port) and mirror its **structural** conventions: manifest app-spec 1.2, templates array, compose service shape, logging/restart, embedded_ui overview link pattern, LICENSE.txt / NOTICE.txt / picture.png at port root. Slide decks use a **simpler** entitlement set than database apps — follow the templates in **this prompt**, not WordPress’s full entitlement list. ## Context - Superprez hosts the deck as a real web app from GitHub or zip. Builders run install, build, and start. The presentation **title in the Superprez UI** is separate from your HTML `<title>`. - Default architecture: **static files under `html/`**, nginx in production (via Superengine compose), Node static server for Superprez preview. Do **not** use Vite/React/Next unless the user explicitly requires it. ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ STEP 0 — IF THE USER GAVE YOU HTML + ASSETS (most common failure) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Do this **before** adding Superengine boilerplate: 1. Create folder **`html/`** at the package root (sibling of `package.json`, not inside it). 2. Put the entry file at **`html/index.html`**. Rename the user’s file (e.g. `deck.html`, `My Slides.html`) to `index.html`. 3. Move **every** asset the HTML references (CSS, JS, images, fonts, data JSON) under **`html/`**, preserving relative paths. Examples: - `styles.css` next to `index.html` → `html/styles.css` - `assets/logo.png` → `html/assets/logo.png` 4. Update `<link>`, `<script>`, `<img>`, `url(...)` paths in `index.html` if needed so they still resolve from `/` when served. 5. **Never** leave `index.html` at the zip root alongside `package.json`. Superprez/nginx serves **`html/`**, not the repo root. 6. After edits, add cache-bust query strings on static references, e.g. `styles.css?v=DECK_SLUG-1.0.0`, `app.js?v=DECK_SLUG-1.0.0` (use the user’s real filenames, not only styles.css/app.js). ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ GOLDEN RULES ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 1. **One docroot name everywhere:** `html/` in compose volume, `npm start`, and `validate-build.js`. 2. **Entitlements:** declare **only** what `compose.yaml.hbs` and `embedded_ui/*.hbs` use. For static nginx decks that is **`port-number`**, **`host`**, **`os`** — in that order. Do **not** add `folder-path`, `uid`, or `gid` unless compose actually references them. 3. **Compose port line** must be a YAML list item with **unquoted** Handlebars: ` - {{entitlements.port-number}}:80` Wrong: quoted whole mapping, spaces inside `{{ }}`, or missing list dash. 4. **Zip root** = `package.json` + `manifest.json` + `compose.yaml.hbs` + `html/` + legal files — OR exactly **one** top-level folder containing those (no `Deck/Deck/package.json`). 5. **Lockfile required:** commit `package-lock.json` (even with zero npm dependencies). 6. **`npm start`** must bind **`0.0.0.0`**, honor **`process.env.PORT`** (default **8080**), serve **`html/`**. 7. **LF line endings** in JSON/YAML (no Windows CRLF in manifest/compose). 8. **No secrets** in the zip; `.env.example` with placeholders only. 9. **Exclude** from zip: `node_modules`, `dist`, `build`, `.next`, `__MACOSX`, `.DS_Store`, nested zips. 10. If you **cannot** run shell commands, produce all files completely and tell the user exactly how to verify (see Verification). ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ TARGET FILE TREE (create every path) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ . ├── package.json ├── package-lock.json ├── server.js ├── manifest.json ├── compose.yaml.hbs ├── picture.png ├── LICENSE.txt ├── NOTICE.txt ├── README.md ├── .env.example ├── html/ │ ├── index.html │ └── … (all deck assets) ├── embedded_ui/ │ ├── overview.html.hbs │ └── about.html └── scripts/ ├── validate-build.js └── write-app-icon.js ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ FILE TEMPLATES — copy, then replace DECK_* placeholders ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Replace: - DECK_TITLE — human-readable deck name (manifest + UI copy) - DECK_SLUG — lowercase alphanumeric hyphenated id (cache-bust strings) - DECK_VERSION — semver, bump on every redeploy (e.g. 1.0.0) - DECK_SERVICE_SUFFIX — short unique lowercase suffix for compose service (e.g. slides, deck42) --- manifest.json --- { "app-spec-version": "1.2", "subject": { "name": { "en": "DECK_TITLE" }, "version": "DECK_VERSION" }, "entitlements": [ { "type": "PortUnspecifiedStaticNumber", "name": "port-number", "description": { "en": "HTTP port mapped to nginx container port 80." } }, { "type": "HostHostnameOrIPAddress", "name": "host", "description": { "en": "Hostname or IP address of your server." } }, { "type": "OperatingSystem", "name": "os", "description": { "en": "Operating system." } } ], "templates": [ "compose.yaml.hbs", "embedded_ui/overview.html.hbs" ], "actions": [] } --- compose.yaml.hbs --- services: {{app_id}}-DECK_SERVICE_SUFFIX: image: nginx:1.27-alpine restart: always volumes: - ./html:/usr/share/nginx/html:ro ports: - {{entitlements.port-number}}:80 logging: driver: local --- embedded_ui/overview.html.hbs --- <section class="section"> <div class="container"> <h2 class="title is-4">DECK_TITLE</h2> <p class="mb-3">Interactive HTML presentation.</p> <a href="http://{{entitlements.host}}:{{entitlements.port-number}}" target="_blank" rel="noopener noreferrer" class="button is-dark">Open deck</a> </div> </section> --- embedded_ui/about.html --- <section class="section"> <div class="container"> <h2 class="title is-4">DECK_TITLE</h2> <p>Static HTML deck packaged for Superprez and Superengine.</p> <p>Production: nginx serves <code>./html</code> read-only. Compose port mapping uses unquoted <code>{{entitlements.port-number}}:80</code>.</p> <p>License: <a href="https://www.superengine.tech/legal/software-license-agreement-for-ports" target="_blank" rel="noopener noreferrer">Software License Agreement for Ports</a>.</p> </div> </section> --- LICENSE.txt --- This software is licensed under the Software License Agreement for Ports available at the URI below: https://www.superengine.tech/legal/software-license-agreement-for-ports If, for any reason, the URI provided in this file to the Software License Agreement for Ports does not redirect to the website of the copyright owner of this software, and, to the correct page on this website, you may not use this software. This license does not apply to the files not under Superengine copyright as detailed in the NOTICE.txt file. This software uses the following third-party software: - the nginx image with the tag 1.27-alpine from Docker Hub Third-party software has a different copyright owner and license. --- NOTICE.txt --- Copyright 2025 Superengine, except for the following files: - picture.png - html/ (presentation content and assets) --- package.json --- { "name": "DECK_SLUG", "version": "DECK_VERSION", "private": true, "description": "DECK_TITLE — Superprez / Superengine static deck", "engines": { "node": ">=18" }, "scripts": { "icon": "node scripts/write-app-icon.js", "build": "node scripts/validate-build.js", "start": "node server.js" } } --- package-lock.json (zero-dependency projects — required for npm ci) --- { "name": "DECK_SLUG", "version": "DECK_VERSION", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "DECK_SLUG", "version": "DECK_VERSION", "engines": { "node": ">=18" } } } } --- .env.example --- # Optional local preview (Superprez sets PORT in hosting) PORT=8080 --- README.md (minimum) --- # DECK_TITLE Static interactive deck for **Superprez** (zip upload) and **Superengine** (manifest + compose). ## Local preview npm ci npm run icon npm run build npm run start Open http://127.0.0.1:8080/ (or set PORT). GET / must return html/index.html. ## Superengine files - manifest.json (app-spec 1.2) - compose.yaml.hbs (nginx → ./html) - embedded_ui/overview.html.hbs, embedded_ui/about.html - picture.png, LICENSE.txt, NOTICE.txt Official port examples: https://software.superengine.tech/superengine/ --- server.js --- const http = require("http"); const fs = require("fs"); const path = require("path"); const PORT = Number.parseInt(process.env.PORT || "8080", 10); const PUBLIC = path.join(__dirname, "html"); const MIME = { ".html": "text/html; charset=utf-8", ".js": "application/javascript; charset=utf-8", ".css": "text/css; charset=utf-8", ".json": "application/json", ".png": "image/png", ".jpg": "image/jpeg", ".jpeg": "image/jpeg", ".gif": "image/gif", ".svg": "image/svg+xml", ".ico": "image/x-icon", ".webp": "image/webp", ".woff": "font/woff", ".woff2": "font/woff2", ".txt": "text/plain; charset=utf-8", }; function safeJoin(rootDir, requestPath) { const decoded = decodeURIComponent(requestPath.split("?")[0]); const rel = path.normalize(decoded).replace(/^\/+/, ""); if (rel.includes("..")) return null; const full = path.join(rootDir, rel); if (!full.startsWith(rootDir)) return null; return full; } const server = http.createServer((req, res) => { if (!req.url || req.method !== "GET") { res.writeHead(405, { "Content-Type": "text/plain; charset=utf-8" }); res.end("Method Not Allowed"); return; } let pathname = req.url.split("?")[0]; if (pathname === "/") pathname = "/index.html"; const filePath = safeJoin(PUBLIC, pathname); if (!filePath) { res.writeHead(403, { "Content-Type": "text/plain; charset=utf-8" }); res.end("Forbidden"); return; } fs.stat(filePath, (err, st) => { if (err || !st.isFile()) { res.writeHead(404, { "Content-Type": "text/plain; charset=utf-8" }); res.end("Not Found"); return; } const ext = path.extname(filePath).toLowerCase(); res.writeHead(200, { "Content-Type": MIME[ext] || "application/octet-stream" }); fs.createReadStream(filePath).pipe(res); }); }); server.listen(PORT, "0.0.0.0", () => { console.log("Serving html/ at http://0.0.0.0:" + PORT); }); --- scripts/validate-build.js --- const fs = require("fs"); const path = require("path"); const root = path.join(__dirname, ".."); const fail = (msg) => { console.error("FAIL:", msg); process.exit(1); }; const requireFile = (rel) => { if (!fs.existsSync(path.join(root, ...rel.split("/")))) fail("missing " + rel); }; [ "html/index.html", "picture.png", "manifest.json", "compose.yaml.hbs", "LICENSE.txt", "NOTICE.txt", "embedded_ui/overview.html.hbs", "embedded_ui/about.html", "package-lock.json", ].forEach(requireFile); const composeRaw = fs.readFileSync(path.join(root, "compose.yaml.hbs"), "utf8"); let portsOk = false; for (const line of composeRaw.split("\n")) { const t = line.trim(); if (!t.startsWith("-") || !t.includes("entitlements.port-number")) continue; portsOk = true; if (!/\{\{entitlements\.port-number\}\}:80/.test(t)) { fail("compose.yaml.hbs ports line must contain {{entitlements.port-number}}:80 unquoted"); } if (/^-\s*["']/.test(t)) fail("compose.yaml.hbs ports line must not quote the whole mapping"); } if (!portsOk) fail("compose.yaml.hbs missing ports mapping for {{entitlements.port-number}}:80"); if (!composeRaw.includes("./html:/usr/share/nginx/html")) { fail("compose.yaml.hbs must mount ./html:/usr/share/nginx/html:ro"); } let manifest; try { manifest = JSON.parse(fs.readFileSync(path.join(root, "manifest.json"), "utf8")); } catch (e) { fail("manifest.json invalid JSON: " + e.message); } if (manifest["app-spec-version"] !== "1.2") fail('manifest.json needs app-spec-version "1.2"'); if (!Array.isArray(manifest.actions) || manifest.actions.length !== 0) fail('manifest.json needs "actions": []'); const templates = manifest.templates; if (!Array.isArray(templates) || templates[0] !== "compose.yaml.hbs" || templates[1] !== "embedded_ui/overview.html.hbs") { fail('manifest.json templates must be ["compose.yaml.hbs", "embedded_ui/overview.html.hbs"]'); } const expected = [ { name: "port-number", type: "PortUnspecifiedStaticNumber" }, { name: "host", type: "HostHostnameOrIPAddress" }, { name: "os", type: "OperatingSystem" }, ]; const ent = manifest.entitlements; if (!Array.isArray(ent) || ent.length !== expected.length) { fail("manifest.json entitlements must be exactly port-number, host, os (3 entries)"); } for (let i = 0; i < expected.length; i++) { if (!ent[i] || ent[i].name !== expected[i].name || ent[i].type !== expected[i].type) { fail("manifest.json entitlements[" + i + "] must be " + JSON.stringify(expected[i])); } } const overview = fs.readFileSync(path.join(root, "embedded_ui/overview.html.hbs"), "utf8"); if (!overview.includes("{{entitlements.host}}") || !overview.includes("{{entitlements.port-number}}")) { fail("embedded_ui/overview.html.hbs must link with host and port-number entitlements"); } console.log("Build OK — Superprez / Superengine static deck checklist passed."); process.exit(0); --- scripts/write-app-icon.js (creates picture.png — no npm deps) --- const zlib = require("zlib"); const fs = require("fs"); const path = require("path"); const W = 256, H = 256, R = 0x2e, G = 0x5b, B = 0xea; const PNG_SIG = Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]); const crcTab = new Uint32Array(256); for (let n = 0; n < 256; n++) { let c = n; for (let k = 0; k < 8; k++) c = (c & 1) !== 0 ? 0xedb88320 ^ (c >>> 1) : c >>> 1; crcTab[n] = c >>> 0; } function crc32(buf) { let c = 0xffffffff; for (let i = 0; i < buf.length; i++) c = crcTab[(c ^ buf[i]) & 0xff] ^ (c >>> 8); return (c ^ 0xffffffff) >>> 0; } function chunk(typ, data) { const t = Buffer.from(typ, "ascii"); const len = Buffer.alloc(4); len.writeUInt32BE(data.length, 0); const body = Buffer.concat([t, data]); const crc = Buffer.alloc(4); crc.writeUInt32BE(crc32(body), 0); return Buffer.concat([len, body, crc]); } const ihdrData = Buffer.alloc(13); ihdrData.writeUInt32BE(W, 0); ihdrData.writeUInt32BE(H, 4); ihdrData[8] = 8; ihdrData[9] = 2; const rowLen = 1 + W * 3; const raw = Buffer.alloc(rowLen * H); for (let y = 0; y < H; y++) { const off = y * rowLen; raw[off] = 0; for (let x = 0; x < W; x++) { const p = off + 1 + x * 3; raw[p] = R; raw[p + 1] = G; raw[p + 2] = B; } } const idatPayload = zlib.deflateSync(raw, { level: 9 }); const out = Buffer.concat([PNG_SIG, chunk("IHDR", ihdrData), chunk("IDAT", idatPayload), chunk("IEND", Buffer.alloc(0))]); fs.writeFileSync(path.join(__dirname, "..", "picture.png"), out); console.log("Wrote picture.png"); ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ HOSTED CACHE (after redeploy) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Bump query strings on CSS/JS (and other static) references in html/index.html, bump manifest.json subject.version, then hard-refresh or use a private window on the live URL. ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ZIP FOR SUPERPREZ UPLOAD ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - Compress the **package root** (folder that directly contains package.json and manifest.json). - On macOS: do not zip the parent folder so the archive opens as `package.json` at top level (or one named folder — not double-nested). - Keep uncompressed size under ~12 MB. - Path segments: ASCII letters, digits, dot, underscore, hyphen only (avoid spaces and special characters in folder/file names). ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ VERIFICATION (required before telling the user the zip is ready) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ If you have a terminal, run from package root: npm ci npm run icon npm run build npm run start Then GET http://127.0.0.1:8080/ must return html/index.html (HTTP 200, HTML body). If you **do not** have a terminal, say so explicitly and give the user these commands. Do **not** claim PASS on the checklist without evidence. ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ DELIVERABLES ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 1. Print the final file tree. 2. List every file you created or changed. 3. For each item below, print PASS or FAIL with the evidence path (or “NOT RUN — user must verify”): - html/index.html exists; all referenced assets exist under html/ - package.json at zip root OR single top-level folder (no double nesting) - manifest.json, compose.yaml.hbs, picture.png, LICENSE.txt, NOTICE.txt at package root - manifest: app-spec 1.2; templates order; actions []; entitlements port-number → host → os only - compose: nginx, ./html volume, unquoted {{entitlements.port-number}}:80 - overview.html.hbs: Open link uses {{entitlements.host}} and {{entitlements.port-number}} - package.json: build + start; package-lock.json present; server.js binds 0.0.0.0 and honors PORT - Cache-bust query params on static assets in index.html if redeploying - .env.example present; no secrets - npm run build exits 0 (or user instructed to run it) Fix every FAIL before delivering the zip. When repackaging after edits: rebuild zip, bump version + cache-bust strings, redeploy on Superprez, hard-refresh browser.

Full prose contract (topology, scripts, networking, patterns): sections A–F above. Superengine port references: superengine.tech/docs.

Additional templates

1) Flagship narrative deck from legacy slides/PDFs

Use when leadership supplies PDFs/PPTX plus brand guidance.

You are a senior front-end engineer. Build a single interactive presentation web app for [COMPANY] targeting [AUDIENCE]. Brand & assets: - Primary colors: [HEX / tokens]. Font stack: [FONTS]. Logo path: /assets/logo.svg (I will place the file). - Recreate narrative flow from: [SOURCES]. Match slide order and metrics; do not invent financials. Product expectations: - Follow this page's "Making compatible with Superprez" guide (sections A–F): topology, build/start contract, PORT + 0.0.0.0, entry HTML, choose Pattern 1 OR Pattern 2 explicitly. - Output package.json scripts: "build" and "start"; accessible responsive 16:9 layout and keyboard navigation between sections. - At least two interactive moments tied to real data under /data (see section F). - Superprez shows the dashboard title separately—still set a sensible <title> aligned with "[DECK_DISPLAY_NAME]". Deliverables: - README + optional /docs/NOTES.md mapping legacy slide numbers to new sections. - Self-verify: clean Linux install → build → start → GET / returns index.html from the served tree.

2) Prepare a repo before linking GitHub in Superprez

Initialize [FRAMEWORK] with deterministic dependencies and satisfy sections A–F on this documentation page. Requirements: - Default branch main; lockfile committed; no absolute paths. - README lists PAT expectations for personal GitHub hosting (fine-grained vs classic scopes per Superprez onboarding docs). - Declare Pattern 1 vs Pattern 2 in README. Provide command cheat sheet + PASS/FAIL checklist before handing off.

3) Edit an exported Superprez zip and ship it back

You have ./deck.zip from Superprez. Tasks: 1) Unzip; detect whether layout is flat vs single-root folder—preserve it exactly. 2) Apply changes: [LIST]. 3) Strip node_modules and build caches before re-zipping. 4) Regenerate picture.png only if branding materially changed. 5) Produce deck-resubmit.zip under ~12MB with the same topology discipline as the incoming archive. Summarize files touched for the presenter changelog. Reminder: uploads become one snapshot commit on main; Superprez rebuilds the git tree from the zip—imports fail if you relocate package.json.

4) Debugging a failed Superprez build

Given this repo tarball and builder stderr [PASTE], enumerate: 1) Missing dependency / script issues vs package.json 2) Node engine mismatches 3) Missing picture.png or Dockerfile promised in README 4) Asset path casing problems 5) Zip topology mistakes (nested duplicate folders) 6) start binding localhost only or wrong directory vs build output (sections C–D) Produce a prioritized patch checklist.

5) Collaborator onboarding without GitHub CLI

Draft email for [NAME]: iterate locally via [COMMANDS], return deck.zip; Superprez applies commits on their behalf. Link to Documentation → Collaboration if helpful.

6) Presenter dashboard title vs in-app headline

Explain how Superprez dashboard title "[SUPERPREZ_TITLE]" relates to in-app H1 "[IN_APP_HEADLINE]"—when they should match vs diverge, plus changelog habits after rebrands.

Product context: Packaging overview, Drop code & zip updates.