docs(copilot): add Copilot instructions for The Collective Hub
- Add comprehensive project overview and core philosophy - Document file structure reference for the codebase - Create key files reference table for task-specific guidance - Include multi-tenant guidelines and site resolution flow
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
---
|
||||
description: 'Use when writing or editing .svelte.ts reactive state modules. Enforces Svelte 5 runes-based shared state patterns and forbids svelte/store primitives.'
|
||||
applyTo: '**/*.svelte.ts'
|
||||
---
|
||||
|
||||
# Svelte Reactive Module Rules (`.svelte.ts`)
|
||||
|
||||
Use `.svelte.ts` files for **global or cross-tree shared reactive state** that needs to be accessed outside of a component hierarchy. For state scoped to a component subtree, prefer `setContext` / `getContext` instead.
|
||||
|
||||
## Module-Scope State
|
||||
|
||||
Declare `$state` at module scope to create a reactive singleton. Export a factory function or a plain object with getter/setter methods — not the raw `$state` variable, which would allow callers to reassign it.
|
||||
|
||||
```ts
|
||||
// ✅ src/lib/state/services.svelte.ts
|
||||
const _state = $state({ list: [] as Service[], loading: false });
|
||||
|
||||
export const servicesStore = {
|
||||
get list() {
|
||||
return _state.list;
|
||||
},
|
||||
get loading() {
|
||||
return _state.loading;
|
||||
},
|
||||
set(services: Service[]) {
|
||||
_state.list = services;
|
||||
},
|
||||
setLoading(v: boolean) {
|
||||
_state.loading = v;
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
```ts
|
||||
// ❌ — callers can do `list = []` bypassing reactivity
|
||||
export let list = $state<Service[]>([]);
|
||||
```
|
||||
|
||||
## Derived State
|
||||
|
||||
Use `$derived` at module scope for computed values:
|
||||
|
||||
```ts
|
||||
const _state = $state({ list: [] as Service[], search: '' });
|
||||
|
||||
export const filtered = $derived(_state.list.filter((s) => s.name.includes(_state.search)));
|
||||
```
|
||||
|
||||
## Never Use svelte/store
|
||||
|
||||
Do not use `writable`, `readable`, or `derived` from `svelte/store` in new code.
|
||||
|
||||
| Instead of | Use |
|
||||
| ------------------------ | ---------------------------------------------- |
|
||||
| `writable(value)` | `$state(value)` in a `.svelte.ts` module |
|
||||
| `derived(store, fn)` | `$derived(fn)` in a `.svelte.ts` module |
|
||||
| `readable(value, start)` | `$state` + a setup function in the module body |
|
||||
|
||||
## When to Use `.svelte.ts` vs `setContext/getContext`
|
||||
|
||||
| Scenario | Pattern |
|
||||
| --------------------------------------------------- | -------------------------------------------------------------------- |
|
||||
| State needed across unrelated component trees | `.svelte.ts` module singleton |
|
||||
| State scoped to one subtree (e.g. a form, a widget) | `setContext` in parent, `getContext` in children |
|
||||
| State that needs SSR / per-request isolation | `setContext` in `+layout.svelte` (never module singletons on server) |
|
||||
|
||||
> **Warning**: Module singletons are shared across all users in SSR. Only use `.svelte.ts` singletons for state that is client-side only (e.g. UI state, client-cached data). For per-user server state, always use context.
|
||||
Reference in New Issue
Block a user