mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-22 03:06:41 +02:00
Drop the threshold-based method and BG_REMOVAL_METHOD config toggle. RMBG-1.4 is now the sole background removal pipeline. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
5 KiB
5 KiB
Figgos
A collectible figure game where users create and collect AI-generated fantasy figures.
Project Structure
apps/figgos/
├── apps/
│ ├── backend/ # @figgos/backend - NestJS API (port 3025)
│ ├── mobile/ # @figgos/mobile - Expo React Native app
│ └── web/ # @figgos/web - SvelteKit web app (port 5196)
├── packages/
│ └── shared/ # @figgos/shared - Shared types & constants
└── package.json
Commands
From monorepo root
pnpm dev:figgos:mobile # Start mobile app
pnpm dev:figgos:web # Start web app (port 5196)
pnpm dev:figgos:backend # Start backend
pnpm dev:figgos:app # Start web + backend together
pnpm dev:figgos:full # Start with auth + auto DB setup
pnpm figgos:db:push # Push schema to database
pnpm figgos:db:studio # Open Drizzle Studio
From mobile directory
npx expo start # Start Expo Go
npx expo start --dev-client # Start with dev build
npx expo start --clear # Start with clean cache
Technology Stack
- Mobile: React Native 0.81 + Expo SDK 54, NativeWind 4, Expo Router
- Web: SvelteKit 2.x, Svelte 5 (runes mode), Tailwind CSS 4
- Backend: NestJS 10, Drizzle ORM, PostgreSQL
- Auth: Mana Core Auth (JWT via @manacore/shared-nestjs-auth)
- Shared:
@figgos/shared— all types inlined insrc/index.ts(Node v24 ESM compat) - AI: Google Gemini API (
gemini-3-flash-previewfor text,gemini-2.5-flash-imagefor images) - Storage: MinIO (local) / Hetzner S3 (production) via
@manacore/shared-storage
Ports
| App | Port |
|---|---|
| Backend | 3025 |
| Web | 5196 |
Environment Variables
Backend (.env)
PORT=3025
DATABASE_URL=postgresql://manacore:devpassword@localhost:5432/figgos
MANA_CORE_AUTH_URL=http://localhost:3001
DEV_BYPASS_AUTH=true
DEV_USER_ID=00000000-0000-0000-0000-000000000000
GEMINI_API_KEY=<your-gemini-api-key>
FIGGOS_STORAGE_PUBLIC_URL=http://localhost:9000/figgos-storage
S3_ENDPOINT=http://localhost:9000
S3_ACCESS_KEY=minioadmin
S3_SECRET_KEY=minioadmin
S3_BUCKET=figgos-storage
CORS_ORIGINS=http://localhost:5196,http://localhost:8081
Mobile (.env)
EXPO_PUBLIC_BACKEND_URL=http://localhost:3025
EXPO_PUBLIC_MANA_CORE_AUTH_URL=http://localhost:3001
Background Removal
Uses RMBG-1.4 AI segmentation model (@huggingface/transformers) for background removal. The model is lazy-loaded and cached on first use (~1s first run to download). After removal, a white-threshold cleanup pass targets the top 12% of the card to remove peg-hole (hang tab) artifacts that the model sometimes preserves.
Game Concept
- Users create fantasy figures by providing a name + description
- Backend rolls rarity (common 60%, rare 25%, epic 12%, legendary 3%)
- AI generates character profile (subtitle, backstory, stats, items, specialAttack) + card image
- Card style derived from rarity (common gets random variant: kraft/white/mint/warm)
- Figures have rarities: common, rare, epic, legendary
- Stats (attack, defense, special) are clamped to rarity-based ranges
Generation Pipeline
POST /api/v1/figures triggers synchronous generation:
- Roll rarity — weighted random (common 60%, rare 25%, epic 12%, legendary 3%)
- Generate profile — Gemini text model creates subtitle, backstory, visualDescription, items, stats, specialAttack
- Generate image — Gemini image model creates card artwork based on visual description + card style
- Remove background — Strip white background (feathered threshold or RMBG-1.4)
- Upload to S3 — Store as WebP in
figgos-storagebucket - Update DB — Save generatedProfile, imageUrl, status='completed'
Architecture Notes
Shared Package (@figgos/shared)
- Uses
"type": "module"for Node v24 ESM compatibility - All types inlined in
src/index.ts(no subdirectory imports — avoids ESM extension issues) - Imported at runtime by backend (Node v24 type stripping) and bundled by Metro for mobile
Backend
- Global prefix
api/v1set by@manacore/shared-nestjs-setup— controllers use resource-only names (e.g.@Controller('figures')) DEV_BYPASS_AUTH=trueskips JWT validation in development- Rarity rolled server-side,
cardStylederived at generation time (not persisted) - Generation is synchronous — client waits ~10-15s for full pipeline
Mobile (Expo SDK 54)
- Re-scaffolded with
create-expo-app(tabs template) for clean setup - NativeWind 4 with
react-native-css-interopas explicit dep (pnpm strict hoisting) babel-preset-expoconfigured withworklets: false(using Reanimated v3 for Expo Go compat)newArchEnabled: falsein app.json (Expo Go doesn't fully support new architecture)- Path alias:
~/maps to project root via tsconfig
Web (SvelteKit)
- API service at
$lib/api.ts— simple fetch wrapper, no auth for dev - Svelte 5 runes (
$state,$derived,$effect) - Neo-brutalist design with 3D flip card detail view