AppView in a box as a Vite plugin thing
hatk.dev
1---
2title: Project Structure
3description: Understand the files and directories in a hatk project.
4---
5
6After creating a project with `vp create github:hatk-dev/hatk-template-starter`, your project looks like this:
7
8```
9my-app/
10├── app/ # SvelteKit frontend
11│ ├── app.html # HTML shell
12│ ├── app.css # Global styles
13│ ├── lib/ # Shared utilities
14│ └── routes/ # SvelteKit routes
15│ ├── +layout.svelte # Root layout
16│ ├── +layout.server.ts # Server-side layout data
17│ ├── +page.svelte # Home page
18│ └── oauth/callback/
19│ └── +page.svelte # OAuth redirect target
20├── server/ # Backend logic
21│ ├── recent.ts # Feed generator
22│ ├── get-profile.ts # XRPC query handler
23│ └── on-login.ts # Lifecycle hook
24├── lexicons/ # AT Protocol schemas
25│ ├── xyz/statusphere/
26│ │ ├── status.json # Custom record type
27│ │ └── getProfile.json # Custom query endpoint
28│ └── app/bsky/actor/
29│ └── profile.json # Bluesky profile (to index)
30├── seeds/
31│ └── seed.ts # Test fixture data
32├── test/
33│ ├── feeds/ # Feed unit tests
34│ ├── xrpc/ # XRPC handler tests
35│ ├── browser/ # Playwright browser tests
36│ └── fixtures/ # Test data (YAML files)
37├── db/
38│ └── schema.sql # Custom SQL migrations
39├── hatk.config.ts # Project configuration
40├── hatk.generated.ts # Generated types (server)
41├── hatk.generated.client.ts # Generated types (client)
42├── vite.config.ts # Vite + SvelteKit config
43├── svelte.config.js # SvelteKit adapter config
44├── docker-compose.yml # Local PDS for development
45├── Dockerfile # Production container build
46├── tsconfig.json # TypeScript config (app)
47└── tsconfig.server.json # TypeScript config (server)
48```
49
50---
51
52## `app/` -- SvelteKit frontend
53
54The `app/` directory is a standard SvelteKit application. Routes live in `app/routes/`, shared code goes in `app/lib/`. The `svelte.config.js` maps `app/` as the SvelteKit source directory (instead of the default `src/`).
55
56Auth helpers for login, logout, and reading the current viewer are imported from `$hatk/client`. Data fetching uses `callXrpc()` from the same import to call your backend's typed endpoints.
57
58See the [Frontend section](/frontend/setup) for details on routing, data loading, and mutations.
59
60## `server/` -- backend logic
61
62The `server/` directory contains all your backend code. hatk auto-discovers files in this directory and registers them based on their exports:
63
64- **Feeds** -- files that export `defineFeed()` become feed generators, queryable via `dev.hatk.getFeed`
65- **XRPC handlers** -- files that export `defineQuery()` or `defineProcedure()` become typed API endpoints
66- **Hooks** -- files named `on-login.ts` fire after OAuth authentication
67- **OG images** -- files in `server/og/` generate dynamic OpenGraph images via satori
68- **Setup scripts** -- files in `server/setup/` run at boot time for custom migrations or data imports
69- **Labels** -- files in `server/labels/` define content moderation rules
70
71Files prefixed with `_` (like `_helpers.ts`) are ignored by auto-discovery, so use that convention for shared utilities.
72
73See the guides for [Feeds](/guides/feeds), [XRPC Handlers](/guides/xrpc-handlers), [Hooks](/guides/hooks), [OpenGraph](/guides/opengraph), and [Labels](/guides/labels).
74
75## `lexicons/` -- AT Protocol schemas
76
77Lexicons are JSON schemas that define your data model for the AT Protocol. They describe records (data types stored in user repositories), queries (GET endpoints), and procedures (POST endpoints).
78
79```
80lexicons/
81├── xyz/statusphere/
82│ ├── status.json # Record: a status emoji
83│ └── getProfile.json # Query: get a user's profile
84└── app/bsky/actor/
85 └── profile.json # Bluesky's profile record (to index)
86```
87
88Lexicons drive two things automatically:
891. **Database tables** -- hatk creates SQLite tables for each record type
902. **TypeScript types** -- `hatk generate types` produces typed helpers in `hatk.generated.ts`
91
92Organized by reverse-DNS namespace (e.g., `xyz/statusphere/status.json` for the `xyz.statusphere.status` collection).
93
94## `seeds/` -- test fixture data
95
96The `seeds/seed.ts` file creates test accounts and records against the local PDS during development. It runs automatically when you `npm run dev`, or manually with `hatk seed`.
97
98Seeds use the AT Protocol API to create real data -- accounts, records, follows -- so your app has something to display during development without connecting to the live network.
99
100See the [Seeds guide](/guides/seeds).
101
102## `test/` -- tests
103
104Tests are organized by type:
105
106| Directory | Purpose | Runner |
107| ---------------- | ------------------------------ | ---------- |
108| `test/feeds/` | Feed generator unit tests | Vitest |
109| `test/xrpc/` | XRPC handler tests | Vitest |
110| `test/browser/` | End-to-end browser tests | Playwright |
111| `test/fixtures/` | Shared YAML test data | -- |
112
113Run tests with `npm run test` (unit/integration) or `npm run test:browser` (Playwright).
114
115## `hatk.config.ts` -- configuration
116
117The main configuration file. Controls the relay connection, database path, backfill settings, OAuth, and more. Uses `defineConfig()` for type safety.
118
119See the [Configuration page](/getting-started/configuration) for all options.
120
121## `hatk.generated.ts` / `hatk.generated.client.ts`
122
123Auto-generated TypeScript derived from your lexicon schemas. Do not edit these files directly.
124
125- **`hatk.generated.ts`** -- server-side types and helpers: `defineFeed()`, `defineQuery()`, `defineProcedure()`, `seed()`, typed record interfaces, and view types
126- **`hatk.generated.client.ts`** -- client-safe subset: `callXrpc()` for typed API calls, `login()`/`logout()`/`parseViewer()` for auth, plus re-exported types
127
128Regenerate both with:
129
130```bash
131npx hatk generate types
132```
133
134## `vite.config.ts` / `svelte.config.js`
135
136- **`vite.config.ts`** -- loads the `hatk()` Vite plugin (which proxies API routes to the hatk backend during development) and the `sveltekit()` plugin. Also configures test includes/excludes.
137- **`svelte.config.js`** -- sets `app/` as the SvelteKit source directory and configures the `$hatk` and `$hatk/client` import aliases that point to the generated files.
138
139## `db/schema.sql`
140
141Auto-generated database reference schema. This file is written by hatk on startup and shows the current table structure.
142
143## `docker-compose.yml` / `Dockerfile`
144
145- **`docker-compose.yml`** -- runs a local PDS and PLC directory for development. Started automatically by `npm run dev`.
146- **`Dockerfile`** -- production container build for deployment.
147
148## Runtime files
149
150The `data/` directory is created at runtime and contains the SQLite database (`hatk.db`). It is gitignored by default.
151
152```
153data/
154└── hatk.db
155```