managarten/apps-archived/maerchenzauber/CHARACTER_SHARING_IMPLEMENTATION.md
Till-JS 61d181fbc2 chore: archive inactive projects to apps-archived/
Move inactive projects out of active workspace:
- bauntown (community website)
- maerchenzauber (AI story generation)
- memoro (voice memo app)
- news (news aggregation)
- nutriphi (nutrition tracking)
- reader (reading app)
- uload (URL shortener)
- wisekeep (AI wisdom extraction)

Update CLAUDE.md documentation:
- Add presi to active projects
- Document archived projects section
- Update workspace configuration

Archived apps can be re-activated by moving back to apps/

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-29 07:03:59 +01:00

320 lines
11 KiB
Markdown

# Character Sharing Feature - Implementation Complete
## Overview
Users can now share **private characters** with friends via deep links. Characters remain private to the owner, but anyone with the link can import them to their library for 10 credits.
**Key Concept:** This is **private sharing** - no publishing required. Your character stays private, only people with the link can see and import it.
## Important: Private Sharing Model
Unlike typical social features, this implementation prioritizes **privacy**:
-**No Publishing Required** - Share any character instantly
-**Stays Private** - Your character remains yours, not in public galleries
-**Link-Only Access** - Only people with the deep link can view/import
-**Full Control** - Delete the character = link stops working
-**No Public Discovery** - Characters aren't searchable or browsable
-**No Analytics** - You won't see who clicked your link (privacy-first)
**Use Case:** Share a character privately with a friend via Messages/WhatsApp, not publish to the world.
## What Was Implemented
### Backend Changes (NestJS)
1. **New DTO** (`backend/src/character/dto/import-character.dto.ts`)
- Validation for character import requests
2. **Service Methods** (`backend/src/core/services/supabase-jsonb-auth.service.ts`)
- `getSharedCharacter(characterId)` - Public endpoint to fetch **any** character by ID (private sharing)
- `importCharacter(characterId, userId, token)` - Creates a copy of shared character
- Includes validation for:
- User can't import their own characters
- User can't import same character twice
3. **Controller Endpoints** (`backend/src/character/character.controller.ts`)
- `GET /character/shared/:characterId` - Public endpoint (no auth required) - works with private characters
- `POST /character/import/:characterId` - Authenticated endpoint with credit check
- 10 credits required to import a character
- Tracks import metadata and increments `times_shared` counter
- **No publishing required** - characters stay private
### Mobile App Changes (React Native/Expo)
1. **Deep Linking Configuration**
- Updated `mobile/app.json` - Changed scheme from `"myapp"` to `"maerchenzauber"`
- Created `mobile/app/+native-intent.tsx` - Deep link handler
- Handles URLs: `maerchenzauber://share/character/{characterId}`
2. **Character Preview Screen** (`mobile/app/character/preview/[characterId].tsx`)
- Displays shared character details
- Shows all character images with selector
- Import button with credit requirement displayed
- Prevents importing own characters
- Prevents duplicate imports
3. **Share Button Component** (`mobile/components/character/ShareCharacterButton.tsx`)
- Simple "Share Character" button
- Native share dialog integration
- **No publishing required** - direct private sharing
- Generates deep link and opens native share sheet
4. **Integration** (`mobile/app/character/[id].tsx`)
- Added ShareCharacterButton to character detail screen
- Positioned below character name/sharing status
## Database Schema Requirements
The following fields should exist in the `characters` table:
```sql
-- Existing fields (already in use):
- id (uuid)
- user_id (uuid)
- name (text)
- image_url (text)
- images_data (jsonb)
- user_description (text)
- character_description (text)
- character_description_prompt (text)
- is_animal (boolean)
- animal_type (text)
- blur_hash (text)
-- Publishing fields (optional - not used in private sharing):
- is_published (boolean) -- Can remain, but not required for sharing
- sharing_preference (text) -- Can remain, but not used in this implementation
- share_code (text) -- Can remain, but not used in this implementation
- published_at (timestamp) -- Can remain, but not used in this implementation
-- Existing field (already in database):
- cloned_from (uuid) -- References id of original character (used for imports)
-- New fields added by migration:
- imported_from_user_id (text) -- User ID of original creator
- imported_at (timestamptz) -- When character was imported
- times_shared (integer) -- Counter for how many times character was imported (default: 0)
```
### Migration Applied ✅
The migration has been applied to your database. The following fields were added:
- `imported_from_user_id` (text)
- `imported_at` (timestamptz)
- `times_shared` (integer, default 0)
And we're using the existing `cloned_from` field to track the original character.
## Testing Guide
### Setup
1. **Restart Backend**: `cd backend && npm run dev`
2. **Restart Mobile App with Cache Clear**: `cd mobile && npx expo start -c`
- Important: Use `-c` flag to clear cache after app.json scheme change
### Test Scenario 1: Private Sharing (Simplified)
1. **Login as User A**
2. **Navigate to any character you created** (doesn't need to be published)
3. **Tap "Share Character" button**
- Native share dialog appears immediately
- No publishing modal required
4. **Share dialog shows**:
- Share link format: `maerchenzauber://share/character/{characterId}`
- Share via any method (Messages, WhatsApp, Email, Copy Link)
- Send link to yourself or another device for testing
### Test Scenario 2: Receiving and Importing
1. **Login as User B** (different account)
2. **Open the shared link**
- Tap the deep link you shared
- App should open to character preview screen
3. **Preview screen should show**:
- Character images (with image selector if multiple)
- Character name and description
- Animal type badge (if applicable)
- "Import to My Library (10 Credits)" button
4. **Tap Import button**
- Confirm dialog should appear
- Should show "Import for 10 credits?"
- Tap confirm
5. **After successful import**:
- Success toast appears
- Navigate to imported character detail
- Character should be in User B's library
### Test Scenario 3: Edge Cases
1. **User tries to import their own character**
- Should show error: "Cannot import your own character"
2. **User tries to import same character twice**
- Should show error: "You have already imported this character"
3. **User with insufficient credits**
- Should show error: "You need 10 credits to import..."
4. **User tries to access deleted character**
- Deep link should show error: "Character not found"
### Test Scenario 4: Deep Link Testing
**Test deep link manually:**
```bash
# iOS
xcrun simctl openurl booted "maerchenzauber://share/character/YOUR_CHARACTER_ID"
# Android
adb shell am start -W -a android.intent.action.VIEW -d "maerchenzauber://share/character/YOUR_CHARACTER_ID"
```
## API Endpoints
### Get Shared Character (Public)
```http
GET /character/shared/:characterId
```
**Response:**
```json
{
"data": {
"id": "uuid",
"name": "Character Name",
"image_url": "https://...",
"images_data": [...],
"user_description": "...",
"is_animal": true,
"animal_type": "fox",
"user_id": "creator-uuid"
}
}
```
### Import Character
```http
POST /character/import/:characterId
Authorization: Bearer <token>
```
**Response:**
```json
{
"data": {
"id": "new-uuid",
"name": "Character Name",
"imageUrl": "https://...",
...
},
"message": "Character imported successfully"
}
```
## Deep Link Format
```
maerchenzauber://share/character/{characterId}
```
**Example:**
```
maerchenzauber://share/character/a1b2c3d4-e5f6-7890-abcd-ef1234567890
```
## File Changes Summary
### New Files
1. `backend/src/character/dto/import-character.dto.ts`
2. `mobile/app/+native-intent.tsx`
3. `mobile/app/character/preview/[characterId].tsx`
4. `mobile/components/character/ShareCharacterButton.tsx`
5. `CHARACTER_SHARING_IMPLEMENTATION.md` (this file)
### Modified Files
1. `backend/src/core/services/supabase-jsonb-auth.service.ts`
2. `backend/src/character/character.controller.ts`
3. `mobile/app.json`
4. `mobile/app/character/[id].tsx`
## Known Limitations
1. **No web fallback** - Deep links only work when app is installed
2. **No share analytics** - Not tracking link opens or share sources
3. **No creator rewards** - Original creator doesn't receive credits when character is imported
4. **No QR codes** - Only URL-based sharing implemented
## Future Enhancements
1. **Universal Links** - Add web landing page for users without app
2. **Share Analytics** - Track how many times links are clicked
3. **Creator Rewards** - Give original creator 5 credits when someone imports
4. **QR Code Generation** - Allow generating QR codes for in-person sharing
5. **Popular Characters Leaderboard** - Show most imported characters
6. **Share Templates** - Custom messages for different platforms
## Troubleshooting
### Deep Link Not Working
- Ensure you restarted Expo with `-c` flag after changing app.json
- Check that URL scheme is `maerchenzauber` (not `myapp`)
- On iOS, deep links might not work in simulator for some URLs - test on device
- On Android, ensure app is in foreground or background (not force-closed)
### Import Failing
- Check user has 10+ credits available
- Verify character is published (is_published = true)
- Check character sharing_preference is not 'private'
- Ensure user is not trying to import their own character
### Backend Errors
- Check Supabase RLS policies allow reading published characters
- Verify all new database fields exist in characters table
- Check backend logs for specific error messages
## Success Criteria
✅ User can share **any private character** directly (no publishing required)
✅ Share button opens native share dialog immediately
✅ Deep link opens app to character preview screen
✅ Character preview shows all character details
✅ Import button validates credits (10 required)
✅ Import creates new character copy in user's library
✅ Prevents self-import and duplicate imports
✅ Times_shared counter increments on original character
✅ Share button integrates seamlessly into character detail screen
**Character remains private to owner** - only people with link can import
## Testing Checklist
- [ ] Backend endpoints return correct responses
- [ ] Deep links open app to preview screen
- [ ] Character preview displays all information (even for private characters)
- [ ] Import validates credits correctly
- [ ] Import creates character copy
- [ ] Prevents self-import
- [ ] Prevents duplicate import
- [ ] Share button works without publishing (private sharing)
- [ ] Share dialog shows correct deep link
- [ ] Credit deduction works (10 credits)
- [ ] Toast notifications appear correctly
- [ ] Error handling works for all edge cases
- [ ] Original character remains private after sharing
---
**Implementation Date:** 2025-10-31
**Status:** ✅ Complete - Ready for Testing