Profile & unified modules
User profile, unified module system, websites, and public profile APIs.
Overview
The on-chain profile UI lives under src/app/[locale]/(default)/profile/page.tsx (large client surface). Persistence goes through src/services/profile.ts and src/models/* unified-module tables. Public read-only views use /api/public/profile/*.
Key API routes (selection)
| Route | Role |
|---|---|
GET/PUT /api/profile | Current user profile load/save (getUserUuid → profile service) |
GET /api/profile/public | Public profile payload for sharing |
GET/POST /api/modules/*, /api/modules/websites/* | Module types, websites CRUD, reorder, batch |
GET /api/public/profile, /api/public/profile/[identifier] | Public profile by identifier |
POST /api/profile/track-view | View analytics for public profile |
Data flow
- Session →
getUserUuid/ NextAuth session in API routes. - Services (
profile,public-profile, unified-modules services) validate input, orchestrate models. - Drizzle models in
src/models/*persistusers, module types, websites, relations.
Key source paths
- UI:
src/components/profile/*,src/components/ui/quick-add-system.tsx(lazy). - Types:
src/types/profile.d.ts,src/types/unified-modules.ts. - DB:
src/db/schema.ts(websites, module types, etc.).
Doc gap note
Profile page is very large; this file is a map. Deep UI state names deserve sub-pages if you split components further.
Dependencies
Environment
DATABASE_URL— required for all profile/module persistence.NEXTAUTH_URL(or your deployment’s app URL) — some routes call internal APIs with an absolute base (e.g. favicon extraction).
Database (src/db/schema.ts)
users,user_profilesuser_module_configs,user_module_website_relations,user_custom_module_types,user_custom_websitespreset_module_types,preset_websites(read / copy-from-preset flows)
Persistence checks
Module lists now come from the owner's module table, including newly created empty modules, and follow the saved module sort order. A zero sort order is preserved. Module/website deletion checks the affected row count and deletes relations in the same transaction. Missing or unowned records return the existing 404 API response instead of a false success.
Regression checks can opt into a dedicated local PostgreSQL database named
bitechain_test with BITECHAIN_TEST_DATABASE_URL. The normal test command skips
these database tests when this variable is absent; the integration suite refuses
remote or differently named databases. It creates and removes only its own fixtures.