Skip to content

03 - Domain Models

Overview

Wavic's domain model represents a hierarchical music production management system. The core entities form a tree structure: Artists → Projects → Tracks. Entities use a tiered URL identifier system (shortId/slug) for clean URLs — see API-DESIGN.md.

Entity Hierarchy

┌─────────────────────────────────────────────────────────────┐
│                         USER (IUser)                        │
│   - Owns multiple artist spaces                             │
│   - Has subscription with storage limits                    │
└─────────────────────┬───────────────────────────────────────┘
                      │ owns

┌─────────────────────────────────────────────────────────────┐
│                    ARTIST SPACE (TArtist)                   │
│   - Top-level container (artist/band)                       │
│   - Contains multiple projects                              │
│   - Has collaborators with roles                            │
└─────────────────────┬───────────────────────────────────────┘
                      │ contains

┌─────────────────────────────────────────────────────────────┐
│                      PROJECT (TProject)                     │
│   - Album, EP, Single, etc.                                 │
│   - Contains multiple tracks                                │
│   - Inherits collaborators from artist                      │
└─────────────────────┬───────────────────────────────────────┘
                      │ contains

┌─────────────────────────────────────────────────────────────┐
│                       TRACK (TTrack)                        │
│   - Individual song/recording                               │
│   - Has audio versions (stems, mixes)                       │
│   - Has attachments (files, documents)                      │
│   - Has comments on waveform                                │
└─────────────────────────────────────────────────────────────┘

Core Types

User (IUser)

Represents an authenticated user with subscription information.

typescript
// types/user.ts
export interface IUser {
  _id: string;
  fullName: string;
  username: string;
  email: string;
  image: string;
  isCreatedByInvitation: boolean;
  spaceUsed: number;
  recentSearches: string[];
  subscription: {
    name: string; // Plan name (Free, Pro, etc.)
    storageMB: number; // Total storage limit
    seats: number; // Team seat limit
    occupiedStorageMB: number; // Used storage
    occupiedSeats: number; // Used seats
    isActive: boolean; // Subscription active
    periodStartsAt?: Date;
    periodEndsAt?: Date;
    stripeSubscriptionId?: string;
    stripeCustomerId?: string;
    stripeProductId?: string;
    isFreeTrial?: boolean;
    hasBeenFreeTrial?: boolean;
  };
}

Artist Space (TArtist)

Top-level container representing an artist or band's workspace.

typescript
// types/artist.ts
export type TArtist = {
  _id: string;
  shortId?: string; // Auto-generated 6-char identifier (nanoid)
  slug?: string; // User-customizable URL slug (premium)
  slugType?: 'auto' | 'premium';
  name: string; // Artist/band name
  type: string; // Type identifier
  image: string; // Profile image URL
  collaborators: TCollaborator[]; // Team members
  owner: string; // Owner user ID
  sharedLinkRole?: string; // Default role for shared links
  lastAccessedAt?: Date; // Last access timestamp
};

Project (TProject)

Container for related tracks (album, EP, single).

typescript
// types/artist.ts
export interface IProject<TArtist, TOwner> {
  _id: string;
  shortId?: string; // Auto-generated 6-char identifier
  slug?: string; // User-customizable URL slug
  slugType?: 'auto' | 'premium';
  name: string; // Project name
  artistSpace: TArtist; // Parent artist space
  type: string; // Single, EP, Album, etc.
  image: string; // Cover image URL
  collaborators: TCollaborator[]; // Project-level team
  owner: TOwner; // Owner (user or ID)
  sharedLinkRole?: string; // Sharing permission
  lastAccessedAt?: Date;
}

// Simplified version with string references
export type TProject = {
  _id: string;
  shortId?: string;
  slug?: string;
  slugType?: 'auto' | 'premium';
  name: string;
  artistSpace: TArtist; // Populated artist
  type: string;
  image: string;
  collaborators: TCollaborator[];
  owner: string; // Owner user ID
  sharedLinkRole?: string;
  lastAccessedAt?: Date;
};

Track (TTrack)

Individual song with audio versions, metadata, and collaboration features.

typescript
// types/track.ts
export type TTrack = {
  id?: string; // Normalized ID
  _id?: string; // MongoDB ID
  shortId?: string; // Auto-generated 6-char identifier
  slug?: string; // User-customizable URL slug
  slugType?: 'auto' | 'premium';
  name: string; // Track title
  isFinalName: boolean; // Name finalized
  finalNameUpdatedAt: string;

  // Relations
  artistSpace: TArtist; // Parent artist
  project: TProject; // Parent project
  collaborators: TCollaborator[]; // Track collaborators
  owner: IUser; // Track owner

  // Audio
  audio: TFile[]; // Audio versions (mixes, stems)
  audioFinal: string | null; // Final version URL
  audioUpdatedAt: string;

  // Artwork
  image: TFile[]; // Cover images
  imageFinal: string | null; // Final image URL
  imageUpdatedAt: string;

  // Metadata
  type: string; // Track type
  status: string; // Production status
  order?: number; // Display order
  releaseDate?: Date;
  genre?: string;
  mainArtists?: string;
  label?: string;
  ISRC?: string; // International Standard Recording Code
  UPC?: string; // Universal Product Code
  notes?: string;

  // Additional data
  credits: any; // Production credits
  attachments: any; // Attached files
  sharedLinkRole?: string;
  lastAccessedAt?: Date;
};

File (TFile)

Represents uploaded files (audio, images, attachments).

typescript
// types/track.ts
export type TFile = {
  _id?: string;
  version?: number; // Version number
  s3Url: string; // AWS S3 URL
  type: string; // File type
  owner?: string; // Uploader user ID
  spaceOwner?: string; // Space owner ID
  project?: string; // Parent project ID
  track?: string; // Parent track ID
  artistSpace?: string; // Parent artist ID
  name?: string; // Original filename
  size?: number; // File size in bytes
  contentType?: string; // MIME type
  isFinalVersion?: boolean; // Marked as final
  comments: any[]; // Comments on this version
  createdAt?: string;
  updatedAt?: string;
};

Collaborator (TCollaborator)

Team member with role-based permissions.

typescript
// types/artist.ts
export type TCollaborator = {
  _id: string;
  userId: IUser; // User details
  role: keyof typeof ROLES; // Permission level
};

// config/constants.ts
export const ROLES = {
  Owner: 'owner',
  Admin: 'admin',
  Editor: 'editor',
  Viewer: 'viewer',
} as const;

Enums and Constants

Track Status

Production workflow stages:

typescript
// types/status.ts
export enum TrackStatus {
  NOT_STARTED = 'Not started',
  PRE_PRODUCTION = 'Pre-production',
  RECORDING = 'Recording',
  EDITING = 'Editing',
  MIXING = 'Mixing',
  MASTERING = 'Mastering',
  COMPLETED = 'Completed',
}

Layout Options

UI layout variants:

typescript
// config/enums.ts
export enum LAYOUT_OPTIONS {
  HYDROGEN = 'hydrogen',
  HELIUM = 'helium',
  LITHIUM = 'lithium',
  BERYLLIUM = 'beryllium', // Default
  BORON = 'boron',
  CARBON = 'carbon',
}

Project Types

typescript
// Common project types used:
type ProjectType = 'Single' | 'EP' | 'Album' | 'Mixtape' | 'Compilation';

Status Options

Track status with visual styling:

typescript
// config/constants.ts
export const TRACK_STATUS_OPTIONS: StatusOption[] = [
  { label: 'Not started', value: 'Not started', bgColor: 'bg-gray-300' },
  {
    label: 'Pre-production',
    value: 'Pre-production',
    bgColor: 'bg-yellow-600',
  },
  { label: 'Recording', value: 'Recording', bgColor: 'bg-purple-800' },
  { label: 'Editing', value: 'Editing', bgColor: 'bg-blue-700' },
  { label: 'Mixing', value: 'Mixing', bgColor: 'bg-yellow-800' },
  { label: 'Mastering', value: 'Mastering', bgColor: 'bg-pink-500' },
  { label: 'Completed', value: 'Completed', bgColor: 'bg-green-800' },
];

Role Permissions

┌─────────────────────────────────────────────────────────────┐
│                    ROLE PERMISSIONS                         │
├─────────────┬─────────┬─────────┬─────────┬────────────────┤
│  Action     │ Owner   │ Admin   │ Editor  │ Viewer         │
├─────────────┼─────────┼─────────┼─────────┼────────────────┤
│ View        │   ✅    │   ✅    │   ✅    │   ✅           │
│ Edit        │   ✅    │   ✅    │   ✅    │   ❌           │
│ Upload      │   ✅    │   ✅    │   ✅    │   ❌           │
│ Delete      │   ✅    │   ✅    │   ❌    │   ❌           │
│ Share       │   ✅    │   ✅    │   ❌    │   ❌           │
│ Manage Team │   ✅    │   ✅    │   ❌    │   ❌           │
│ Transfer    │   ✅    │   ❌    │   ❌    │   ❌           │
└─────────────┴─────────┴─────────┴─────────┴────────────────┘

Waveform Data Types

Used by the audio player and waveform visualization:

typescript
// src/app/shared/wave/data/wave-data.ts
export interface IComment {
  _id: string;
  text: string;
  time: number; // Position in seconds
  user: IUser;
  status: string;
  createdAt: string;
}

export interface IVersion {
  label: string; // Display name
  value: string; // Version ID
  name: string; // File name
}

export interface IWaveFormState {
  currentTime: number; // Current playback position
  totalTime: number; // Total duration
}

export interface VolumeState {
  volume: number; // Current volume (0-100)
  lastVolume: number; // Volume before mute
}

Search Types

typescript
// types/search-items.ts
export interface SearchItem {
  _id: string;
  name: string;
  type: 'artist' | 'project' | 'track';
  image?: string;
  artistSpace?: string;
  project?: string;
}

Notification Types

typescript
// types/notification.interface.ts
export interface INotification {
  _id: string;
  type: string;
  message: string;
  read: boolean;
  createdAt: string;
  data?: any;
}

Ctrl-Audio Platform Documentation