managarten/apps/cards
Till JS 950b822070 docs(cards): Phase-1 Spinoff-Guidelines — Core-Gameloop, Stack, Datenpfad
Verbindliche Leitlinien für den Cards-Spinoff (Karteikarten-App mit
Spaced Repetition). Status: Planungsphase, noch kein Code. Doc dient
als nicht-verhandelbarer Kontext für PRs sobald gebaut wird.

Wichtigste Festlegungen:
- Game-Dev-Prinzip: Phase 1 baut NUR den Core-Gameloop (Lernsession).
  KI-Generierung, Voice, Sharing, Stripe, Mobile, Dashboards = Phase 2+.
- Open-Source-only: jede Dep braucht OSI-konforme Lizenz.
- Zentrale Mana-Bausteine sind Pflicht, kein Eigen-Auth/Sync/Analytics.
- Daten-Contract mit dem bestehenden mana-Modul: gleiche Postgres-
  Tabellen (cardDecks/cards + neu cardReviews/cardStudyBlocks),
  appId='cards'. Schema-Änderungen rolled-out gemeinsam, nicht einseitig.
- FSRS v6 via ts-fsrs für Spaced-Repetition-Algorithmik.
- Phase 1 hat keinen eigenen Service — Lese-/Schreibpfad geht
  ausschließlich über IndexedDB → mana-sync → Postgres.

Definition of Done in §7 ist die Acceptance-Liste fürs MVP.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 20:39:26 +02:00
..
.github/workflows refactor: rename ManaDeck to Cards across entire monorepo 2026-04-01 11:45:21 +02:00
apps/landing chore(mobile): remove 6 of 7 mobile apps — keep only memoro 2026-04-20 15:31:47 +02:00
supabase/migrations chore(memoro): remove old NestJS backends (Phase 8+9) 2026-04-01 11:21:03 +02:00
.gitignore chore(memoro): remove old NestJS backends (Phase 8+9) 2026-04-01 11:21:03 +02:00
CI_CD_SETUP_GUIDE.md chore: complete ManaCore → Mana rename (docs, go modules, plists, images) 2026-04-07 12:26:10 +02:00
CREDIT_SYSTEM.md chore: complete ManaCore → Mana rename (docs, go modules, plists, images) 2026-04-07 12:26:10 +02:00
DEPLOYMENT_CHECKLIST.md chore: complete ManaCore → Mana rename (docs, go modules, plists, images) 2026-04-07 12:26:10 +02:00
EDGE_FUNCTION_FIX.md refactor: rename ManaDeck to Cards across entire monorepo 2026-04-01 11:45:21 +02:00
GUIDELINES.md docs(cards): Phase-1 Spinoff-Guidelines — Core-Gameloop, Stack, Datenpfad 2026-05-06 20:39:26 +02:00
MANA_CORE_ARCHITECTURE.md chore: complete ManaCore → Mana rename (docs, go modules, plists, images) 2026-04-07 12:26:10 +02:00
MANA_CORE_INTEGRATION_CHECKLIST.md chore: complete ManaCore → Mana rename (docs, go modules, plists, images) 2026-04-07 12:26:10 +02:00
MANA_CORE_INTEGRATION_GUIDE.md chore: complete ManaCore → Mana rename (docs, go modules, plists, images) 2026-04-07 12:26:10 +02:00
MANA_CORE_README.md chore: complete ManaCore → Mana rename (docs, go modules, plists, images) 2026-04-07 12:26:10 +02:00
README.md chore: complete ManaCore → Mana rename (docs, go modules, plists, images) 2026-04-07 12:26:10 +02:00
SETUP_GUIDE.md chore: complete ManaCore → Mana rename (docs, go modules, plists, images) 2026-04-07 12:26:10 +02:00

Cards

A deck management system with Mana authentication and credit system integration.

Features

  • 🔐 Mana Authentication - Complete auth system with JWT tokens, device tracking, and automatic token refresh
  • Credit System - Mana-based billing for operations (10 mana to create a deck, 5 for AI features, etc.)
  • 📱 React Native/Expo - Cross-platform mobile app (iOS, Android, Web)
  • 🚀 NestJS Backend - Type-safe API with AuthGuard protection
  • 💾 Supabase - Database and real-time features
  • 🎨 NativeWind - Tailwind CSS for React Native styling

Quick Start

Prerequisites

  • Node.js 18+
  • npm or yarn
  • Expo CLI (npm install -g expo-cli)
  • Supabase account
  • Mana credentials (APP_ID, SERVICE_KEY)

Backend Setup

  1. Navigate to backend directory:

    cd backend
    
  2. Install dependencies:

    npm install
    
  3. Configure environment variables:

    cp .env.example .env
    

    Edit .env and add your credentials:

    # Mana
    MANA_SERVICE_URL=https://mana-middleware-111768794939.europe-west3.run.app
    APP_ID=your-app-id-from-mana-core
    SERVICE_KEY=your-service-key-from-mana-core  # Required for credits
    
    # Supabase
    SUPABASE_URL=https://your-project.supabase.co
    SUPABASE_ANON_KEY=your-anon-key
    SUPABASE_SERVICE_KEY=your-service-key
    
    # Server
    NODE_ENV=development
    PORT=8080
    
  4. Start the backend:

    npm run start:dev
    

    Backend will be available at http://localhost:8080

Frontend Setup

  1. Navigate to mobile app directory:

    cd apps/mobile
    
  2. Install dependencies:

    npm install
    
  3. Configure environment:

    cp .env.example .env
    

    Edit .env:

    # Supabase
    EXPO_PUBLIC_SUPABASE_URL=https://your-project.supabase.co
    EXPO_PUBLIC_SUPABASE_ANON_KEY=your-anon-key
    
    # Backend API
    EXPO_PUBLIC_API_URL=http://localhost:8080  # For local development
    # EXPO_PUBLIC_API_URL=https://your-production-backend.com  # For production
    
  4. Start Expo:

    npm start
    
  5. Run on platform:

    • Press i for iOS simulator
    • Press a for Android emulator
    • Press w for web browser

Architecture

┌─────────────────────┐
│   Mobile App        │  React Native + Expo
│   (Frontend)        │  - Authentication UI
│                     │  - Credit balance display
│                     │  - Deck management
└──────────┬──────────┘
           │ HTTPS/JSON
           │ Bearer Token Auth
           ▼
┌─────────────────────┐
│   Backend API       │  NestJS
│                     │  - AuthGuard protection
│                     │  - Credit validation
│                     │  - Business logic
└──────────┬──────────┘
           │
           ├─────────────────────┐
           │                     │
           ▼                     ▼
┌─────────────────┐   ┌──────────────────┐
│  Mana      │   │  Supabase        │
│  - Auth         │   │  - Database      │
│  - Credits      │   │  - Storage       │
│  - Transactions │   │  - Real-time     │
└─────────────────┘   └──────────────────┘

Credit System

Cards uses Mana as its credit currency. Operations cost credits:

Operation Cost
Create Deck 10 mana
Create Card 2 mana
AI Card Generation 5 mana
Export Deck 3 mana

How it Works

  1. Pre-flight Validation: Backend checks if user has enough credits
  2. Operation: Performs the requested operation (create deck, etc.)
  3. Consumption: Deducts credits only if operation succeeds
  4. Response: Returns success + credits used

Frontend Integration

The frontend automatically handles insufficient credits with a modal:

import { useInsufficientCredits } from '../hooks/useInsufficientCredits';
import { InsufficientCreditsModal } from '../components/InsufficientCreditsModal';

function MyScreen() {
  const insufficientCredits = useInsufficientCredits();

  const handleAction = async () => {
    try {
      await post('/api/decks', data);
    } catch (error) {
      // Automatically shows modal if insufficient credits
      insufficientCredits.handleCreditError(error);
    }
  };

  return (
    <>
      <Button onPress={handleAction} />
      <InsufficientCreditsModal {...insufficientCredits} />
    </>
  );
}

Full documentation: See CREDIT_SYSTEM.md

API Endpoints

Authentication (via Mana)

  • POST /v1/auth/signin - Sign in
  • POST /v1/auth/signup - Sign up
  • POST /v1/auth/refresh - Refresh token
  • POST /v1/auth/logout - Sign out

Protected Endpoints (require Bearer token)

  • GET /api/profile - Get user profile + credit balance
  • GET /api/credits/balance - Get credit balance
  • GET /api/decks - List user's decks
  • POST /api/decks - Create deck (costs 10 mana)
  • PUT /api/decks/:id - Update deck
  • DELETE /api/decks/:id - Delete deck
  • GET /api/cards - List cards
  • POST /api/cards - Create card (costs 2 mana)

Public Endpoints

  • GET /public/health - Health check
  • GET /public/version - API version
  • GET /public/featured-decks - Featured decks (optional auth)

Project Structure

cards/
├── backend/                    # NestJS backend
│   ├── src/
│   │   ├── config/
│   │   │   ├── credit-operations.ts   # Credit costs & operation types
│   │   │   └── validation.schema.ts   # Environment validation
│   │   ├── controllers/
│   │   │   ├── api.controller.ts      # Protected endpoints
│   │   │   ├── public.controller.ts   # Public endpoints
│   │   │   └── health.controller.ts   # Health checks
│   │   ├── services/
│   │   │   └── supabase.service.ts    # Supabase integration
│   │   ├── app.module.ts              # Main module (Mana config)
│   │   └── main.ts                    # Entry point
│   ├── .env                    # Environment variables
│   └── package.json
│
├── apps/
│   ├── mobile/                # React Native/Expo app
│   ├── web/                   # Web app
│   └── landing/               # Landing page
│   ├── app/                    # Expo Router screens
│   │   ├── (tabs)/            # Tab navigation
│   │   └── _layout.tsx        # Root layout
│   ├── components/
│   │   └── InsufficientCreditsModal.tsx   # Credit error modal
│   ├── services/
│   │   ├── authService.ts     # Authentication
│   │   ├── tokenManager.ts    # Token refresh & management
│   │   └── creditService.ts   # Credit operations
│   ├── hooks/
│   │   └── useInsufficientCredits.ts  # Credit error handling
│   ├── types/
│   │   ├── auth.ts            # Auth types
│   │   └── credits.ts         # Credit types
│   ├── utils/
│   │   ├── apiClient.ts       # Authenticated API client
│   │   └── deviceManager.ts   # Device info
│   ├── examples/
│   │   └── DeckCreationExample.tsx    # Usage example
│   ├── .env                   # Environment variables
│   └── package.json
│
├── CREDIT_SYSTEM.md           # Credit system documentation
├── MANA_CORE_INTEGRATION_GUIDE.md
├── MANA_CORE_INTEGRATION_CHECKLIST.md
├── MANA_CORE_ARCHITECTURE.md
├── MANA_CORE_README.md
└── README.md                  # This file

Development

Backend

cd backend

# Development with hot reload
npm run start:dev

# Build for production
npm run build

# Run production build
npm run start:prod

# Linting
npm run lint

# Tests
npm run test

Frontend

cd apps/mobile

# Start Expo dev server
npm start

# Run on iOS
npm run ios

# Run on Android
npm run android

# Run on web
npm run web

# Linting & formatting
npm run lint
npm run format

# Build with EAS
npm run build:dev      # Development build
npm run build:preview  # Preview build
npm run build:prod     # Production build

Environment Variables

Backend Required Variables

Variable Description Example
MANA_SERVICE_URL Mana service URL https://mana-middleware-*.run.app
APP_ID Your app ID from Mana cea4bfc6-a4de-4e17-91e2-54275940156e
SERVICE_KEY Service key for credit operations Get from Mana
SUPABASE_URL Supabase project URL https://abc.supabase.co
SUPABASE_ANON_KEY Supabase anonymous key Your anon key
PORT Backend port 8080

Frontend Required Variables

Variable Description Example
EXPO_PUBLIC_SUPABASE_URL Supabase project URL https://abc.supabase.co
EXPO_PUBLIC_SUPABASE_ANON_KEY Supabase anonymous key Your anon key
EXPO_PUBLIC_API_URL Backend API URL http://localhost:8080

Testing

Backend Testing

The backend includes example tests in backend/src/app.controller.spec.ts. To add credit system tests:

import { CreditClientService } from '@mana-core/nestjs-integration/services';

// Mock in test setup
{
  provide: CreditClientService,
  useValue: {
    validateCredits: jest.fn().mockResolvedValue({
      hasCredits: true,
      availableCredits: 100,
    }),
    consumeCredits: jest.fn(),
  },
}

Manual Testing

  1. Test authentication:

    # Sign up
    curl -X POST http://localhost:8080/v1/auth/signup \
      -H "Content-Type: application/json" \
      -d '{"email":"test@example.com","password":"password123","username":"testuser"}'
    
    # Sign in
    curl -X POST http://localhost:8080/v1/auth/signin \
      -H "Content-Type: application/json" \
      -d '{"email":"test@example.com","password":"password123"}'
    
  2. Test protected endpoint:

    export TOKEN="your-jwt-token-from-signin"
    
    curl -H "Authorization: Bearer $TOKEN" \
      http://localhost:8080/api/profile
    
  3. Test credit system:

    # Check balance
    curl -H "Authorization: Bearer $TOKEN" \
      http://localhost:8080/api/credits/balance
    
    # Create deck (costs 10 mana)
    curl -X POST http://localhost:8080/api/decks \
      -H "Authorization: Bearer $TOKEN" \
      -H "Content-Type: application/json" \
      -d '{"name":"My Deck","description":"Test deck"}'
    

Troubleshooting

Backend won't start

  • Check all environment variables are set
  • Verify Mana credentials are correct
  • Check if port 8080 is available

Credits not working

  • Ensure SERVICE_KEY is set in backend .env
  • Check backend logs for credit validation errors
  • Verify user has credits in Mana dashboard

Frontend can't connect to backend

  • Check EXPO_PUBLIC_API_URL is correct
  • For Android emulator, use http://10.0.2.2:8080 instead of localhost
  • Verify backend is running

Token refresh fails

  • Check device info is being sent with refresh requests
  • Verify refresh token is stored correctly
  • Check network connectivity

Documentation

Resources

License

Private project - All rights reserved

Support

For issues related to: