`
+- **Reactive class**: Define in `.svelte.ts` files for reusability
-### Convex の Import について
+## Controllers (`.svelte.ts`)
+
+Controllers must be instantiated **synchronously at script top-level**, so `$effect`/`$derived` work in constructors.
+
+**Reactive props pattern:**
```ts
-import { api, type Id } from "@apps/convex";
+// ✅ Pass getter function, fine-grained reactivity
+class MyController {
+ organizationId: string;
+ constructor(organizationId: () => string) {
+ this.organizationId = $derived(organizationId());
+ }
+}
+// Usage: new MyController(() => organizationId)
-// use api and type Id ...
+// ❌ Don't pass raw values (not reactive)
+class MyController {
+ organizationId: string;
+ constructor(organizationId: string) {
+ this.organizationId = organizationId; // Won't update!
+ }
+}
+```
+
+```svelte
+
```
-### 注意点: convex-svelte の `useQuery` について
+**Hooks in controllers:** `useWebSocket`, `useQuery`, etc. can be called in constructors since they run at component init time.
+for example,
-`useQuery` に渡す引数は、関数の形式で渡してください。そうでないと、期待しない動作を引き起こす可能性があります。
+```ts
+// foo.controller.svelte.ts
+class FooController {
+ constructor() {
+ useWebSocket("message:foo", (ev) => {
+ console.log("event received:", ev);
+ });
+ }
+}
+```
+
+## Vocaburaly
+
+[Hooks]
+we derive the words "hooks" from react.
+hooks in svelte can only be called at script initialization time.
+
+```ts
+// for "constant" variable you may use bare variables, but otherwise use getter-style passing, just like in controllers.
+function useHook(defaultVal: number, plus: () => number) {
+ // inside hooks you can call effects
+ $effect(() => {
+ console.log("effects");
+ });
+
+ // create reactive variables
+ let reactive = $state(defaultVal);
+ let derived = $derived(reactive * 2 + plus());
+
+ // and return controller-like objects
+ // ALWAYS use getters and setters for returning reactive variables, otherwise it won't be reactive.
+ return {
+ get reactive() {
+ return reactive;
+ },
+ set reactive(newVal) {
+ reactive = newVal;
+ }
+ get derived() {
+ return derived;
+ }
+ }
+}
+```
```svelte
+
+{foo.reactive} * 2 + {plus} = {foo.derived}
```
-### Mutations with useMutation
+
-Since `convex-svelte` doesn't export `useMutation`, we have a custom utility at `src/lib/useMutation.svelte.ts`:
+
-```typescript
-import { useMutation } from "@/lib/useMutation.svelte.ts";
+## Eden Treaty (Data Fetching)
-const createOrganization = useMutation(api.organizations.create);
+```ts
+import { treaty } from "@elysiajs/eden";
+import type { App } from "@apps/server";
+
+const client = treaty("http://localhost:8080");
-// Use like this
-await createOrganization.run({ name: "New Org", description: "..." });
-// which exposes these properties
-createOrganization.processing; // boolean, use for button disabled state / loading spinners
-createOrganization.error; // string | null, use for error messages
+await client.products.get(); // GET
+await client.products["123"].get(); // Dynamic param
+await client.products.get({ query: { category: "foo" } }); // Query
+await client.products.post({ name: "bar", price: 100 }); // POST
```
-## Framework - Svelte
+
-### Syntax
+
-Never use logacy svelte syntax. This project uses Svelte 5 runes mode.
+## Code Quality
-- ❌ FORBIDDEN: `$: reactiveVar = ...` (reactive statements)
-- ❌ FORBIDDEN: `let count = 0` for reactive state
-- ✅ REQUIRED: `let count = $state(0)` for reactive state
-- ✅ REQUIRED: `$effect(() => { ... })` for side effects
-- ✅ REQUIRED: `const sum = $derived(a + b);` for derived variables
-- ✅ REQUIRED: `const sum = $derived.by(() => { if (a + b < 0) return 0; return a + b; );` for derived variables which needs a block.
+- **FILE LENGTH**: 30-50 lines recommended, be warned over 100, 200 AT MAX
+- **TIDY**: Run `bun tidy` after writing code (auto-fix + check)
+- **DOCUMENTATION**: Document behavior, not implementation
-### Svelte Capabilities
+## Svelte Rules
-- clsx: Svelte has clsx builtin to its class. `{text}
`
+- **NAMING**: Snippets use camelCase (not PascalCase)
+- **ALIAS**: Use `@/` for imports
+- **STYLING**: TailwindCSS + DaisyUI only. No `