Claude Code Plugins

Community-maintained marketplace

Feedback
1
0

Step-by-step user journeys through the mixmi platform including onboarding, upload, remix creation, purchasing, and discovery

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name mixmi-user-flows
description Step-by-step user journeys through the mixmi platform including onboarding, upload, remix creation, purchasing, and discovery
metadata [object Object]

mixmi User Flows

Complete step-by-step journeys showing how users interact with the mixmi platform.

Table of Contents

  1. Flow 1: Alpha User Onboarding
  2. Flow 2: Quick Upload (Minimal)
  3. Flow 3: Advanced Upload (Full Metadata)
  4. Flow 4: Creating a Remix (Planned)
  5. Flow 5: Purchasing Content
  6. Flow 6: Discovery via Globe
  7. Flow 7: Discovery via Search
  8. Flow 8: Browsing Creator Stores
  9. Flow 9: Exploring Artist Profiles
  10. Flow 10: Editing Your Profile

Flow 1: Alpha User Onboarding

Goal: Authenticate and gain upload access Duration: 1-2 minutes Authentication Methods: Stacks Wallet OR Alpha Invite Code

Path A: Stacks Wallet Authentication (Preferred)

Step 1: Navigate to Platform

URL: https://mixmi-alpha.vercel.app/ (or localhost) Page: Globe homepage (app/page.tsx) State: User not authenticated

UI:

  • Header shows "Sign In" button (top-right)
  • Globe visible with existing content
  • No upload button visible

Step 2: Click "Sign In"

Action: User clicks "Sign In" in header Component: Header.tsx → opens SignInModal.tsx

Modal Displays:

  • "Welcome to mixmi Alpha" header
  • Two options:
    1. "Connect Wallet" button (cyan, primary)
    2. "Use Alpha Code" link (secondary, text link below)

Step 3: Click "Connect Wallet"

Action: User clicks "Connect Wallet" Library: @stacks/connect (Stacks blockchain wallet integration)

What Happens:

import { showConnect } from '@stacks/connect';

showConnect({
  appDetails: {
    name: 'mixmi Alpha',
    icon: window.location.origin + '/logo.png'
  },
  onFinish: (data) => {
    // Wallet connection successful
    const walletAddress = data.userSession.loadUserData().profile.stxAddress.mainnet;
    // Store in AuthContext
  },
  onCancel: () => {
    // User closed wallet popup
  }
});

Wallet Popup Appears:

  • Shows available wallets (Hiro, Xverse, Leather, etc.)
  • User selects their wallet
  • Wallet asks to approve connection
  • User signs authentication message

Step 4: Alpha Whitelist Verification

Backend Call:

const response = await fetch('/api/auth/alpha-check', {
  method: 'POST',
  body: JSON.stringify({ walletAddress })
});

const { isApproved, alphaCode } = await response.json();

Database Query:

SELECT alpha_code, is_active
FROM alpha_users
WHERE wallet_address = 'SP...'
  AND is_active = true;

Two Outcomes:

✅ If Approved:

  • AuthContext sets isAuthenticated = true
  • walletAddress stored in context
  • Modal closes automatically
  • Header now shows:
    • "Upload" button appears
    • Wallet address (truncated): "SP1ABC...XYZ"
    • Cart icon

❌ If Not Approved:

  • Error message: "Wallet not approved for alpha access"
  • Option to request access (future)
  • User must use alpha code instead

Path B: Alpha Code Authentication (Fallback)

Step 1-2: Same as Path A

Step 3: Click "Use Alpha Code"

UI Changes:

  • "Connect Wallet" button dims/hides
  • Text input appears: "Enter your alpha invite code"
  • Placeholder: "mixmi-ABC123"
  • "Submit" button

Step 4: Enter Alpha Code

User Types: mixmi-ABC123 Action: Clicks "Submit"

Validation (Frontend):

const isAlphaCode = (code) => {
  return /^mixmi-[A-Z0-9]{6}$/.test(code);
};

Backend Conversion:

// User entered: mixmi-ABC123
// Backend resolves to actual wallet

const response = await fetch('/api/auth/resolve-wallet', {
  method: 'POST',
  body: JSON.stringify({ authIdentity: 'mixmi-ABC123' })
});

const { walletAddress } = await response.json();
// Returns: SP1ABC...XYZ

Why This Works:

  • UI never shows "wallet address" (prevents security scanner warnings)
  • Backend transparently converts alpha code → wallet
  • Blockchain operations use real wallet address
  • User-friendly authentication

Step 5: Authenticated State

AuthContext State:

{
  isAuthenticated: true,
  walletAddress: 'SP1ABC...',
  alphaCode: 'mixmi-ABC123', // For display
  authMethod: 'alpha_code' // or 'wallet'
}

UI Changes:

  • Modal closes
  • Header shows upload button
  • User can now upload content

First Upload Incentive

After Authentication:

  • Toast notification: "You're in! Ready to upload your first track?"
  • Welcome page: "Sign In and Upload" button now says "Upload Your First Track"

Flow 2: Quick Upload (Minimal)

Goal: Upload a loop or song in ~60 seconds Prerequisites: User authenticated Duration: 1-2 minutes

Step 1: Open Upload Modal

Triggers:

  • Click "Upload" in header
  • Click "Sign In and Upload" on Welcome page (if authenticated)
  • Click "+" in own store

Component: IPTrackModal opens Mode: Quick Upload (default, toggle enabled)

Step 2: Select Content Type

UI: 5 large buttons with icons

┌─────────┬─────────┬─────────┬─────────┬─────────┐
│ 🎵 Song │ 🔁 Loop │📦 Pack │ 💿 EP  │ 🎚️ Mix │
└─────────┴─────────┴─────────┴─────────┴─────────┘

User Clicks: "🔁 Loop"

State Change:

setFormData({ ...formData, content_type: 'loop' });

UI Updates:

  • BPM field becomes required (red asterisk)
  • Loop category dropdown appears

Step 3: Upload Audio File

UI: File picker or drag zone (drag-and-drop for audio not yet implemented)

User Actions:

  • Clicks "Choose Audio File"
  • Selects trap-beat-140.wav (8MB)

File Validation:

// Check format
const validFormats = ['audio/wav', 'audio/mpeg', 'audio/mp4', 'audio/flac'];
if (!validFormats.includes(file.type)) {
  throw new Error('Invalid audio format');
}

// Check size
if (file.size > 10 * 1024 * 1024) {
  throw new Error('File too large (max 10MB)');
}

Auto-Detection Starts:

// BPM detection
setIsDetectingBPM(true);
const detectedBPM = await detectBPM(file);
// Result: 140 BPM

// Duration detection
const duration = await detectDuration(file);
// Result: 32 seconds

UI Updates:

  • Progress bar shows during detection
  • "BPM: 140 (auto-detected)" appears
  • User MUST verify/override this value

Step 4: Fill Basic Metadata

Required Fields (Quick Mode):

Title: [Trap Beat 140      ]  *
Artist: [DJ Example        ]  *
BPM: [140                  ]  * (pre-filled, editable)
Loop Category: [▼ Beats    ]  * (dropdown)
Location: [Los Angeles, CA ]  * (autocomplete)

BPM Verification:

⚠️ User clicks BPM field
Modal: "Auto-detected 140 BPM. Is this correct?"
[Yes, 140 is correct] [No, let me change it]

If user changes to 142:
✓ BPM updated to 142 (whole number only)

Location Autocomplete:

User types: "Los"

Suggestions appear:
┌──────────────────────────┐
│ 🏙️ Los Angeles, CA, USA  │
│ 🏙️ Los Alamos, NM, USA   │
│ 🏙️ Louisiana, USA        │
│ 🏔️ Louisiana Nation      │
└──────────────────────────┘

User selects: Los Angeles, CA, USA

Coordinates Stored:

{
  location_name: "Los Angeles, CA, USA",
  location_lat: 34.052234,
  location_lng: -118.243685
}

Step 5: Upload Cover Image

UI: File picker or drag zone

Auto-Generation Option:

┌────────────────────────────┐
│  📷 Upload Cover Image      │
│                            │
│  [Choose File]             │
│       or                   │
│  [🎨 Auto-Generate]        │
└────────────────────────────┘

If Auto-Generate:

// Creates visual from audio waveform
const generateCover = async (audioFile) => {
  const waveformCanvas = await createWaveformCanvas(audioFile);
  const blob = await canvasToBlob(waveformCanvas);
  return blob;
};

Manual Upload Validation:

// Check image dimensions
const img = new Image();
img.src = URL.createObjectURL(file);
if (img.width < 500 || img.height < 500) {
  alert('Image too small (min 500x500)');
}
if (img.width !== img.height) {
  alert('Image should be square');
}

Step 6: Review and Submit

Pre-Submit Summary:

┌──────────────────────────────┐
│  Ready to Upload?            │
├──────────────────────────────┤
│  Type: Loop                  │
│  Title: Trap Beat 140        │
│  Artist: DJ Example          │
│  BPM: 140                    │
│  Location: Los Angeles, CA   │
│  Files: ✅ Audio ✅ Cover     │
│                              │
│  [← Back]  [Upload Track →]  │
└──────────────────────────────┘

Upload Process:

// 1. Upload audio to Supabase Storage
const audioPath = `${walletAddress}/${Date.now()}_audio.wav`;
await supabase.storage
  .from('user-content')
  .upload(audioPath, audioFile);

// 2. Upload cover image
const imagePath = `${walletAddress}/${Date.now()}_cover.jpg`;
await supabase.storage
  .from('user-content')
  .upload(imagePath, imageFile);

// 3. Create database record
const { data: track } = await supabase
  .from('ip_tracks')
  .insert({
    title: formData.title,
    artist: formData.artist,
    content_type: 'loop',
    bpm: formData.bpm,
    audio_url: audioPath,
    cover_image_url: imagePath,
    location_name: formData.location_name,
    location_lat: formData.location_lat,
    location_lng: formData.location_lng,
    primary_uploader_wallet: walletAddress,
    created_at: new Date().toISOString()
  })
  .select()
  .single();

// 4. Success!
return track;

Step 7: Success State

Modal Updates:

┌──────────────────────────────┐
│  ✅ Upload Complete!         │
├──────────────────────────────┤
│                              │
│  Your track "Trap Beat 140"  │
│  is now live on mixmi!       │
│                              │
│  [View Track] [Upload Another]│
└──────────────────────────────┘

Actions:

  • "View Track" → Opens TrackDetailsModal
  • "Upload Another" → Resets form
  • Close modal → Returns to previous page

Flow 3: Advanced Upload (Full Metadata)

Goal: Upload with complete IP attribution Prerequisites: User authenticated Duration: 3-5 minutes

Toggle to Advanced Mode

Location: Top of IPTrackModal

Quick Upload ○━━━━━● Advanced Upload
               ↑ User slides toggle

What Changes:

  • Additional metadata fields appear
  • IP splitting interface shows
  • Referrer section enabled
  • Full credits section available

Additional Fields in Advanced Mode

IP Splitting Configuration

UI:

┌──────────────────────────────┐
│  IP Splits                   │
├──────────────────────────────┤
│  Producer: [You      ] [60%] │
│  + Add Collaborator          │
│                              │
│  Platform Fee:         15%   │
│  Available:            25%   │
│                              │
│  [+ Add Split Recipient]     │
└──────────────────────────────┘

Adding Collaborator:

// User clicks "+ Add Collaborator"
// New row appears:
{
  role: "Vocalist",        // Dropdown
  wallet: "SP2ABC...",    // Text input
  percentage: 25          // Number input
}

// Validation
if (totalPercentage > 85) {
  error: "Total cannot exceed 85% (15% platform fee)"
}

Credits Section

Fields:

Credits (Optional)
├─ Vocalist: [Jane Doe        ]
├─ Mixing Engineer: [John Mix ]
├─ Mastering: [Master Studios ]
└─ + Add Credit Field

Referrer Attribution

Field:

Referred By (Optional)
[SP2DEF...] or [mixmi-XYZ789]
Help: Who told you about mixmi?

Validation:

// Check if valid wallet or alpha code
const isValidReferrer = (input) => {
  return isWalletAddress(input) || isAlphaCode(input);
};

Complete Upload Flow

All steps from Quick Upload, plus:

  • IP splits configuration
  • Credits attribution
  • Referrer tracking
  • Extended metadata

Flow 4: Creating a Remix (Planned)

Goal: Create and save a remix using the mixer Prerequisites: Authenticated, tracks loaded in mixer Status: Coming in Generation 1

Planned Implementation

Step 1: Load Tracks to Mixer

  • Drag loops from Crate to Deck A/B
  • Or click "Load to Mixer" from track card

Step 2: Create Mix

  • Adjust BPM, apply FX
  • Record live mixing session
  • Mix auto-saves as WebM/Opus

Step 3: Save Recording

Planned Modal:

┌──────────────────────────────┐
│  Save Your Remix             │
├──────────────────────────────┤
│  Title: [Summer Mix 2025   ] │
│  Duration: 3:42              │
│                              │
│  Source Tracks:              │
│  • Loop 1 by Artist A (30%)  │
│  • Loop 2 by Artist B (30%)  │
│  Platform Fee: 15%           │
│  Your Share: 25%             │
│                              │
│  [Cancel] [Save & Upload]    │
└──────────────────────────────┘

Step 4: Auto-Calculate IP Splits

// Automatic attribution based on source loops
const calculateRemixSplits = (sourceTracks) => {
  const remixerShare = 25;  // Fixed for remixer
  const platformFee = 15;   // Fixed platform fee
  const sourceShare = 60;   // Divided among sources
  
  const perSource = sourceShare / sourceTracks.length;
  
  return sourceTracks.map(track => ({
    recipient: track.primary_uploader_wallet,
    percentage: perSource,
    role: 'Original Creator'
  }));
};

Flow 5: Purchasing Content

Goal: Purchase and download a track Prerequisites: None (can purchase without auth) Duration: 30 seconds - 2 minutes

Step 1: Find Track to Purchase

Entry Points:

  • Globe page card hover → price badge
  • Store page → track cards
  • Search results → price badges
  • Track details modal → purchase button

Step 2: Click Price Badge

UI Example:

Track card hover state:
┌─────────────┐
│   Cover     │
│   Image     │
│ [$2.99 STX] │ ← Click this
└─────────────┘

Step 3: Add to Cart

Action: Click price badge Result: Track added to cart

Cart Updates:

  • Cart icon shows item count: 🛒 (1)
  • Toast notification: "Added to cart!"
  • Price badge changes to "✓ In Cart"

Step 4: Open Cart

Click: Cart icon in header Modal: Shopping cart opens

┌──────────────────────────────┐
│  Shopping Cart          [×]  │
├──────────────────────────────┤
│                              │
│  1. Trap Beat 140            │
│     by DJ Example            │
│     Type: Loop               │
│     $2.99 STX         [🗑️]   │
│                              │
│  ─────────────────────────   │
│  Total: $2.99 STX            │
│                              │
│  [Continue Shopping]         │
│  [Proceed to Checkout →]     │
└──────────────────────────────┘

Step 5: Checkout Process

If Not Authenticated:

┌──────────────────────────────┐
│  Sign In to Purchase         │
├──────────────────────────────┤
│  Connect your wallet to       │
│  complete this purchase       │
│                              │
│  [Connect Wallet]            │
│  [Use Alpha Code]            │
└──────────────────────────────┘

If Authenticated:

┌──────────────────────────────┐
│  Confirm Purchase            │
├──────────────────────────────┤
│  Track: Trap Beat 140        │
│  Price: $2.99 STX            │
│  From: Your Wallet           │
│  To: Creator Wallet          │
│                              │
│  IP Splits:                  │
│  • Creator: 60% ($1.79)      │
│  • Platform: 15% ($0.45)     │
│  • Referrer: 10% ($0.30)     │
│  • Other: 15% ($0.45)        │
│                              │
│  [Cancel] [Confirm Purchase] │
└──────────────────────────────┘

Step 6: Blockchain Transaction

Process:

// 1. Initialize Stacks transaction
const transaction = {
  contractAddress: 'ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM',
  contractName: 'mixmi-payments',
  functionName: 'purchase-track',
  functionArgs: [
    trackId,
    priceInMicroSTX,
    ipSplits
  ]
};

// 2. User approves in wallet
await openContractCall(transaction);

// 3. Wait for confirmation
// Shows loading state: "Processing payment..."

// 4. Transaction confirmed

Step 7: Download Access

Success Modal:

┌──────────────────────────────┐
│  ✅ Purchase Complete!       │
├──────────────────────────────┤
│                              │
│  Thank you for supporting    │
│  DJ Example!                 │
│                              │
│  [Download Track]            │
│  [View in Library]           │
│  [Continue Shopping]         │
└──────────────────────────────┘

Download Process:

// Generate temporary download URL
const { data: downloadUrl } = await supabase
  .from('purchases')
  .insert({
    buyer_wallet: walletAddress,
    track_id: track.id,
    transaction_hash: txHash,
    purchased_at: new Date()
  })
  .select('download_token')
  .single();

// Trigger download
window.open(`/api/download/${downloadUrl.download_token}`);

Flow 6: Discovery via Globe

Goal: Discover new music through map interface Prerequisites: None Duration: Ongoing browsing

Globe Interaction

Default View:

  • 3D rotating globe
  • Glowing dots for track locations
  • Auto-rotation at 0.001 radians/frame

Hover on Location Dot

Visual Feedback:

  • Dot grows (1.5x scale)
  • Glow intensifies
  • Tooltip appears with city name

Click on Location

Action: Click glowing dot Result: Track cards appear

┌─────────────────────────────┐
│  Los Angeles, CA            │
│  12 tracks                  │
├─────────────────────────────┤
│ [Track] [Track] [Track]     │
│ [Track] [Track] [Track]     │
│         Load More...         │
└─────────────────────────────┘

Track Card Interactions

Hover State:

  • Card scales to 1.05x
  • Overlay with track details
  • Action buttons appear

Available Actions:

  • Play preview (▶️)
  • Add to cart ($)
  • View details (ℹ️)
  • Load to mixer (🎛️) - if loop

Flow 7: Discovery via Search

Goal: Find specific tracks or artists Prerequisites: None Duration: 10-30 seconds

Access Search

Trigger: Click search icon in header Modal: Search interface opens

Enter Search Query

Search Input:

┌──────────────────────────────┐
│  🔍 Search mixmi             │
├──────────────────────────────┤
│  [trap beats 140 bpm_____]   │
│                              │
│  Filter by:                  │
│  ○ All  ● Tracks  ○ Artists  │
│  ○ Loops  ○ Songs           │
└──────────────────────────────┘

Real-time Results

As User Types:

// Debounced search (300ms)
const debouncedSearch = debounce(async (query) => {
  const { data: results } = await supabase
    .from('ip_tracks')
    .select('*')
    .or(`title.ilike.%${query}%,artist.ilike.%${query}%`)
    .limit(20);
  
  setSearchResults(results);
}, 300);

Results Display

Search Results:

┌──────────────────────────────┐
│  Results for "trap beats"    │
├──────────────────────────────┤
│                              │
│  Tracks (8)                  │
│  ├─ Trap Beat 140           │
│  │  by DJ Example • Loop     │
│  ├─ Dark Trap 150           │
│  │  by Producer X • Loop     │
│  └─ ...                      │
│                              │
│  Artists (3)                 │
│  ├─ Trap Lord               │
│  ├─ Trap Queen              │
│  └─ ...                      │
└──────────────────────────────┘

Select Result

Click Action:

  • Track → Opens TrackDetailsModal
  • Artist → Navigate to artist profile

Flow 8: Browsing Creator Stores

Goal: Explore a creator's catalog Prerequisites: None Duration: 2-5 minutes browsing

Navigate to Store

Entry Points:

  • Click artist name on track card
  • Click "View Store" in profile
  • URL: /store/[identifier]

Store Layout

Header Section:

┌──────────────────────────────┐
│  DJ Example's Store          │
│  12 tracks • Member since Oct│
│                              │
│  [Follow] [Share] [Tip]      │
└──────────────────────────────┘

Track Grid:

Filters: [All] [Loops] [Songs] [Packs]
Sort: [Newest ▼]

┌────┬────┬────┬────┐
│Loop│Loop│Song│Pack│
├────┼────┼────┼────┤
│Loop│EP  │Loop│Song│
├────┼────┼────┼────┤
│... │... │... │... │
└────┴────┴────┴────┘

Filter and Sort

Filter Options:

const filters = {
  all: null,
  loops: "content_type = 'loop'",
  songs: "content_type = 'full_song'",
  packs: "content_type IN ('loop_pack', 'ep')"
};

Sort Options:

  • Newest First (default)
  • Oldest First
  • Price: Low to High
  • Price: High to Low
  • Most Downloaded (future)

Flow 9: Exploring Artist Profiles

Goal: Learn about an artist Prerequisites: None Duration: 1-2 minutes

Navigate to Profile

Entry Points:

  • Click artist avatar
  • Click artist name (when underlined)
  • URL: /profile/[identifier]

Profile Sections

Header:

┌──────────────────────────────┐
│    [Avatar]                  │
│    DJ Example                │
│    "Making beats daily"      │
│                              │
│  📍 Los Angeles, CA          │
│  🎵 12 tracks                │
│  👥 234 followers (future)   │
└──────────────────────────────┘

Bio Section:

About
─────
Producer and DJ from LA, specializing 
in trap and hip-hop beats. Available 
for custom work and collaborations.

[Instagram] [SoundCloud] [Twitter]

Recent Tracks:

Recent Uploads
──────────────
[Track] [Track] [Track] [Track]
        View All →

Social Actions (Future)

Planned Features:

  • Follow artist
  • Send message
  • Book for collaboration
  • Tip directly (STX/BTC)

Flow 10: Editing Your Profile

Goal: Update profile information Prerequisites: Authenticated Duration: 2-3 minutes

Navigate to Own Profile

Access:

  • Click avatar in header → "My Profile"
  • URL: /profile/me redirects to /profile/[wallet]

Edit Profile Button

Location: Top-right of profile when viewing own Button: "Edit Profile" (pencil icon)

Profile Edit Modal

Sections:

Basic Information

Display Name*
[DJ Example_______________]

Tagline (40 chars)
[Making beats daily_______]

Bio (350 chars)
[Producer and DJ from LA,
specializing in trap and
hip-hop beats...]

[Save Changes]

Avatar Upload

Profile Image
┌──────────┐
│  Current │ [Change Photo]
│  Avatar  │
└──────────┘

Drag & drop or choose file
Max 5MB • Square recommended

Social Links (Future)

Social Links
├─ Instagram: [@djexample____]
├─ SoundCloud: [/djexample___]
├─ Twitter: [@djexample_____]
└─ + Add Link

Save Changes

Process:

// Update profile in database
await supabase
  .from('user_profiles')
  .upsert({
    wallet_address: walletAddress,
    display_name: formData.name,
    tagline: formData.tagline,
    bio: formData.bio,
    avatar_url: uploadedImageUrl,
    social_links: formData.socialLinks,
    updated_at: new Date()
  });

// Update local ProfileContext
updateProfile(newProfileData);

// Close modal
onClose();

Success:

  • Changes reflect immediately
  • No page refresh needed
  • Toast: "Profile updated!"

Related Skills

  • mixmi-component-library - UI components used in flows
  • mixmi-design-patterns - Visual patterns for extending flows
  • mixmi-payment-flow - Detailed payment implementation
  • mixmi-database-schema - Data structures behind flows