managarten/apps/manadeck
Till-JS feaf27dd14 feat(auth): implement cross-subdomain SSO for all web apps
Add Single Sign-On (SSO) support across all mana.how subdomains:

- Add trySSO() method to @manacore/shared-auth that exchanges session
  cookies for JWT tokens
- Add /api/v1/auth/session-to-token endpoint to mana-core-auth service
- Update all 15 web apps to try SSO during auth initialization

SSO Flow:
1. User logs in on any app (e.g., calendar.mana.how)
2. Session cookie is set with Domain=.mana.how
3. When visiting another app (e.g., todo.mana.how), it checks for
   local tokens first
4. If no local tokens, tries SSO via session cookie
5. Session cookie is exchanged for JWT tokens via new endpoint
6. User is automatically authenticated

Apps updated: calendar, chat, clock, contacts, manacore, manadeck,
nutriphi, picture, planta, presi, questions, skilltree, storage,
todo, zitare

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 13:17:04 +01:00
..
.github/workflows refactor: restructure 2025-11-26 03:03:24 +01:00
apps feat(auth): implement cross-subdomain SSO for all web apps 2026-02-02 13:17:04 +01:00
supabase/migrations feat(manadeck): migrate stores to backend API and remove audio features 2025-11-27 14:47:14 +01:00
.gitignore refactor: restructure 2025-11-26 03:03:24 +01:00
CI_CD_SETUP_GUIDE.md refactor: restructure 2025-11-26 03:03:24 +01:00
CREDIT_SYSTEM.md refactor: restructure 2025-11-26 03:03:24 +01:00
DEPLOYMENT_CHECKLIST.md style: auto-format codebase with Prettier 2025-11-27 18:33:16 +01:00
EDGE_FUNCTION_FIX.md style: auto-format codebase with Prettier 2025-11-27 18:33:16 +01:00
MANA_CORE_ARCHITECTURE.md refactor: restructure 2025-11-26 03:03:24 +01:00
MANA_CORE_INTEGRATION_CHECKLIST.md refactor: restructure 2025-11-26 03:03:24 +01:00
MANA_CORE_INTEGRATION_GUIDE.md refactor: restructure 2025-11-26 03:03:24 +01:00
MANA_CORE_README.md refactor: restructure 2025-11-26 03:03:24 +01:00
README.md refactor: restructure 2025-11-26 03:03:24 +01:00
SETUP_GUIDE.md refactor: restructure 2025-11-26 03:03:24 +01:00

Manadeck

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

Features

  • 🔐 Mana Core 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 Core 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 Core
    MANA_SERVICE_URL=https://mana-core-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 Core      │   │  Supabase        │
│  - Auth         │   │  - Database      │
│  - Credits      │   │  - Storage       │
│  - Transactions │   │  - Real-time     │
└─────────────────┘   └──────────────────┘

Credit System

Manadeck 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 Core)

  • 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

manadeck/
├── 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 Core 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 Core service URL https://mana-core-middleware-*.run.app
APP_ID Your app ID from Mana Core cea4bfc6-a4de-4e17-91e2-54275940156e
SERVICE_KEY Service key for credit operations Get from Mana Core
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 Core 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 Core 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: