DEV Community

Deepto
Deepto

Posted on

Deejay - Request Songs Through Email

Image description
This is a submission for the Postmark Challenge: Inbox Innovators.

What I Built

I built Deejay, a system where people can request songs by simply sending an email with an youtube link. The email gets processed, the song is fetched from YouTube using the YoutubeAPI, and it appears in a real-time DJ console for approval. The UI allows the DJ to accept the request and play/queue it or reject it.

Demo

Code Repository

How I Built It

The Architecture Journey

Starting Simple: Email → Queue

The core concept was straightforward:

  1. Receive email with song request
  2. Parse the content (YouTube link or search query)
  3. Add to a queue
  4. Let the DJ manage it

Tech Stack Decisions

Backend: Express.js + TypeScript

// Clean, typed API endpoints
app.post('/api/queue/:id/approve', async (req, res) => {
  const { id } = req.params;
  const song = await queue.update(id, { status: 'approved' });
  io.emit('queue-update', { queue: await queue.list() });
  res.json({ success: true, song });
});
Enter fullscreen mode Exit fullscreen mode

Real-time Updates: Socket.IO

// Instant updates to all connected clients
io.on('connection', (socket) => {
  socket.emit('now-playing', playerState.getNowPlaying());
  socket.emit('queue-update', { queue: await queue.list() });
});
Enter fullscreen mode Exit fullscreen mode

Frontend: React + TypeScript + Tailwind

// Clean, responsive DJ console
function QueueItem({ song, onApprove, onReject }) {
  return (
    <div className="flex items-center gap-4 p-4 border rounded-lg">
      <img src={song.thumbnail} className="w-16 h-16 rounded" />
      <div className="flex-1">
        <h3 className="font-semibold">{song.title}</h3>
        <p className="text-sm text-gray-600">{song.artist}</p>
      </div>
      <div className="flex gap-2">
        <Button onClick={() => onApprove(song.id)}></Button>
        <Button onClick={() => onReject(song.id)}></Button>
      </div>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

The Email Processing Magic

The most interesting part was processing emails reliably. I used Postmark's inbound email service:

// Email webhook processor
router.post('/webhook', async (req, res) => {
  const { content, requester } = extractEmailContent(req.body);

  // Detect YouTube link or search query
  const videoId = detectYouTubeLink(content);
  let songData;

  if (videoId) {
    songData = await youtube.getVideoDetails(videoId);
  } else {
    songData = await youtube.search(content);
  }

  const song = {
    id: uuidv4(),
    title: songData.title,
    requester,
    status: 'pending',
    submittedAt: new Date()
  };

  await queue.push(song);
  io.emit('queue-update', { newSong: song });
});
Enter fullscreen mode Exit fullscreen mode

Top comments (0)