b54a3139c7
Includes QWB, Qortal Web, and Q-Shops Q-Apps with shared packages and build scripts. Co-authored-by: Cursor <cursoragent@cursor.com>
74 lines
6.9 KiB
Markdown
74 lines
6.9 KiB
Markdown
# 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 **`<base href>`** (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 Hub’s `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 name’s **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-App’s 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.
|