Aller au contenu

← Retour au projet sur l'accueil

RapCongolais242

En ligne · Accès public

RapCongolais242

Un blog qui met en avant des artistes congolais du pays et de la diaspora : leur parcours, leur musique et leurs images grâce à des clips vidéo, le tout sur un seul site, avec un paiement pour accéder à des exclusivités introuvables ailleurs. La démo montre un lecteur aux sons générés dans votre navigateur et les parcours d'abonnement, sans paiement réel.

Essayer la démoVoir le site (s'ouvre dans un nouvel onglet)

Client
Projet personnel
Rôle
Conception et développement, seul
RapCongolais242

Le lecteur qui ne s'arrête jamais

RapCongolais242RapCongolais242En ligneSimulation · données fictives
Qu'est-ce qui est réel ?

Simulation construite sur le code de RapCongolais242, données fictives.

Code réel
La logique de file d'attente (aléatoire, suivant, précédent, fin d'un titre, boucle à trois états) est extraite du lecteur de RapCongolais242, comportement inchangé.
Données fictives
Les trois artistes et les sept titres sont inventés, et les sons sont synthétisés dans votre navigateur : aucun morceau réel, aucune pochette, aucun artiste de tiers.
Illustration ajoutée
Les deux parcours d'abonnement sont une illustration construite à partir du modèle de données de l'application. Aucun paiement n'est simulé ni effectué.
RapCongolais242
RapCongolais242

RapCongolais242

La démo ne se charge que si vous la demandez.

  1. 01

    Le problème

    Un service de musique pour ce public doit résoudre trois choses à la fois. L'écoute ne doit pas s'arrêter quand on circule dans le site. Le paiement doit fonctionner pour les auditeurs à l'étranger comme pour ceux du pays. Et les médias doivent être stockés et servis sans alourdir l'application ni les connexions lentes.

  2. 02

    Un lecteur en dehors des pages

    Le lecteur vit au-dessus des pages, avec une seule file d'attente pour tout le site. La file se construit selon la liste que vous lancez : le catalogue, une playlist, la discographie d'un artiste. La lecture aléatoire et la boucle sont intégrées, et la boucle a trois états : aucune, toute la file, un seul titre.

    Sous le capot

    Lancer une liste construit la file ; la fin d'un titre passe au suivant, ou reboucle.

    Fichier : RapCongolais242 · src/context/PlayerContext.tsx · lignes 92 à 118

      const playQueue = useCallback((tracks: PlayerTrack[], startIndex = 0) => {    const trackVise = tracks[startIndex];    if (currentTrack?.id === trackVise?.id) {      const audio = audioRef.current;      if (!audio) return;      if (audio.paused) audio.play(); else audio.pause();      return;    }    setQueueOriginale(tracks);    setQueue(aleatoire ? melanger(tracks) : tracks);    setIndexActuel(startIndex);  }, [aleatoire, currentTrack]);   const suivant = useCallback(() => {    setIndexActuel((i) => (i + 1 < queue.length ? i + 1 : 0));  }, [queue.length]);   const precedent = useCallback(() => {    setIndexActuel((i) => (i > 0 ? i - 1 : queue.length - 1));  }, [queue.length]);   const avancerAutomatiquement = useCallback(() => {    setIndexActuel((i) => {      if (i + 1 < queue.length) return i + 1;      return boucle === "file" ? 0 : i;    });  }, [queue.length, boucle]);

    Code réel du projet, copié et anonymisé.

  3. 03

    Deux voies de paiement

    PayPal sert le public international. Pour le marché local, les paiements Mobile Money et Wave sont validés à la main : l'auditeur déclare une référence, la demande attend, un administrateur décide. Chaque voie garde sa propre traçabilité.

    Sous le capot

    La demande manuelle : quel service a servi, quelle formule, quelle référence, et la décision.

    Fichier : RapCongolais242 · prisma/schema.prisma · lignes 209 à 229

    model ManualPaymentRequest {  id            String                @id @default(cuid())  userId        String  provider      ManualPaymentProvider  plan          PremiumPlan  phoneUsed     String  reference     String  screenshotUrl String?  status        ManualPaymentStatus   @default(PENDING)  rejectReason  String?  createdAt     DateTime              @default(now())  reviewedAt    DateTime?   user User @relation(fields: [userId], references: [id], onDelete: Cascade)} enum ManualPaymentProvider {  MTN_CONGO  AIRTEL_CONGO  WAVE_SENEGAL}

    Code réel du projet, copié et anonymisé.

  4. 04

    Des médias légers

    Les médias sont stockés sur Cloudflare R2. Les images récupérées automatiquement sont recadrées et compressées côté serveur, en qualité 85, avant d'être servies. Cette partie n'est pas dans la démo. Pas dans cette version : une stratégie globale de formats d'image modernes et un chargement différé systématique.

    Sous le capot

    Un recadrage carré centré quand l'image est nettement plus large que haute, puis un JPEG en qualité 85.

    Fichier : RapCongolais242 · src/lib/upload.ts · lignes 45 à 73

    export async function telechargerEtRecadrerCover(  urlSource: string,  dossier: "pochettes"): Promise<string | null> {  try {    const reponse = await fetch(urlSource);    if (!reponse.ok) return null;     const bufferOriginal = Buffer.from(await reponse.arrayBuffer());    const image = sharp(bufferOriginal);    const metadata = await image.metadata();     if (!metadata.width || !metadata.height) return null;     let imageFinale = image;     const ratio = metadata.width / metadata.height;    if (ratio > 1.15) {      const taille = metadata.height;      const decalageGauche = Math.round((metadata.width - taille) / 2);      imageFinale = image.extract({        left: decalageGauche,        top: 0,        width: taille,        height: taille,      });    }     const bufferFinal = await imageFinale.jpeg({ quality: 85 }).toBuffer();

    Code réel du projet, copié et anonymisé.

  5. 05

    Essayez vous-même

    Lancez un titre, changez de page, passez du catalogue à un artiste puis à la playlist, activez l'aléatoire et la boucle. Ouvrez ensuite la page d'abonnement pour suivre les deux voies de paiement et jouer l'administrateur. Les sons sont synthétisés dans votre navigateur : aucun morceau réel, et rien ne joue avant votre clic.

Ce que vous pouvez y faire

  • Lancer un titre, puis changer de page : la musique continue
  • Passer du catalogue à un artiste ou à une playlist : la file suit
  • Utiliser l'aléatoire, la boucle, le volume et le panneau de la file
  • Parcourir deux voies d'abonnement, PayPal et Mobile Money, sans aucun paiement réel
  • Écouter des sons générés dans votre navigateur : aucun titre réel n'est utilisé

Stack

Next.js 16 · TypeScript · Tailwind CSS v4 · Prisma 7 · Neon Postgres · NextAuth v5 · Cloudflare R2 · Vercel

Contexte

RapCongolais242 est un blog qui met en avant des artistes congolais du pays et de la diaspora : leur parcours, leur musique et leurs images grâce à des clips vidéo, le tout sur un seul site, avec un paiement pour accéder à des exclusivités introuvables ailleurs.

Le problème

Un service de musique pour ce public doit résoudre trois choses à la fois. L'écoute ne doit pas s'arrêter quand on circule dans le site. Le paiement doit fonctionner pour les auditeurs à l'étranger comme pour ceux du pays. Et les médias doivent être stockés et servis sans alourdir l'application ni les connexions lentes. Chacune de ces contraintes tirait l'architecture dans une direction différente.

Contraintes

  • Une partie du public écoute sur mobile avec une bande passante limitée
  • Le Mobile Money ne s'automatise pas simplement : le paiement local ne peut pas reposer sur une API de paiement
  • Les contenus d'artistes tiers doivent être gérés proprement

Ce que j'ai construit

  • Une page d'accueil avec l'artiste de la semaine et l'actualité
  • Des pages artistes : biographie, pays, style, nombre de titres, discographie, liens sociaux et note en étoiles
  • Des titres avec favoris, listes de lecture et mention du statut de droits sur chaque titre
  • Une page Clips alimentée par la playlist YouTube de la chaîne, du plus récent au plus ancien
  • Une page « Collaborons » pour les artistes : mise en avant, stratégie marketing, pitch et presse, shooting et visuels
  • Des comptes utilisateurs et un abonnement Premium
  • Un back-office complet pour créer, modifier et supprimer artistes, titres, albums, actualités et demandes

Décisions structurantes

  1. 01

    Un lecteur qui ne s'arrête jamais

    Le lecteur vit en dehors des pages, avec une seule file d'attente partagée par tout le site. La musique continue pendant que le visiteur navigue. La file se construit selon le contexte : le catalogue, une playlist ou la discographie d'un artiste. La lecture aléatoire et la boucle sont intégrées.

    Écarté

    Un lecteur logé dans chaque page. Il aurait coupé la musique à chaque navigation, ce qu'un site d'écoute ne peut pas se permettre.

  2. 02

    Deux voies de paiement, chacune avec sa propre traçabilité

    PayPal sert le public international. Pour le marché local, les paiements Mobile Money et Wave sont validés à la main. Chaque voie a son propre flux et sa propre traçabilité dans l'administration : on peut toujours suivre un paiement de la demande à la décision.

    Écarté

    Un flux unique pour tout le monde. Un seul prestataire aurait exclu soit les auditeurs de l'étranger, soit ceux du pays, puisque le Mobile Money ne s'automatise pas simplement.

  3. 03

    Médias sur Cloudflare R2, images traitées côté serveur

    Les médias sont stockés sur Cloudflare R2, qui parle le protocole S3, et les envois passent par des liens signés. Les images récupérées automatiquement sont recadrées et compressées côté serveur, en qualité 85, avant d'être servies.

    Écarté

    Pas dans cette version : une stratégie globale de formats d'image modernes comme WebP ou AVIF, et un chargement différé systématique.