Developer Guide
Local development, locating the correct source boundary, verification, and documentation updates.
Setup
git clone --recurse-submodules https://github.com/tqmane/vyline.git
cd vyline
bun install --frozen-lockfile
bun run typecheck
bun run lint
bun test
bun run build
Use Bun 1.4 or later. The workspace includes Vyline/packages/*, the Desktop app, Backend, and related packages; Protocol, Plugin, and Themes are Git submodules.
Development servers
bun run dev
# backend only: bun run dev:backend
# frontend only: bun run dev:frontend
dev:backend restarts Vyline/backend/src/index.ts through Bun watch, while dev:frontend starts the Vite development server. Production builds compile the Frontend to static assets and serve them from the Bun/Hono Backend process.
Where to make a change
| Area | Start here |
|---|---|
| Web UI | Vyline/apps/desktop |
| HTTP API / DB / restore | Vyline/backend |
| LINE RPC / E2EE / login | Vyline/packages/protocol |
| Plugin contract | Vyline/packages/plugin + Backend plugin runtime |
| Theme preset | Vyline/packages/themes |
| Desktop LINE reverse research | tools |
Order for tracing a request
| Operation | Frontend | Backend | Protocol |
|---|---|---|---|
| Initial render | useLineData.ts → api.line.bootstrap | GET /line/:accountId/bootstrap → SQLite | Normally no RPC |
| New events | useVylineSync.ts / pollIncoming | event buffer / processFetchedOperations | base.talk.sync |
| Active-chat delta | pollMessagesDelta | /messages/:chatMid/delta | Remote fetch when required |
| Send | api/client.ts | api/line.ts → lineService.sendMessage | Talk / E2EE |
| Login | auth UI/client | clientManager | QR / Email / Token + E2EE ensure |
| Media | upload/download API | lineService / media storage | Talk metadata + object storage/E2EE |
When debugging, do not jump directly from the UI to Protocol. Trace the boundary in order: Frontend request → BFF route → service → session manager → Protocol.
Changing a Backend API
- Check the client contract in
Vyline/apps/desktop/src/api/client.ts. - Keep input validation, status codes, and HTTP serialization in
Vyline/backend/src/api/line.ts. - Put LINE/DB behavior in
service/lineService.tsor the appropriate service. - If the operation requires an account/session, reuse the existing queue, urgent, or send path in
line/clientManager.ts. - If persistent state changes, verify storage, restore, and backup behavior together.
- Add route/service tests and keep Frontend types aligned with the actual response.
The current boundary keeps substantial business logic out of api/line.ts. HTTP-independent behavior stays in services so the same operation can be reused by another endpoint or consumer.
Changing Protocol
For an RPC addition or change, first inspect the existing mapping in Vyline/packages/protocol/src/dictionary/rpcMap.ts, then follow Desktop evidence → Protocol stack → domain facade → Backend service/BFF.
rpcMap.ts
canonicalName / desktopEvidence / path
↓
stack API / Thrift types
↓
domain API
↓
backend lineService
↓
api/line.ts
↓
frontend api/client.ts
For regressions caused by Desktop updates, use bun run vyline:delta or bun run vyline:find-native -- <name> to inspect the current implementation. A feature entry in modules.map.ts narrows the related binary, search strings, and analysis documents.
Changing storage
Chat runtime persistence uses SQLite. chatStoreSqlite.ts manages WAL mode, schema version, chats/messages/message_sync/local_read, and related state. Vyline does not hydrate the entire chat history into memory on startup.
- Check the existing schema and how
PRAGMA user_versionis handled. - Make forward migrations that preserve existing databases.
- Validate restore/import on a staging database or copy so a failure cannot partially mutate the original DB.
- For Docker, decide whether the data belongs under
/app/dataor/app/storage. - Check backup quota, media sidecars, and what cache deletion is supposed to mean.
Do not treat cache and persistent state as equivalent. Regenerable CDN/icon caches have different deletion semantics from sessions, chat databases, saved media, and backups.
Changing Plugin / Theme
The Plugin contract lives in the @vyline/plugin-sdk submodule; execution and per-account enable state live in Backend pluginRuntime.ts/pluginManager.ts. Plugin activate/deactivate hooks and event handlers are isolated so an extension failure does not take down the main process.
Adding a permission string to a manifest does not create a capability. Verify the SDK type, the methods actually exposed by Backend context, and permission handling in the manager together. For themes, use the VyTheme contract and preset tokens in Vyline/packages/themes as the source of truth.
Verification levels
bun run typecheck
bun run lint
bun test
bun run build
Passing these four checks does not prove a real LINE session or Docker deployment. Add verification in proportion to the change: local Backend API, browser UI, Docker image, then a real session when the change requires it.
Updating the Docs site
web/ is hand-maintained static HTML/CSS/JavaScript. Edit the target web/docs/<page>/index.html directly. Shared styling lives in web/assets/vyline.css, while Docs search, theme, table-of-contents, and code-copy behavior lives in web/assets/docs.js.
Do not generate the Web Docs from a script. Update only the pages affected by an implementation change after rereading the current code and related documentation, then verify the result through a local HTTP server.
README
README.src.md is the editable README source. Its Japanese/English output uses a separate README pipeline; after changing it, run bun run docs:readme. The Web Docs remain hand-edited HTML and are not generated by that command.