Files
workspace/code/app/PROJECT_CONTEXT.md
T
2026-06-10 22:06:52 +08:00

11 KiB

Allapp Project Context

This file is a compact project memory for future Codex chats. Read it first when working in D:\workspace\code\app.

Workspace

  • Root: D:\workspace\code\app
  • Git repository root: D:\workspace
  • Backend: app-go
  • Frontend: app-rn
  • Local database memo: db.local.yml
  • Treat config files as sensitive. Some local config files may contain real credentials.

Product Mental Model

Allapp is shaped more like a mini-program platform than a single linear mobile app.

There is a main shell for the family/personal space, and feature modules behave like small apps inside it. The frontend owns most product flow and business behavior. The backend is deliberately thin and generic, acting mostly as auth, file storage, ID generation, and database access.

High-level model:

Allapp main shell
├── Home / Chat / Tools / My
├── Auth and family/space management
└── Sub-apps
    ├── Finance
    │   ├── Home
    │   ├── Add record
    │   └── Analysis
    └── Clothes matching
        └── Planned/listed, route not implemented yet

Important naming note:

  • The product often uses "family" and "space" as the same concept.
  • Database tables use b_family and b_family_member.
  • Main tab config currently includes /space, but there is no matching page yet.

Backend: app-go

Tech stack:

  • Go
  • Fiber v3
  • pgx PostgreSQL client
  • JWT
  • Viper config
  • Zap logging
  • S3/RustFS file storage
  • QQ/WeChat login and binding
  • Snowflake-style unique ID generator

Important files:

  • Entry: app-go/cmd/app/main.go
  • Bootstrap: app-go/internal/bootstrap/app.go
  • Server: app-go/internal/bootstrap/server.go
  • Routes: app-go/internal/router/router.go
  • Config type: app-go/internal/config/config.go
  • Request binding/validation: app-go/internal/httpx/request.go
  • Response shape: app-go/internal/httpx/response.go
  • Auth middleware: app-go/internal/middleware/auth.go
  • Generic DB access: app-go/pkg/db/*

Bootstrap flow:

config -> logger -> S3 client -> Postgres pool -> db.Init
       -> unique ID -> JWT -> WeChat client -> Fiber server

API base path comes from config and is currently:

/app

Important endpoints:

POST /app/auth/login/qq
POST /app/auth/login/wechat
POST /app/bind/qq
POST /app/bind/wechat

POST /app/data/loadData
POST /app/data/loadDataBySql
POST /app/data/saveData
POST /app/data/getUniqueId

POST /app/s3/upload
POST /app/s3/delete

Backend architecture notes:

  • loadData accepts a table/view name, selected columns, condition string, order string, and args.
  • loadDataBySql accepts raw SQL and args.
  • saveData accepts batches of inserts, updates, and deletes by table name/key field.
  • Insert/update helpers add audit fields for most tables via applyMetaFields.
  • Token header is parsed by middleware.Auth() and stores user_id in context.
  • There are no explicit database foreign keys in the inspected schema; relationships are enforced by code and naming conventions.

Security/architecture caution:

  • The generic data API is very flexible but risky.
  • Table names, columns, conditions, ordering, and raw SQL can come from the frontend.
  • If this moves toward production, prioritize server-side table/field whitelists, ownership checks, and removing or restricting raw SQL.

Validation notes:

  • BindAndValidate validates structs with go-playground/validator.
  • It skips validation for slices.
  • GetUniqueIdReq.Count currently uses a binding tag, not a validate tag, so its min/max rules may not run.

Frontend: app-rn

Tech stack:

  • Expo 55
  • React Native 0.83
  • React 19
  • Expo Router
  • Zustand
  • Alova with Axios adapter
  • HeroUI Native
  • Uniwind / Tailwind-style classes
  • Lucide React Native icons
  • QQ/WeChat native login plugins

Important files:

  • Package: app-rn/package.json
  • App config: app-rn/app.json
  • Root layout: app-rn/src/app/_layout.tsx
  • Startup redirect page: app-rn/src/app/index.tsx
  • Request wrapper: app-rn/src/request/index.ts
  • API methods: app-rn/src/request/api.ts
  • User store: app-rn/src/store/user.ts
  • Family store: app-rn/src/store/family.ts
  • Finance store: app-rn/src/store/finance.ts
  • Main shell layout: app-rn/src/layouts/AppLayout.tsx
  • Module shell layout: app-rn/src/layouts/ModuleLayout.tsx
  • Shared tabbar: app-rn/src/components/layout/tabbar.tsx
  • App/module list config: app-rn/src/configs/pages.ts

Frontend/backend contract:

  • Frontend reads EXPO_PUBLIC_API_URL.
  • Requests use Alova with Axios adapter.
  • Auth token is sent in a custom Token header.
  • Login APIs are whitelisted in the request wrapper.
  • Backend response shape:
{
  code: number;
  message: string;
  data: unknown;
  track_id?: string;
}

Response codes:

1000 success
1001 unauthorized/token expired
2000 business error
3000 system error

State:

  • user-storage: persisted user token/id/nickname/avatar.
  • family-storage: persisted current family id.
  • Finance categories are in memory only and loaded by the finance module layout.

Startup flow:

/ index
├── no local token -> /auth/login
├── token exists but user check fails -> /auth/login
├── token exists but no family -> /family/entry
└── token exists and family exists -> /(tabs)/home

Frontend Route Structure

Expo Router tree:

src/app
├── _layout.tsx
├── index.tsx
├── +not-found.tsx
├── auth
│   └── login.tsx
├── (tabs)
│   ├── _layout.tsx
│   ├── home/index.tsx
│   ├── chat/index.tsx
│   ├── my/index.tsx
│   └── star/index.tsx
├── tools
│   └── index.tsx
├── family
│   ├── entry.tsx
│   ├── settings.tsx
│   ├── user.tsx
│   └── member/[id].tsx
└── finance
    ├── (tabs)
    │   ├── _layout.tsx
    │   ├── home/index.tsx
    │   └── analysis/index.tsx
    ├── add/index.tsx
    └── sub/index.tsx

Effective routes:

/                       startup redirect
/auth/login             login
/home                   main home
/chat                   chat/image picker demo
/my                     profile tab
/star                   placeholder page, not currently in tab config
/tools                  app/module list
/family/entry           create or join family
/family/settings        family settings
/family/user            user profile settings
/family/member/:id      family member detail
/finance/home           finance module home
/finance/add            add finance record
/finance/analysis       finance analysis
/finance/sub            test page

Main tab config in src/app/(tabs)/_layout.tsx:

/home    首页
/space   空间, but route currently missing
/tools   center app-list button
/chat    聊天
/my      我的

Finance module tab config in src/app/finance/(tabs)/_layout.tsx:

/finance/home       记账
/finance/add        center add button
/finance/analysis   分析

Layout behavior:

  • Root _layout.tsx renders a global Stack with no headers.
  • (tabs)/_layout.tsx uses AppLayout, which renders Slot, top Navbar, and bottom Tabbar.
  • finance/(tabs)/_layout.tsx uses ModuleLayout, a module-level shell with its own top bar and tabbar.
  • ModuleLayout close action returns to /(tabs)/home.

Current route mismatches:

  • Main tab points to /space, but no /space file exists.
  • src/app/(tabs)/star/index.tsx exists but is not in the tab config.
  • /tools is outside (tabs), so it is not wrapped by AppLayout; decide whether this is intentional.
  • /finance/add is outside finance/(tabs), but the finance tabbar points to it. This can be intentional for a modal/subpage style add screen.

Feature Status

Implemented or mostly implemented:

  • QQ login
  • WeChat login
  • Auth persistence
  • Auth-expired redirect
  • Family creation
  • Family joining by invite code
  • Family settings
  • User profile
  • Avatar upload to S3/RustFS
  • QQ/WeChat account binding
  • App/module list page

Partially implemented:

  • Finance module shell
  • Finance category loading
  • Finance add-record form UI
  • Finance analysis placeholder/demo page

Not yet complete:

  • Saving a finance record from /finance/add
  • Finance record list on /finance/home
  • Finance analysis real data
  • Clothes matching app route
  • /space main-tab page

Database: allapp

Observed database:

  • PostgreSQL version observed previously: 18.1
  • Database: allapp
  • Schema: public
  • Explicit foreign keys: none observed

Tables:

b_user
b_user_oauth
b_family
b_family_member
b_finance
b_finance_category
b_finance_category_default

Views:

v_family_member

Main entities:

  • b_user: user profile, nickname, avatar, last login time, name, phone, birth date.
  • b_user_oauth: third-party login bindings; includes user_id, type, openid.
  • b_family: family/space; includes name, invite_code, owner_id.
  • b_family_member: family membership; includes family_id, user_id, role, nickname.
  • b_finance: finance records; includes category_id, family_id, amount, remark, record_time.
  • b_finance_category_default: default finance category template.
  • b_finance_category: actual finance categories for a family.
  • v_family_member: joins b_family_member with b_user.

Finance conventions:

type = 0 expense
type = 1 income

Category icon names match frontend iconfont names, for example:

finance_jiaotong
finance_canyin
finance_shicai
finance_gouwu
finance_gongzi
finance_jianzhi
finance_shouru

Local Environment Notes

The Codex shell runs inside WSL2 Ubuntu.

WSL has fnm installed at:

/home/oneao/.local/share/fnm/fnm

Known WSL Node setup:

fnm 1.39.0
v22.22.3
v24.16.0 default

In non-interactive Codex commands, ~/.bashrc may not initialize fnm automatically. If node is not found, temporarily enable it with:

export PATH="$HOME/.local/share/fnm:$PATH"
eval "$(fnm env --shell bash)"

After fnm init, expected tools:

node v24.16.0
pnpm 11.5.2

Windows-side nvm paths may appear in PATH:

/mnt/d/devtool/nvm
/mnt/d/devtool/nodejs

Those are not the right runtime for WSL. Prefer WSL fnm.

Known Type/Build Issues

Frontend:

  • pnpm exec tsc --noEmit currently fails.
  • tsconfig.json includes **/*.ts and **/*.tsx, pulling in example.
  • tsconfig.json has a suspicious extra include entry: src/app/auth/login_2.
  • Generated iconfont components have react-native-svg prop type incompatibilities.
  • src/app/finance/(tabs)/analysis/index.tsx has Surface variant="2" type mismatch.

Backend:

  • go was not available in the earlier command environment, so go test ./... could not be rerun there.
  • Prior context noted a possible unique ID package compile issue around fmt.Println(message) vs fmt.Println(message...).

Important Current Risks

  • Generic backend data APIs need server-side permissions before production use.
  • Finance category loading currently queries all b_finance_category rows without filtering by current family_id.
  • Frontend business logic often trusts local/user-provided family and user IDs.
  • Main tab route /space is missing.
  • Some pages are placeholders or demos.