@mindstudio-ai/remy 0.1.304 → 0.1.305
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -46,6 +46,7 @@ All fields are nested under the `"web"` key.
|
|
|
46
46
|
| `prerender` | `object` | — | Opt into prerendering the listed routes/patterns for crawlers/unfurlers. See "Prerendering" below. |
|
|
47
47
|
| `mounts` | `array` | — | Serve other same-workspace apps under path prefixes of this app's hosts. See "Mounting other apps" below. |
|
|
48
48
|
| `redirects` | `array` | — | Path-level redirects. See "Redirects" below. |
|
|
49
|
+
| `rewrites` | `array` | — | Serve different content at the same URL. See "Rewrites" below. |
|
|
49
50
|
| `trailingSlash` | `"strip"` \| `"append"` | — | Enforce a canonical trailing-slash form with a 308. Off by default. |
|
|
50
51
|
|
|
51
52
|
### Frontend SDK
|
|
@@ -168,11 +169,26 @@ Declare moved URLs in `web.json` — never ship a component that redirects clien
|
|
|
168
169
|
|
|
169
170
|
`trailingSlash` picks the canonical form (`"strip"`: `/about/` → `/about`; `"append"`: the reverse, skipping the root and paths with file extensions). Off by default. Write `source` patterns without trailing slashes either way — normalization and matching resolve in one hop. Sources under `/_/` are rejected, as are self-referential and two-rule loops. A redirecting path is never prerendered, so don't list one in `prerender.paths`.
|
|
170
171
|
|
|
172
|
+
### Rewrites
|
|
173
|
+
|
|
174
|
+
Serve different content at the same URL — no redirect. The way to give a clean path to a file that isn't in the build output:
|
|
175
|
+
|
|
176
|
+
```json
|
|
177
|
+
{ "web": { "rewrites": [
|
|
178
|
+
{ "source": "/sitemap.xml", "destination": "/_/files/public/site/sitemap.xml" },
|
|
179
|
+
{ "source": "/docs/*rest", "destination": "/help/*rest" }
|
|
180
|
+
] } }
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
`destination` is either `/_/files/public/<store>/<key>` (the object's bytes served inline — use this for anything the app generates at runtime and uploads: sitemaps, `robots.txt`, `llms.txt`, `.well-known/*`; the store must be public, private is rejected at build) or another path in the build output. Same `source` syntax as redirects, first match wins. Objects over 10 MB fall back to a CDN redirect. External URLs are not supported (use `mounts`), nor are other `/_/` surfaces.
|
|
184
|
+
|
|
185
|
+
Redirects resolve before everything; rewrites resolve at the content lookup, after prerendering — so a path with both gets the redirect.
|
|
186
|
+
|
|
171
187
|
### Mounting other apps
|
|
172
188
|
|
|
173
189
|
Rare: `mounts` serves another same-workspace app under a path prefix of this app's hosts — `{ "web": { "mounts": [{ "path": "/docs", "app": "docs-site" }] } }` (`app` = the target's `custom_subdomain` or appId). The child is served first-class (its own bundle, session, backend, prerendering) and needs no mount-specific config; the two serving conventions above are what make an app mountable.
|
|
174
190
|
|
|
175
|
-
Under a mount the child's own `web.json` governs its
|
|
191
|
+
Under a mount the child's own `web.json` governs its routing: its `prerender.paths` gates its mounted pages, its `prerender.invalidate` purges them, and its `redirects`/`rewrites`/`trailingSlash` apply within the prefix (written against its own paths). SEO files are NOT handled for you — the child must generate its sitemap with the mounted URLs, and the parent must advertise it in its own `robots.txt` or sitemap index. Canonicals must be written from the page's own location; a hardcoded absolute canonical points crawlers back at the child's host and undoes the mount.
|
|
176
192
|
|
|
177
193
|
## API Interface
|
|
178
194
|
|
|
@@ -39,7 +39,7 @@ These are things we already know about and have decided to accept:
|
|
|
39
39
|
- use [wouter](https://github.com/molefrog/wouter) for React routing instead of reaching for react-router
|
|
40
40
|
- uploading user files should always happen via `platform.uploadFile()` from `@mindstudio-ai/interface` — not custom S3 code, not FormData to a method endpoint
|
|
41
41
|
- for build-time prerendering of purely static sites (marketing pages with no dynamic content — distinct from the platform's crawler prerendering, below), roll your own with a post-build `renderToString` script — do not use `vite-prerender-plugin` (it bundles the prerender script as a client chunk, adding ~800KB to the user-facing bundle with no way to prevent it)
|
|
42
|
-
- **Prerendering for crawlers/unfurlers is a platform feature — don't design around it.** For SEO / link-unfurl / AI-crawler visibility on a non-static SPA, the platform already handles it: routes opt in via `web.json` (`{ "web": { "prerender": { "paths": ["/blog/*"] } } }`), the SPA signals readiness by setting `data-prerender-ready` on the html element, deploys invalidate the snapshot cache automatically, and content that changes outside deploys is invalidated at runtime with `await prerender.invalidate([...])` from `@mindstudio-ai/agent` (called from the mutating method). It serves cached headless snapshots of the live SPA to bots — it is NOT build-time rendering. Do not recommend post-build render scripts, rebuild-on-content-change, or third-party prerender services for this. An app mounted under another app's path prefix keeps its own `prerender.paths` and its own `prerender.invalidate` — don't recommend moving prerender config to the parent
|
|
42
|
+
- **Prerendering for crawlers/unfurlers is a platform feature — don't design around it.** For SEO / link-unfurl / AI-crawler visibility on a non-static SPA, the platform already handles it: routes opt in via `web.json` (`{ "web": { "prerender": { "paths": ["/blog/*"] } } }`), the SPA signals readiness by setting `data-prerender-ready` on the html element, deploys invalidate the snapshot cache automatically, and content that changes outside deploys is invalidated at runtime with `await prerender.invalidate([...])` from `@mindstudio-ai/agent` (called from the mutating method). It serves cached headless snapshots of the live SPA to bots — it is NOT build-time rendering. Do not recommend post-build render scripts, rebuild-on-content-change, or third-party prerender services for this. An app mounted under another app's path prefix keeps its own `prerender.paths` and its own `prerender.invalidate` — don't recommend moving prerender config to the parent. SEO files under a mount are NOT automatic: the child generates its sitemap with the mounted URLs (point its base-URL config at the mount) and the parent advertises it in its own robots.txt or sitemap index. To give a generated file a clean path (`/sitemap.xml`, `/robots.txt`, `/llms.txt`, `.well-known/*`) use a `web.json` rewrite to `/_/files/public/<store>/<key>` — never a redirect, which moves the URL, and never a client-side component. The developer's main context carries the full interfaces reference with exact semantics — tell them to consult it rather than improvising.
|
|
43
43
|
|
|
44
44
|
### Common pitfalls (always flag these)
|
|
45
45
|
|