# webavatar-template The SvelteKit application template webavatar client projects branch from. It composes `@webavatar/webavatar-core` and `@webavatar/webavatar-humanoid` with project-owned persona, tools, and deployment configuration — see the monorepo root's [docs/ARCHITECTURE.md](../../docs/ARCHITECTURE.md) for the full architecture map, and [AGENTS.md](../../AGENTS.md) for project conventions. `docs/` holds a deep-dive per subsystem. ## Getting started (inside this monorepo) ```sh npm install # from the monorepo root cp apps/template/.env.example apps/template/.env # fill in OPENAI_API_KEY and REALTIME_TOKEN_SECRET in apps/template/.env npm run dev # from the monorepo root — builds the packages, then watches them alongside this app ``` Open [`/demo/realtime`](http://localhost:5173/demo/realtime) for the realtime session reference wiring, or [`/demo/humanoid`](http://localhost:5173/demo/humanoid) for the humanoid avatar-state demo (works offline via `REALTIME_PROVIDER=mock`, no API key needed). Running `npm run dev` from _this_ directory alone starts the app but does **not** hot-reload package source changes — see [docs/REALTIME_SESSION.md](../../docs/REALTIME_SESSION.md)'s "Dev-mode reload behavior" for why, and use the root `npm run dev` instead when iterating on `packages/core` or `packages/humanoid`. ## Scripts - `npm run dev` / `npm run build` / `npm run preview` — standard SvelteKit commands. - `npm run check` — type-check. `npm run lint` / `npm run format` — prettier + eslint. - `npm run test:unit` — vitest. `npm run test:e2e` — Playwright. - `npm start` — run the production build via `server.js` (the persistent Node process the realtime WebSocket relay requires — see [docs/ARCHITECTURE.md](../../docs/ARCHITECTURE.md)). ## Documentation | Subsystem | Doc | | --------------------------------------------------------------------- | ---------------------------------------------------------- | | Architecture overview and module layering | [docs/ARCHITECTURE.md](../../docs/ARCHITECTURE.md) | | Realtime session management | [docs/REALTIME_SESSION.md](../../docs/REALTIME_SESSION.md) | | Tool calling (server- and client-executed) | [docs/TOOLS.md](../../docs/TOOLS.md) | | Analytics recording | [docs/ANALYTICS.md](../../docs/ANALYTICS.md) | | Configuration (env vars, persona) | [docs/CONFIGURATION.md](../../docs/CONFIGURATION.md) | | `@webavatar/webavatar-humanoid` (avatar-state, animation composition) | [docs/HUMANOID.md](../../docs/HUMANOID.md) | ## Starting a client project from this template The packages (`@webavatar/webavatar-core`, `@webavatar/webavatar-humanoid`) are what a client project upgrades; this template is what it starts from. A project installs versions of the packages — it does not merge package source from this repository. 1. Copy this directory (`apps/template`) into a new repository. Do not copy the monorepo root, `packages/`, or the root lockfile. 2. The copied `package.json` becomes the project's own root manifest. It stays `"private": true`. Its `@webavatar/*` ranges no longer resolve to workspace links, so pin them to published versions. 3. Add the committed `.npmrc` scope mapping (`@webavatar:registry=...`), configure registry authentication, and run `npm install`. 4. Copy `.env.example` to `.env`, fill in the secrets, and run `npm run dev`. The demo routes stay dev-only gated and can be kept or deleted. 5. Project code goes under `src/lib/**/project`, exactly as in this template. 6. To upgrade, bump the package versions; a peer-range conflict between core and humanoid surfaces as an `npm install` error — that's the intended signal, not a bug. Changes to this template shell itself (`server.js`, `vite.config.ts`, routes, deployment files) don't arrive through package upgrades; a project applies them by hand. The composition-root factory (`createRealtimeRuntime`, from `@webavatar/webavatar-core/server`) is what keeps the shell thin enough that this stays rare — a change in how the relay is assembled ships inside a core release instead. **Current status:** steps 3 and 6 (installing from the registry, and the peer-range upgrade signal) require the private Gitea package registry, which isn't provisioned yet — see `docs/MONOREPO_MIGRATION_BRIEF.md`'s "Decisions required before handoff". Steps 1, 2, 4, and 5 work today; the packages themselves have been verified installable from packed tarballs in place of the registry (see the migration brief's verification requirements).