✨ feat: enhance project setup and architecture documentation
- Updated `tibi-project-setup` skill to clarify project initialization goals and steps. - Improved `tibi-ssr-caching` skill to detail SSR architecture, responsibilities, and caching mechanisms. - Introduced `website-solution-architecture` skill for translating website requirements into coherent solutions. - Refined `AGENTS.md` to provide a structured roadmap for project development phases. - Added `ADMIN_ASSET_VERSION` to `api/config.yml.env` for asset versioning. - Updated SSR request flow and cache invalidation logic in `api/hooks/ssr/AGENTS.md`. - Removed obsolete `esbuild.config.admin.js` and integrated asset versioning into the main `esbuild.config.js`. - Adjusted `api/collections/content.yml` to utilize asset versioning for admin scripts.
This commit is contained in:
@@ -15,6 +15,7 @@ Use this skill when:
|
||||
- Adding new Svelte 5 reactive patterns
|
||||
- Understanding the API layer and error handling
|
||||
- Working with i18n / multi-language features
|
||||
- Understanding how SSR and SPA loading share one app-level data path
|
||||
|
||||
---
|
||||
|
||||
@@ -81,6 +82,22 @@ Example: /de/ueber-uns → lang="de", routePath="/ueber-uns"
|
||||
|
||||
Root `/` redirects to `/{browserLanguage}/` via `getBrowserLanguage()`.
|
||||
|
||||
### SSR interaction with routing
|
||||
|
||||
This frontend is not just an SPA. The same top-level app also participates in SSR.
|
||||
|
||||
- `frontend/src/ssr.ts` is intentionally thin and should mostly bootstrap locale state and call `render(App, { props: { url } })`.
|
||||
- `App.svelte` owns page loading for both browser and SSR.
|
||||
- Browser navigation triggers page loading from `$effect`.
|
||||
- SSR triggers the same page-loading path directly inside `typeof window === "undefined"`.
|
||||
|
||||
This means route changes, i18n path handling, and content-loading behavior must be reasoned about together. If a route works in the browser but SSR returns empty content or 404, inspect the mapping between:
|
||||
|
||||
- public URL (`/de/...`)
|
||||
- stripped route path (`/...`)
|
||||
- `content.path` in the DB
|
||||
- `api/hooks/config.js` SSR route validation
|
||||
|
||||
### Navigation API
|
||||
|
||||
```typescript
|
||||
@@ -130,6 +147,8 @@ export const ROUTE_TRANSLATIONS: Record<string, Record<SupportedLanguage, string
|
||||
}
|
||||
```
|
||||
|
||||
Keep in mind that these translations affect the public URL shape and therefore also the SSR route-validation layer. Changing localized slugs is not purely a frontend concern.
|
||||
|
||||
---
|
||||
|
||||
## State management
|
||||
@@ -138,17 +157,17 @@ The project uses **Svelte writable/derived stores** (not a centralized state lib
|
||||
|
||||
### Store inventory
|
||||
|
||||
| Store | File | Purpose |
|
||||
| ---------------------- | ---------------------- | ----------------------------------------------------------------------------------- |
|
||||
| `location` | `lib/store.ts` | Current URL state (path, search, hash, push/pop flags) |
|
||||
| `mobileMenuOpen` | `lib/store.ts` | Whether mobile hamburger menu is open |
|
||||
| `currentContentEntry` | `lib/store.ts` | Currently displayed page's `translationKey`, `lang`, `path` (for language switcher) |
|
||||
| `previousPath` | `lib/store.ts` | Previous URL path (for conditional back buttons) |
|
||||
| `apiBaseOverride` | `lib/store.ts` | Override API base URL (used by admin module) |
|
||||
| `cookieConsentVisible` | `lib/store.ts` | Whether cookie consent banner is showing |
|
||||
| `currentLanguage` | `lib/i18n.ts` | Derived from `$location.path` — current language code |
|
||||
| `selectedLanguage` | `lib/i18n.ts` | Writable — synced with `currentLanguage` on navigation |
|
||||
| `activeRequests` | `lib/requestsStore.ts` | Number of in-flight API requests (drives `LoadingBar`) |
|
||||
| Store | File | Purpose |
|
||||
| ---------------------- | ---------------------- | -------------------------------------------------------------------------------- |
|
||||
| `location` | `lib/store.ts` | Current URL state (path, search, hash, push/pop flags) |
|
||||
| `mobileMenuOpen` | `lib/store.ts` | Whether mobile hamburger menu is open |
|
||||
| `currentContentEntry` | `lib/store.ts` | Currently displayed page entry data such as `translationKey`, `lang`, and `path` |
|
||||
| `previousPath` | `lib/store.ts` | Previous URL path (for conditional back buttons) |
|
||||
| `apiBaseOverride` | `lib/store.ts` | Override API base URL (used by admin module) |
|
||||
| `cookieConsentVisible` | `lib/store.ts` | Whether cookie consent banner is showing |
|
||||
| `currentLanguage` | `lib/i18n.ts` | Derived from `$location.path` — current language code |
|
||||
| `selectedLanguage` | `lib/i18n.ts` | Writable — synced with `currentLanguage` on navigation |
|
||||
| `activeRequests` | `lib/requestsStore.ts` | Number of in-flight API requests (drives `LoadingBar`) |
|
||||
|
||||
### Pattern: creating a new store
|
||||
|
||||
@@ -244,6 +263,16 @@ Located in `frontend/src/lib/api.ts`. Features:
|
||||
- **Mock interceptor** — when `__MOCK__` is `true`, routes requests to `frontend/mocking/*.json`
|
||||
- **Sentry integration** — span instrumentation (when enabled)
|
||||
|
||||
### Shared browser/SSR transport
|
||||
|
||||
The project intentionally shares the low-level API transport between browser and SSR via `api/hooks/lib/ssr`.
|
||||
|
||||
- In the browser, it eventually becomes `fetch(...)`.
|
||||
- In SSR, `apiRequest(...)` delegates to `context.ssrRequest(...)`.
|
||||
- GET responses reached during SSR are written into `window.__SSR_CACHE__` for hydration.
|
||||
|
||||
This is why SSR can preload both content and navigation without building a separate frontend-only data layer.
|
||||
|
||||
### Usage patterns
|
||||
|
||||
```typescript
|
||||
@@ -358,3 +387,5 @@ Return { data, count, buildTime }
|
||||
- **`_id` not `id` for filters** — API filters use MongoDB's `_id`, but response objects may have both `id` and `_id`.
|
||||
- **`$location` strips trailing slashes** — `/about/` becomes `/about` (except root `/`).
|
||||
- **Content cache is 1 hour** — `getCachedEntries` caches in memory for 1h. For admin previews, use `getDBEntries` (uncached).
|
||||
- **`$effect` alone is not SSR** — server-side rendering must trigger the same data path explicitly outside browser-only reactive effects.
|
||||
- **A rendered shell is not enough** — always verify that SSR HTML actually contains page-critical content and navigation.
|
||||
|
||||
Reference in New Issue
Block a user