Skip to content

Commit e5b241c

Browse files
authored
Merge pull request #2947 from appwrite/chore-agent-files
2 parents 9c1a252 + 10857e0 commit e5b241c

2 files changed

Lines changed: 231 additions & 124 deletions

File tree

AGENTS.md

Lines changed: 229 additions & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -1,138 +1,243 @@
1-
# Appwrite Console - Copilot Instructions
1+
# Appwrite Console
2+
3+
SvelteKit web dashboard for Appwrite. Manages projects, databases, functions, auth, storage, messaging, and sites. Static SPA (no SSR) served behind Nginx at `/console`.
4+
5+
## Commands
6+
7+
All commands use **bun** (not pnpm/npm). Use `bun run <script>` consistently — `bun run build` is required to avoid invoking bun's built-in bundler.
8+
9+
| Command | Purpose |
10+
| ------------------------- | --------------------------------------------- |
11+
| `bun run dev` | Dev server (port 3000) |
12+
| `bun run build` | Production build (custom `build.js` via Vite) |
13+
| `bun run check` | `svelte-kit sync && svelte-check` |
14+
| `bun run format` | Prettier write + cache |
15+
| `bun run lint` | Prettier check + ESLint |
16+
| `bun run tests` | Unit + E2E |
17+
| `bun run test:unit` | Vitest (TZ=EST) |
18+
| `bun run test:unit-watch` | Vitest watch mode |
19+
| `bun run test:e2e` | Playwright |
20+
| `bun run clean` | Remove node_modules, .svelte-kit, reinstall |
21+
22+
**Always run before committing:** `bun run format && bun run check && bun run lint && bun run tests && bun run build`
23+
24+
## CI checks (`.github/workflows/tests.yml`)
25+
26+
`bun audit --audit-level high` -> `bun check` -> `bun lint` -> `bun test:unit` -> `bun run build`. Uses frozen lockfile.
27+
28+
## Stack
29+
30+
- **Framework:** SvelteKit 2 + Svelte 5, TypeScript (strict: false), `@sveltejs/adapter-static`
31+
- **Bundler:** Vite 7 (overridden to `rolldown-vite`)
32+
- **Design system:** `@appwrite.io/pink-svelte`, `@appwrite.io/pink-icons-svelte`
33+
- **UI primitives:** Melt UI (`@melt-ui/svelte` with preprocessor)
34+
- **API client:** `@appwrite.io/console` SDK (pinned to GitHub commit)
35+
- **Code editing:** CodeMirror 6
36+
- **Charts:** ECharts 5
37+
- **3D:** Three.js via Threlte
38+
- **Payments:** Stripe
39+
- **AI:** Vercel AI SDK (`@ai-sdk/svelte`)
40+
- **Testing:** Vitest + @testing-library/svelte (unit), Playwright (E2E)
41+
- **Error tracking:** Sentry (`@sentry/sveltekit`)
42+
- **Analytics:** Plausible + custom Growth endpoint
43+
44+
## Architecture
45+
46+
### Route structure (`src/routes/`)
47+
48+
SvelteKit file-based routing with layout groups:
49+
50+
- `(public)/` -- unauthenticated routes: `(guest)/` (login, register), auth (OAuth, magic URL), invite, recover, card, functions/sites deploy, hackathon, templates
51+
- `(console)/` -- authenticated console (projects, orgs, account, onboarding)
52+
- `(authenticated)/` -- post-login flows (MFA, Git authorization)
53+
54+
Dynamic segments: `project-[region]-[project]`, `organization-[organization]`
55+
56+
### Route file conventions
57+
58+
Each route can have:
59+
60+
- `+page.svelte` -- page component
61+
- `+page.ts` -- client-side load function
62+
- `+layout.svelte` / `+layout.ts` -- layout wrappers
63+
- `store.ts` -- route-scoped state
64+
- Feature components colocated alongside (e.g. `table.svelte`, `create.svelte`)
65+
66+
### Path aliases
67+
68+
| Alias | Path |
69+
| ----------- | ------------------------------------------------------------------------------- |
70+
| `$lib` | `src/lib` (SvelteKit built-in) |
71+
| `$routes` | `src/routes` |
72+
| `$themes` | `src/themes` |
73+
| `$database` | `src/routes/(console)/project-[region]-[project]/databases/database-[database]` |
74+
75+
### Library (`src/lib/`)
76+
77+
| Directory | Contents |
78+
| ----------------- | ------------------------------------------------------------------------------------------ |
79+
| `components/` | Feature components (billing, permissions, filters, etc.) -- barrel-exported via `index.ts` |
80+
| `elements/forms/` | Form inputs (text, email, phone, OTP, file, geometry, etc.) |
81+
| `elements/table/` | Table components |
82+
| `layout/` | Shell, Container, Wizard, Breadcrumbs, Navigation -- barrel-exported via `index.ts` |
83+
| `stores/` | Svelte stores for global state |
84+
| `helpers/` | Utilities (array, date, object, numbers, string, validation) |
85+
| `sdk/` | Custom SDK extensions (billing, usage, sources) |
86+
| `actions/` | Svelte actions and analytics tracking |
87+
| `charts/` | Chart visualization components -- barrel-exported via `index.ts` |
88+
| `commandCenter/` | Command palette |
89+
| `images/` | SVG assets (logos, illustrations, empty states) |
90+
| `data/` | Static data (testimonials) |
91+
| `profiles/` | CSS profiles and theming |
92+
| `mock/` | Mock data for development |
93+
94+
### Imports
95+
96+
Components use **barrel exports** -- always import from the directory `index.ts`:
97+
98+
```typescript
99+
import { Card, Modal, Steps } from '$lib/components';
100+
import { Shell, Container } from '$lib/layout';
101+
import { InputText, Button, Form } from '$lib/elements/forms';
102+
```
103+
104+
### Svelte 5 migration (in progress)
2105

3-
## Repository Overview
106+
~500 files still use legacy Svelte 4 syntax, ~240 migrated to runes. **When touching a file, migrate it to runes if practical.** Don't mix syntaxes within a single component.
4107

5-
Appwrite Console is the web-based GUI for the Appwrite backend-as-a-service platform. Single-page application built with
6-
**Svelte 5 + SvelteKit 2**, **TypeScript** (not strict mode), **Vite 7**, tested with **Vitest + Playwright**. Package
7-
manager/runtime: **Bun** (Node 20+ optional for tooling). ~1500 files with extensive component-based architecture.
108+
Legacy (Svelte 4):
8109

9-
## Critical Build & Test Commands
110+
```svelte
111+
<script lang="ts">
112+
export let items: Item[] = [];
113+
export let disabled = false;
114+
$: count = items.length;
115+
</script>
116+
```
10117

11-
### Setup (REQUIRED before any commands)
118+
Runes (Svelte 5 -- preferred for new and modified code):
12119

13-
1. **Install Bun**:
14-
- Linux & macOS: `curl -fsSL https://bun.sh/install | bash`
15-
- Windows: `powershell -c "irm bun.sh/install.ps1 | iex"`
16-
2. **Create .env**: `cp .env.example .env` (configure `PUBLIC_APPWRITE_ENDPOINT` and `PUBLIC_CONSOLE_MODE`)
17-
3. **Configure network access** (if using GitHub Actions or restricted environments):
18-
- Ensure firewall/proxy allows access to: `pkg.pr.new`, `pkg.vc`, `registry.npmjs.org`
19-
- These domains are required for dependencies: `@appwrite.io/console`, `@appwrite.io/pink-icons-svelte`,
20-
`@appwrite.io/pink-svelte`
21-
- In GitHub Actions: Ensure Bun is installed and registry access is configured
22-
- If network errors persist, check proxy settings: `npm config get proxy` and `npm config get https-proxy`
23-
4. **Install dependencies**: `bun install --frozen-lockfile` (if pkg.pr.new/pkg.vc fail due to network restrictions,
24-
installation may still succeed with cached versions)
120+
```svelte
121+
<script lang="ts">
122+
// $bindable() enables two-way binding so parent components can mutate items directly
123+
let { items = $bindable(), disabled = false }: Props = $props();
124+
let selected = $state<string | null>(null);
125+
const count = $derived(items.length);
126+
const filtered = $derived.by(() => items.filter((i) => i.active));
127+
128+
$effect(() => {
129+
console.log('selected changed:', selected);
130+
});
131+
</script>
132+
```
25133

26-
### Development Commands
134+
### SDK usage (`src/lib/stores/sdk.ts`)
27135

28-
**Standard workflow**: `check``lint``test``build` (before committing)
136+
Four client instances: `clientConsole` (console API), `scopedConsoleClient` (region-scoped console API, used by `forConsoleIn()`), `clientProject` (project API, admin mode), `clientRealtime` (realtime subscriptions). Region-aware endpoints with subdomain routing (fra., nyc., syd., sfo., sgp., tor.).
29137

30-
- `bun run check` - TypeScript/Svelte validation (~30-60s)
31-
- `bun run lint` - ESLint check (~10-20s)
32-
- `bun run format` - Auto-fix Prettier formatting
33-
- `bun run test` - Vitest unit tests with TZ=EST (~10-30s)
34-
- `bun run build` - Production build via build.js (~60-120s)
35-
- `bun run dev` - Dev server on port 3000
36-
- `bun run preview` - Preview build on port 4173
37-
- `bun run e2e` - Playwright tests (needs `bunx playwright install --with-deps chromium` first, ~120s+)
138+
```typescript
139+
import { sdk } from '$lib/stores/sdk';
38140

39-
**CI Pipeline** (`.github/workflows/tests.yml`): audit → install → check → lint → test → build
141+
// Console-level operations
142+
await sdk.forConsole.account.get();
40143

41-
## Project Structure
144+
// Region-scoped console operations
145+
await sdk.forConsoleIn(region).projects.get({ projectId });
42146

147+
// Project-level operations (admin mode)
148+
await sdk.forProject(region, projectId).tablesDB.listTables();
43149
```
44-
src/
45-
├── lib/ # Reusable logic ($lib alias)
46-
│ ├── components/ # Feature components (billing, domains, permissions, etc.)
47-
│ ├── elements/ # Basic UI elements
48-
│ ├── helpers/ # Utility functions (array, date, string, etc.)
49-
│ ├── stores/ # Svelte stores for state
50-
│ ├── sdk/ # Appwrite SDK wrappers
51-
│ └── constants.ts, flags.ts, system.ts
52-
├── routes/
53-
│ ├── (console)/ # Auth-required routes
54-
│ │ ├── organization-[organization]/
55-
│ │ └── project-[region]-[project]/ # databases, functions, messaging, storage
56-
│ └── (public)/ # Public routes (login, register, auth callbacks)
57-
├── themes/ # Theme definitions ($themes alias)
58-
└── app.html, hooks.{client,server}.ts, service-worker.ts
150+
151+
### Database types (feat-dedicated-db)
152+
153+
The databases feature unifies multiple database backends behind a polymorph API (`$database/(entity)/helpers/sdk.ts`):
154+
155+
| Type | Entity | Field | Record | Status |
156+
| ------------- | ---------- | --------- | -------- | ------------------------ |
157+
| `tablesdb` | table | column | row | Implemented |
158+
| `documentsdb` | collection | attribute | document | Implemented |
159+
| `vectorsdb` | -- | -- | -- | Not yet implemented |
160+
| `dedicateddb` | table | column | row | Cross-repo (cloud/edge) |
161+
162+
- `useDatabaseSdk()` returns a unified interface regardless of backing type
163+
- `useTerminology()` returns singular/plural names for the current database type
164+
165+
### Data loading
166+
167+
Load functions declare dependencies for cache invalidation via `depends()`:
168+
169+
```typescript
170+
export const load: LayoutLoad = async ({ depends, parent, params }) => {
171+
depends(Dependencies.DATABASE);
172+
return { database: await sdk.forProject(...).tablesDB.get(...) };
173+
};
59174
```
60175

61-
**SvelteKit conventions**: `+page.svelte` (component), `+page.ts` (data loader), `+layout.svelte` (wrapper),
62-
`+error.svelte` (errors). Groups like `(console)` organize routes without affecting URLs. Dynamic params: `[param]`.
63-
64-
## Key Configuration
65-
66-
**svelte.config.js**: Adapter = static SPA (fallback: index.html), base path `/console`, aliases: `$lib`, `$routes`,
67-
`$themes`
68-
**vite.config.ts**: Dev port 3000
69-
**tsconfig.json**: Extends `.svelte-kit/tsconfig.json`, **NOT strict mode** (`strict: false`)
70-
**eslint.config.js**: Flat config (ESLint 9+), many rules disabled (see TODOs)
71-
**.prettierrc**: 4 spaces, single quotes, 100 char width, no trailing commas
72-
73-
## Testing
74-
75-
**Unit (Bun test)**: Tests in `src/lib/helpers/*.test.ts`, run with `TZ=EST` (timezone matters). Setup mocks SvelteKit (
76-
`$app/*`) in `bun-test-setup.ts` via `bunfig.toml`.
77-
**E2E (Playwright)**: Tests in `e2e/journeys/*.spec.ts`, needs build+preview on port 4173, retries 3x, timeout 120s,
78-
Chromium only.
79-
80-
## Common Pitfalls
81-
82-
1. **Blank page in dev**: Disable ad blockers if seeing "Failed to fetch dynamically imported module" (known SvelteKit
83-
issue)
84-
2. **Network errors on install**:
85-
- pkg.pr.new/pkg.vc deps may fail due to firewall/proxy restrictions
86-
- Check access: `curl -I https://pkg.pr.new` and `curl -I https://pkg.vc`
87-
- Configure proxy if needed: `npm config set proxy http://proxy:port` and
88-
`npm config set https-proxy http://proxy:port`
89-
- GitHub Actions: Ensure runner has internet access and Bun is installed
90-
- Local dev: Often safe to continue with cached versions if network fails
91-
3. **OOM on build**: Set `NODE_OPTIONS=--max_old_space_size=8192` (like Dockerfile does)
92-
4. **Test failures**: Always use `bun run test` (sets TZ=EST), not `bun test` directly
93-
5. **TS errors not showing**: Run `bun run check` explicitly (dev server doesn't always surface them)
94-
6. **Format vs lint conflicts**: Run `bun run format` before `bun run lint`
95-
7. **E2E timeouts**: Wait 120s for preview server startup, tests auto-retry 3x
96-
8. **Stale build**: Clear `.svelte-kit` if changes not reflected: `rm -rf .svelte-kit && bun run build`
97-
98-
## Code Conventions
99-
100-
- Imports: Use `$lib`, `$routes`, `$themes` aliases
101-
- Components: PascalCase, in `src/lib/components/[feature]/`
102-
- Helpers: Pure functions in `src/lib/helpers/`
103-
- Types: Inline or `.d.ts`, not `.types.ts` files
104-
- Comments: Minimal, use for TODOs or complex logic
105-
- TypeScript: Not strict mode, `any` tolerated
106-
107-
## Workflow
108-
109-
1. Run Appwrite backend locally (see [docs](https://appwrite.io/docs/advanced/self-hosting))
110-
2. Configure `.env` with backend endpoint
111-
3. `bun install --frozen-lockfile`
112-
4. `bun run dev` (hot reload on port 3000)
113-
5. Before commit: `bun run check && bun run format && bun run lint && bun run test && bun run build`
114-
6. **Take screenshots**: For any UI changes, capture screenshots and include them in the PR description or comments
115-
before finalizing
116-
117-
## Required Pre-Completion Checklist
118-
119-
**CRITICAL**: Before finishing any work or marking a task complete, agents MUST run the following commands in order and
120-
ensure all pass:
121-
122-
1. **`bun run format`** - Auto-fix all formatting issues
123-
2. **`bun run check`** - Verify TypeScript/Svelte types (must show 0 errors, 0 warnings)
124-
3. **`bun run lint`** - Check code style (ignore pre-existing issues in files you didn't modify)
125-
4. **`bun run test`** - Run all unit tests (all tests must pass)
126-
5. **`bun run build`** - Ensure production build succeeds
127-
128-
If any command fails:
129-
130-
- **Format/Lint**: Run `bun run format` to auto-fix, then re-check
131-
- **Type errors**: Fix all TypeScript errors in files you modified
132-
- **Test failures**: Fix failing tests or ensure failures are unrelated to your changes
133-
- **Build failures**: Debug and resolve build issues before proceeding
134-
135-
**Never skip these checks** - they are mandatory quality gates before any work is considered complete.
136-
137-
**Trust these instructions** - only search if incomplete/incorrect. See CONTRIBUTING.md for PR conventions. Use
138-
`--frozen-lockfile` always. Docker builds: multi-stage, final image is nginx serving static files from `/console` path.
176+
Invalidate with `await invalidate(Dependencies.DATABASE)` after mutations. The `Dependencies` enum in `src/lib/constants.ts` defines 66+ keys for fine-grained cache invalidation (e.g. `DATABASES`, `TABLES`, `FUNCTIONS`, `USERS`, `DEPLOYMENTS`).
177+
178+
### State management
179+
180+
Stores in `src/lib/stores/` -- writable, derived, and "conservative" (selective update via `createConservative()` from `$lib/helpers/stores`) patterns. Key stores: `app`, `user`, `organization`, `projects`, `billing`, `wizard`, `notifications`, `sdk`.
181+
182+
### Wizard pattern (`$lib/stores/wizard`)
183+
184+
Modal wizard flow: `wizard.start(Component, media?, step?, props?)` to open, `wizard.hide()` to close. Methods: `setInterceptor(callback)` for async pre-step validation, `setNextDisabled(bool)` for flow control, `setStep(n)` / `updateStep(cb)` for navigation, `showCover(Component)` for overlays.
185+
186+
### Notifications (`$lib/stores/notifications`)
187+
188+
```typescript
189+
import { addNotification } from '$lib/stores/notifications';
190+
addNotification({ type: 'error', message: error.message });
191+
```
192+
193+
Types: `'success' | 'error' | 'info' | 'warning'`. Auto-dismisses after 6s. Max 5 visible.
194+
195+
### Analytics (`$lib/actions/analytics`)
196+
197+
Plausible + custom Growth endpoint. Track events via `trackEvent(Click.* | Submit.*, data)` and errors via `trackError(exception, Submit.*)`. Respects `navigator.doNotTrack`.
198+
199+
### Theming and modes
200+
201+
Four theme variants in `src/themes/`: `light`, `dark`, `light-cloud`, `dark-cloud`. Resolved based on `isCloud` flag and user preference. Two modes (`src/lib/system.ts`): `cloud` and `self-hosted`, set via `PUBLIC_CONSOLE_MODE` env var. Gate features using `isCloud` (for cloud-only) or `isSelfHosted` (for self-hosted-only).
202+
203+
## Code style
204+
205+
- **Formatter:** Prettier -- 4 spaces, single quotes, no trailing commas, 100 char width, bracket same line
206+
- **Prefer Svelte 5 runes** in new and modified code (`$props()`, `$state()`, `$derived()`, `$effect()`)
207+
- Types from `@appwrite.io/console` SDK (`Models`, `Query`, enums) -- don't redefine what the SDK provides
208+
- Error handling: try/catch with `addNotification()` for user-facing errors, `trackError()` for analytics
209+
- Queries use the SDK's `Query` builder: `Query.equal()`, `Query.limit()`, `Query.offset()`, etc.
210+
- Mark tech debt with `@todo` annotations, never `@fixme`
211+
- Don't add new dependencies without consulting the team
212+
213+
## Environment variables
214+
215+
Set via `.env` (copy `.env.example`). All prefixed with `PUBLIC_` for SvelteKit:
216+
217+
| Variable | Default | Purpose |
218+
| ------------------------------------ | --------------------- | ------------------------------ |
219+
| `PUBLIC_CONSOLE_MODE` | `self-hosted` | `cloud` or `self-hosted` |
220+
| `PUBLIC_APPWRITE_ENDPOINT` | `http://localhost/v1` | API endpoint |
221+
| `PUBLIC_APPWRITE_MULTI_REGION` | `false` | Multi-region support |
222+
| `PUBLIC_STRIPE_KEY` | -- | Stripe public key (cloud only) |
223+
| `PUBLIC_GROWTH_ENDPOINT` | -- | Analytics endpoint |
224+
| `PUBLIC_CONSOLE_FEATURE_FLAGS` | -- | Feature flags |
225+
| `PUBLIC_CONSOLE_EMAIL_VERIFICATION` | `false` | Require email verification |
226+
| `PUBLIC_CONSOLE_MOCK_AI_SUGGESTIONS` | `true` | Mock AI in dev |
227+
228+
## Common pitfalls
229+
230+
- **Blank page in dev:** Disable ad blockers if seeing "Failed to fetch dynamically imported module"
231+
- **OOM on build:** Set `NODE_OPTIONS=--max_old_space_size=8192`
232+
- **Test failures:** Always use `bun run tests` (runs test:unit with TZ=EST, plus test:e2e), not `bun test` directly
233+
- **TS errors not showing:** Run `bun run check` explicitly (dev server doesn't always surface them)
234+
- **Format vs lint conflicts:** Run `bun run format` before `bun run lint`
235+
- **Stale build:** Clear `.svelte-kit` if changes not reflected: `rm -rf .svelte-kit && bun run build`
236+
237+
## Branch naming
238+
239+
`TYPE-ISSUE_ID-DESCRIPTION` (e.g. `feat-548-add-backup-ui`). Types: feat, fix, doc, cicd, refactor.
240+
241+
## Cross-repo context
242+
243+
The `feat-dedicated-db` feature spans cloud, edge, and console. When modifying API contracts or response models, check the other repos for breaking changes.

CLAUDE.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
<!-- Loads AGENTS.md into AI assistant context -->
2+
@AGENTS.md

0 commit comments

Comments
 (0)