A production-oriented TypeScript monorepo for a Convex-backed bookmark sync product:
apps/web: Next.js 16 App Router dashboardapps/extension: Vite + React 19 browser extensionconvex: Convex backend and Convex Auth configurationpackages/ui: shared presentational componentspackages/convex: shared Convex client helpers, auth session manager, and bookmark helperspackages/utils: bookmark normalization, tree conversion, and sync utilitiespackages/config: shared Biome, TypeScript, and Tailwind v4 config assets
pnpmworkspacesturbo- strict TypeScript
- Biome
- Tailwind CSS v4
- Convex
- Convex Auth password provider
- Node.js 22+
- pnpm 10+
- A Convex account and deployment for full local backend execution
Copy .env.example to .env.local and fill in:
NEXT_PUBLIC_CONVEX_URLCONVEX_DEPLOYMENTCONVEX_SITE_URLJWT_PRIVATE_KEYVITE_CONVEX_URL
Notes:
VITE_CONVEX_URLis optional if it matchesNEXT_PUBLIC_CONVEX_URL.JWT_PRIVATE_KEYmust be an RSA private key for Convex Auth token signing.apps/webloads the workspace root.env.local, so local Convex values do not need to be duplicated insideapps/web.- If
convex devwritesCONVEX_URLinto.env.local, the Next app reuses it automatically asNEXT_PUBLIC_CONVEX_URLduring local development.
pnpm installStart the full local workflow:
pnpm devThat runs:
convex devnext dev- extension watch build for Chromium
Important:
convex devis the step that configures the local Convex project ifCONVEX_DEPLOYMENTis not already valid.- This repository includes committed
convex/_generated/*files so the TypeScript packages can build before a deployment is configured. - Once your Convex deployment is configured,
pnpm run codegenuses the real Convex generator.
pnpm build
pnpm lint
pnpm formatThe web app lives in apps/web and uses:
ConvexAuthNextjsServerProvider- Next proxy middleware for protected routes
- Convex reactive queries for the dashboard
Routes:
//login/signup/dashboard
The dashboard supports:
- real-time tree view
- search
- create bookmark
- create folder
- rename
- move
- soft delete
- logout
The extension lives in apps/extension and ships two builds:
apps/extension/dist/chromiumapps/extension/dist/firefox
Architecture:
src/background: sync coordinator and bookmark event listenerssrc/popup: popup UIsrc/lib: browser wrappers, storage, roots, env, and message types
Chrome / Edge:
- Run
pnpm --filter @bookmark-sync/extension build:chromium - Open the extensions page
- Enable developer mode
- Load unpacked from
apps/extension/dist/chromium
Firefox:
- Run
pnpm --filter @bookmark-sync/extension build:firefox - Open
about:debugging#/runtime/this-firefox - Load temporary add-on from
apps/extension/dist/firefox/manifest.json
- Chromium uses
background.service_worker - Firefox uses
background.scriptswith MV3browser_specific_settings - Bookmark root handling is normalized into logical roots so native top-level folder differences do not leak into Convex
Convex Auth is the only auth system.
The repository uses the password provider with two execution models:
- Web:
- Next proxy route handling via Convex Auth Next.js integration
- session persisted via the web integration’s cookie flow
- Extension:
- auth actions executed directly against Convex Auth
- access token and refresh token stored in
chrome.storage.local/browser.storage.local - session restored on popup and background startup without relying on cookies
Both clients authenticate against the same Convex Auth backend and resolve to the same Convex user identity.
Convex is the source of truth.
Schema highlights:
bookmarkstable- soft delete with
deleted: true updatedAtfor LWW conflict resolution- logical root folders persisted in Convex with
rootKey
Conflict policy:
- last write wins by
updatedAt - equal timestamps resolve in favor of server state
- first attach on a browser with existing local and remote data uses a server-safe merge
Sync behavior:
- initial local upload when remote is empty
- remote subscription in the extension background worker
- debounced local bookmark event handling
- local browser ID to Convex ID mapping stored only in extension storage
apps/
extension/
web/
packages/
config/
convex/
ui/
utils/
convex/
- There are no tests and no CI/CD in this repository by design.
- The root
pnpm buildcommand falls back to the committed Convex generated files when a deployment is not yet configured locally.