Files
Simon James b54a3139c7 Initial commit: Qortal Web Builder monorepo.
Includes QWB, Qortal Web, and Q-Shops Q-Apps with shared packages and build scripts.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-09 12:17:29 +00:00

74 lines
6.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Running this Q-App in Qortal Hub (and on QDN)
The [Qortal](https://github.com/qortal) org hosts the core chain, [Qortal-Hub](https://github.com/Qortal/Qortal-Hub), [qapp-core](https://github.com/Qortal/qapp-core) helpers, and app examples. For protocol-level behaviour of websites vs apps, see [**Q-Apps.md** in the qortal core repo](https://github.com/Qortal/qortal/blob/master/Q-Apps.md) and the [**Q-Apps** section on qortal.dev](https://qortal.dev/docs/q-apps).
## What to ship
1. `npm run build` — produces **`dist/`** with `index.html`, `assets/`, `manifest.json`, `zip-store.js`, `favicon.svg`, etc.
2. Create a **flat zip of everything inside `dist/`** (not the parent “Portfolio” zip that also wraps `app.js` / `extracted/` — that is for a different release layout). The Hub and QDN expect the **Q-App root** to match the zip root: `index.html` next to `assets/…` and `zip-store.js`.
Use either:
- `bash scripts/make-zip.sh` — zips the **`dist/`** tree into `Qortal-Hub-Dev-Test-YYYYMMDD.zip` and mirrors to `extracted/`, or
- Manually: `( cd dist && zip -r ../my-qapp.zip . )`
3. In **Qortal Hub**, load that zip and use **Preview** (see Q-Apps.md: *Select "Preview" in the UI after choosing the zip*) so you can test before publishing to QDN.
## WEBSITE vs APP (important for a Vite SPA)
From [Q-Apps / QDN routing](https://github.com/Qortal/qortal/blob/master/Q-Apps.md):
- **`WEBSITE`**: a missing `filepath` returns 404; there is no automatic “send everything to `index.html`” for unknown paths.
- **`APP`**: unhandled requests are routed to `index.html`, which is what most single-page apps (React + client router) expect when the host resolves subpaths.
For the **builder UI** loaded as a registered Q-App, prefer publishing/loading it as an **APP**-style package when the Hub allows it, so subpaths and asset loading behave like a normal SPA. Your **published end-user site** (users `website.zip`) is still a **`WEBSITE`** resource where appropriate.
### APP preview: “Could not load … /render/APP/…/assets/…”
If the Hub opens the app at a URL like `/render/APP/YourName` **without** a trailing slash, the browser resolves relative URLs such as `./assets/index-….js` against `/render/APP/` (dropping your name from the path), so JS/CSS **404**. **WEBSITE** URLs often include `index.html` or a trailing slash, so the same zip can appear to work only as WEBSITE.
This project injects a **`&lt;base href&gt;`** (see the first script in `dev.html` / `site.html`) so the app root always ends with `/`. Rebuild and re-zip **`dist/`** after pulling this fix.
### Published site: embedded Q-Apps and wallet
Visitors are **not** auto-connected to the Hub wallet: they must click **Authenticate** in the site chrome. Only then does the store hold a wallet address, **`sessionTag`** updates, embed URL cache clears, and **`_snConn`** is appended to embedded `/render/APP/…` iframe URLs so the Hub can align the child frame with the parent session. The embed resolver reads **`sessionTag` only after** `await` (no stale `_snConn`).
If auth **inside** an embedded Q-App still fails after you authenticated the **page**, that is often a **Hub** limitation (`qortalRequest` only in the top window). Use **Open in Qortal** on the Q-App tile (new tab). For core fixes, the Hub team needs version, OS, and whether the inner app uses `qortalRequest`.
### Why **Authenticate** or **Connect** “does nothing”
1. **You must use the Qortal Hub**
`GET_USER_ACCOUNT` is not a public HTTP API. It is implemented by the Hubs `qortalRequest` (injected in the page, or forwarded from our **inline stub** to `window.parent`). Opening the built `site.html` or `index.html` in **Chrome/Firefox alone** (file:// or a random `https://` host) **cannot** complete wallet auth.
2. **Inline bridge + top-level window**
If the Hub has **not** injected `qortalRequest` and our **fallback stub** is active (`__QWB_QORTAL_BRIDGE_STUB__` on `window`), wallet calls are sent to **`window.parent`**. If you are **not** inside a Hub iframe (`parent === top`), that path **fails by design**. Open the resource from the Hub (**Browse** → your names **WEBSITE**, or `qortal://WEBSITE/…`).
3. **Hub version**
Older Hub builds may handle `postMessage` / `MessageChannel` for `GET_USER_ACCOUNT` differently. Update the Hub if auth always times out.
4. **Embedded Q-Apps after you authenticated the page**
The site can append `_snConn` to embed URLs only **after** you use **Authenticate**.
The published **WEBSITE** page includes a small **message relay** (`site.html` / `dev.html`): when an embedded Q-Apps stub sends `qortalRequest` to its **parent** (this site, not the Hub), the parent calls its own `qortalRequest` and returns the result on the `MessageChannel` so the embed can use the same wallet. If a Q-App still cannot connect, use **Open in Qortal** on the tile, or check Hub version.
**What to send when reporting issues:** Qortal Hub version, OS, exact URL (e.g. `qortal://WEBSITE/Name` vs external site), browser console errors, and whether `window.qortalRequest` exists and is native or the stub (`__QWB_QORTAL_BRIDGE_STUB__`).
## Runtime API
- `qortalRequest()` is [injected by the core](https://qortal.dev/docs/q-apps); the builder uses it via `getQortalRequest()` in `src/lib/qortalEnv.ts`.
- **Official REST / node API reference (debugging):** [Qortal API Documentation](https://api.qortal.org/api-documentation/) — useful to compare request/response field names and node behaviour with what the Hub bridge returns; interactive flows in this app use **`qortalRequest` actions** (see `src/lib/qortalClient.ts`), not raw HTTP, but the same domain concepts apply.
- Q-Apps are **static files**; ship fonts and JS **in the zip** — avoid relying on public CDNs for required assets (see project `.cursor/rules/qortal-qdn-sandbox.mdc`).
## If the UI stays on “Loading…” or a gray screen
1. **Network tab**: `assets/index-*.js` and `index-*.css` must be **200** (same folder as `index.html`). Root-absolute paths like `/assets/...` or `/zip-store.js` often **404** when the app is not at the site root — this project uses **relative** `./` URLs and strips `crossorigin` in `vite.config.ts` to avoid CORS-related fetch failures in some Hub builds.
2. **Zip layout**: the paths inside the zip must match what the browser requests (flat `dist` contents).
3. Re-run **`npm run build`** after any HTML/Vite config change, then re-zip **only** `dist/`.
## References
- [Qortal on GitHub](https://github.com/qortal) — core, Hub, `qapp-core`, and example apps.
- [Q-Apps.md (qortal core)](https://github.com/Qortal/qortal/blob/master/Q-Apps.md) — QDN resources, `qortalRequest`, routing.
- [qortal.dev Q-Apps docs](https://qortal.dev/docs/q-apps) — API overview.
- [Qortal API documentation](https://api.qortal.org/api-documentation/) — node/REST reference for debugging and cross-checking shapes.
- [qapp-core README](https://github.com/Qortal/qapp-core) — optional npm helpers for new apps.