François Castets

CréationsWork Plateforme sur mesureBespoke platform

Plateforme sur mesure · Place de marché, musique électroniqueBespoke platform · Marketplace, electronic music

djplays, la place de marchédjplays, the marketplace

Une place de marché où les producteurs de musique électronique paient de vrais DJs pour écouter leur inédit, et reçoivent la preuve horodatée quand il est joué.A marketplace where electronic music producers pay real DJs to listen to their unreleased track, and receive timestamped proof when it gets played.

Aperçu du site djplays, la place de marché

Les notes de ce chantierNotes from this build

Un DJ reçoit cinquante promos par jour et n’en répond aucune. djplays renverse l’échange : le DJ est payé pour écouter, il répond sous sept jours, et s’il joue le titre en set, en stream ou en radio, le producteur reçoit l’extrait horodaté qui le prouve. Tout est construit à la main, sans framework, sans WordPress et sans la moindre dépendance externe.A DJ gets fifty promos a day and answers none of them. djplays turns the exchange around: the DJ is paid to listen, answers within seven days, and if they play the track in a set, a stream or on radio, the producer receives the timestamped clip that proves it. Everything is built by hand, with no framework, no WordPress and not a single external dependency.

Le défi techniqueThe technical challenge

Reverser de l’argent à des tiers change la nature du projet. djplays n’encaisse pas pour son compte : il est l’agent commercial des DJs. Chaque commande payée doit donc émettre une facture au nom du DJ, pas au nom de la plateforme, et la commission doit faire l’objet d’une facture distincte, réglée par compensation sur les sommes encaissées. Ce n’est pas une subtilité comptable que l’on ajoute à la fin : c’est une contrainte qui descend jusqu’au schéma de la base.Paying money out to third parties changes the nature of a project. djplays does not collect on its own behalf: it acts as the DJs commercial agent. Every paid order must therefore issue an invoice in the DJ name, not the platform name, and the commission must be a separate invoice, settled by offset against the sums collected on their behalf. This is not an accounting subtlety bolted on at the end: it is a constraint that reaches all the way down into the database schema.

La promesse tient en un mot : la preuve. Pas un avis, pas un ajout en playlist, mais un passage devant un vrai public. Or une promesse que le code ne sait pas vérifier n’est pas une promesse. Il a fallu la rendre mécanique : le formulaire de réponse ne se déverrouille qu’après trente secondes réellement écoutées, un passage se prouve par un extrait, une tracklist ou un lien de mix, l’équipe vérifie sous 48 h, et un passage invérifiable n’est jamais facturé.The promise comes down to one word: proof. Not an opinion, not a playlist add, but a play in front of a real audience. And a promise the code cannot verify is not a promise. It had to be made mechanical: the reply form only unlocks after thirty seconds genuinely played, a play is proven by a clip, a tracklist or a mix link, the team verifies within 48 hours, and an unverifiable play is never billed.

Sur une place de marché, laisser le vendeur fixer son prix est la liberté évidente. Le laisser le fixer sans limite ruine la confiance de l’acheteur. djplays fait les deux à la fois : chaque DJ règle son prix, la plateforme le plafonne selon son audience vérifiée. Trois paliers, un plancher à 1 euro, un plafond de passage qui vaut trois fois le plafond d’écoute, des réglages par pas de 0,50 euro et un seul changement par mois.On a marketplace, letting the seller set their price is the obvious freedom. Letting them set it without limit destroys the buyer trust. djplays does both at once: each DJ sets their price, the platform caps it according to their verified audience. Three tiers, a floor of 1 euro, a play cap worth three times the listen cap, adjustments in steps of 0.50 euro and a single change per month.

Dernier défi, le moins visible : une commande passée ne doit jamais être recalculée. Un DJ qui change de prix, un palier qui baisse, une grille tarifaire qui évolue — rien de tout cela ne peut modifier une facture déjà émise. Le calcul à la volée, si pratique à l’affichage, est ici une faute : il réécrit le passé à chaque consultation.The last challenge is the least visible: an order already placed must never be recalculated. A DJ changing their price, a tier going down, a pricing grid evolving — none of that can alter an invoice already issued. Calculating on the fly, so convenient for display, is a mistake here: it rewrites the past every time someone looks at it.

Comment c'est construitHow it is built

PHP 8 écrit à la main, sans framework et sans WordPress : 38 555 lignes de PHP et 6 154 lignes de JavaScript et de CSS. Pas de dossier vendor, pas de composer.json, aucune dépendance externe. Stripe, l’API Claude et la voix off sont appelés en curl direct. Le déploiement est une copie de fichiers, et rien ne casse le jour où un paquet tiers change d’avis.PHP 8 written by hand, with no framework and no WordPress: 38,555 lines of PHP and 6,154 lines of JavaScript and CSS. No vendor directory, no composer.json, no external dependency at all. Stripe, the Claude API and the voice-over are called with plain curl. Deployment is a file copy, and nothing breaks the day a third-party package changes its mind.

SQLite, dans un fichier placé hors de la racine web : 35 tables, 61 index, 17 Mo. Le schéma est créé au premier appel et versionné par PRAGMA user_version, avec 35 étapes de migration dans le code — chacune rejouable sans dégât. Une base qui tient dans un fichier se sauvegarde en le copiant, et se restaure de même.SQLite, in a file placed outside the web root: 35 tables, 61 indexes, 17 MB. The schema is created on first call and versioned by PRAGMA user_version, with 35 migration steps in the code, each one safe to replay. A database that fits in one file is backed up by copying it, and restored the same way.

Chaque envoi fige à la commande son palier et ses sept montants : prix d’écoute, part du DJ, commission, puis les mêmes pour le passage. Le partage est arrondi au centime le plus proche, demi-centime vers le haut, et la commission est toujours le reste, de sorte que part plus commission égale le prix exactement. Aucune de ces valeurs n’est recalculée après coup.Each send freezes its tier and its seven amounts at order time: listen price, DJ share, commission, then the same for the play. The split is rounded to the nearest cent, half-cent upwards, and the commission is always the remainder, so share plus commission equals the price exactly. None of these values is ever recalculated afterwards.

Huit tâches planifiées font tourner la plateforme quand personne ne regarde : échéances et relances chaque heure, recrutement des DJs toutes les quinze minutes, puis nettoyage, sauvegarde, versements, rapport quotidien, et le classement hebdomadaire du lundi matin. Ce sont des scripts PHP en ligne de commande, sur le même code que le site, chacun avec son propre journal.Eight scheduled tasks keep the platform running when nobody is watching: deadlines and reminders every hour, DJ recruitment every fifteen minutes, then cleanup, backup, payouts, the daily report, and the weekly ranking on Monday morning. They are command-line PHP scripts, running on the same code as the site, each with its own log.

Les fonctionnalités développéesThe features built

  • Dépôt d’un inédit en MP3 ou WAV, qui reste privé : seuls les DJs choisis l’entendent, et le nom du producteur reste masqué jusqu’à leur réponse.Upload of an unreleased track as MP3 or WAV, kept private: only the chosen DJs hear it, and the producer name stays hidden until they reply.
  • Sélection des DJs par style, BPM, canal et audience — ou bien un budget, et une sélection recommandée que le producteur modifie librement, sans jamais dépasser son montant.DJ selection by style, BPM, channel and audience — or else a budget, and a recommended selection the producer edits freely, never going over their amount.
  • Un catalogue d’environ deux cents styles rangés en quinze familles : un titre n’atteint que les DJs qui affichent son style et sa fourchette de BPM.A catalogue of around two hundred styles sorted into fifteen families: a track only reaches DJs who list its style and its BPM range.
  • Formulaire de réponse déverrouillé après trente secondes réellement écoutées, deux lignes minimum, sous sept jours — sinon le crédit revient automatiquement.Reply form unlocked after thirty seconds genuinely played, two lines minimum, within seven days — otherwise the credit is returned automatically.
  • Preuve de passage par extrait, tracklist ou lien de mix, vérifiée par l’équipe sous 48 h sur six canaux : Twitch, radio, club, Mixcloud et SoundCloud, YouTube, festival.Play proof by clip, tracklist or mix link, verified by the team within 48 hours across six channels: Twitch, radio, club, Mixcloud and SoundCloud, YouTube, festival.
  • Badge public à jeton, et widget en image, iframe ou PNG qui se met à jour tout seul à chaque nouveau passage prouvé, partout où il a été collé.Public token badge, plus a widget as an image, an iframe or a PNG that updates itself with every newly proven play, everywhere it has been pasted.
  • Visuels partageables dessinés par le serveur en trois formats, et une vidéo montée par le studio pour Reels et TikTok.Shareable visuals drawn by the server in three formats, plus a video edited by the studio for Reels and TikTok.
  • Classement hebdomadaire publié le lundi, un par famille de styles, chaque passage cliquable et vérifiable.Weekly ranking published on Monday, one per style family, every play clickable and verifiable.
  • Espace DJ complet : boîte de réception filtrée, dépôt de preuve, gains, versements, paliers, et un kit promo à son nom avec QR code.Full DJ area: filtered inbox, proof upload, earnings, payouts, tiers, and a promo kit in their name with a QR code.
  • Facturation sous mandat au nom de chaque DJ, numérotation continue par année, avoirs en cas de remboursement, et déclaration DAC7 des revenus versés.Invoicing under mandate in each DJ name, continuous yearly numbering, credit notes on refunds, and DAC7 reporting of the income paid out.
  • Anti-spam sans service tiers : preuve de travail calculée par le navigateur, rien à cocher, aucun cookie en plus, aucune donnée qui sort du domaine.Anti-spam with no third-party service: proof of work computed by the browser, nothing to tick, no extra cookie, no data leaving the domain.
  • Application web installable, bilingue français et anglais, utilisable depuis le téléphone sans rien installer.Installable web app, bilingual French and English, usable from a phone with nothing to install.

Les technologies employéesThe technologies used

  • PHP 8 sur mesure — types stricts, expressions match, retours typés. Aucun framework, aucune bibliothèque tierce, aucun Composer : tout ce qui tourne a été écrit pour ce projet.Bespoke PHP 8 — strict types, match expressions, typed returns. No framework, no third-party library, no Composer: everything running here was written for this project.
  • SQLite — base dans un fichier hors de la racine web, schéma versionné par PRAGMA user_version et migré en 35 étapes rejouables. 35 tables et 61 index.SQLite — database in a file outside the web root, schema versioned with PRAGMA user_version and migrated in 35 replayable steps. 35 tables and 61 indexes.
  • Stripe — paiement et webhook appelés en HTTP direct, événements journalisés en base pour que le même message reçu deux fois ne produise jamais deux effets.Stripe — payment and webhook called over plain HTTP, events logged in the database so the same message received twice never produces two effects.
  • GD — badges et visuels dessinés côté serveur en story 1080×1920, carré 1080×1080 et Open Graph 1200×630, texte vectoriel avec les polices embarquées, résultats mis en cache.GD — badges and visuals drawn server-side as 1080×1920 story, 1080×1080 square and 1200×630 Open Graph, vector text with embedded fonts, results cached.
  • API Claude — lecture assistée des preuves d’audience fournies par un DJ : plateforme reconnue, audience lue, cohérence, palier suggéré. Une aide pour l’équipe, jamais une décision, et plafonnée au mois.Claude API — assisted reading of the audience proofs a DJ submits: platform recognised, audience read, consistency, suggested tier. An aid for the team, never a decision, and capped monthly.
  • Preuve de travail maison — anti-spam sur le principe d’ALTCHA : défi signé par le serveur, empreinte SHA-256 cherchée par le navigateur, défi à usage unique et valable deux heures.Homemade proof of work — anti-spam on the ALTCHA principle: challenge signed by the server, SHA-256 hash searched by the browser, single-use challenge valid for two hours.
  • PWA — manifeste, service worker et icônes générées par script. Application installable, bilingue, servie par des adresses lisibles portées par de vrais dossiers.PWA — manifest, service worker and script-generated icons. Installable app, bilingual, served from readable addresses backed by real directories.

Ce que j'en retiensWhat I take from it

La partie la plus longue à écrire n’a pas été le paiement, ni le classement, ni même les badges : c’est le courrier. Le module qui compose les messages transactionnels pèse à lui seul 123 Ko, le plus gros fichier du projet. Une place de marché où deux parties s’attendent mutuellement est d’abord une machine à écrire au bon moment — la relance qui part trop tôt agace, celle qui part trop tard fait perdre la commande.The longest part to write was not the payment, nor the ranking, nor even the badges: it was the mail. The module that composes transactional messages weighs 123 KB on its own, the largest file in the project. A marketplace where two sides wait on each other is first of all a machine for writing at the right moment — a reminder sent too early irritates, one sent too late loses the order.

Le second apprentissage tient à l’amorçage. Une place de marché sans vendeurs n’a rien à offrir aux acheteurs, et il fallait donc des DJs avant d’avoir des producteurs. Le repérage s’est révélé être un travail de données plutôt que de commerce : savoir quel DJ joue quel style, sur quel canal, devant quelle audience. Sans cela, l’offre n’est qu’un annuaire. Une tâche tourne toutes les quinze minutes pour l’entretenir, et la table de recrutement compte aujourd’hui 34 733 DJs repérés.The second lesson is about bootstrapping. A marketplace with no sellers has nothing to offer buyers, so DJs had to come before producers. Finding them turned out to be a data problem rather than a sales one: knowing which DJ plays which style, on which channel, in front of which audience. Without that, the supply side is just a directory. A task runs every fifteen minutes to maintain it, and the recruitment table now holds 34,733 identified DJs.

La plateforme est en accès anticipé. Ce qui est en ligne est complet de bout en bout — dépôt, sélection, écoute, réponse, preuve, facture, versement, classement — mais l’ouverture se fait par invitation, et c’est volontaire : une place de marché se juge sur la qualité des premiers échanges, pas sur le nombre d’inscrits.The platform is in early access. What is online is complete end to end — upload, selection, listen, reply, proof, invoice, payout, ranking — but opening up is by invitation, and that is deliberate: a marketplace is judged on the quality of its first exchanges, not on its sign-up count.

Dans le même genreIn the same vein

Voir les 42 créationsSee all 42 projects · Comment je travailleHow I work · Ce qu'en disent mes clientsWhat my clients say