<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Natasha Arroyo</title>
    <description>The latest articles on DEV Community by Natasha Arroyo (@a-xine).</description>
    <link>https://dev.to/a-xine</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3781953%2Ffd288b96-4ddf-4c8f-aadf-ca9b817ff9df.png</url>
      <title>DEV Community: Natasha Arroyo</title>
      <link>https://dev.to/a-xine</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/a-xine"/>
    <language>en</language>
    <item>
      <title>DJ.MODE: How to Create Your First Music Player Desktop App from Scratch Using Electron JS</title>
      <dc:creator>Natasha Arroyo</dc:creator>
      <pubDate>Sun, 22 Feb 2026 03:26:50 +0000</pubDate>
      <link>https://dev.to/up_min_sparcs/djmode-how-to-create-your-first-music-player-desktop-app-from-scratch-using-electron-js-3egf</link>
      <guid>https://dev.to/up_min_sparcs/djmode-how-to-create-your-first-music-player-desktop-app-from-scratch-using-electron-js-3egf</guid>
      <description>&lt;p&gt;This article was co-authored by &lt;a class="mentioned-user" href="https://dev.to/dayani_yani"&gt;@dayani_yani&lt;/a&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;I.Introduction&lt;br&gt;
II.Features of DJ.MODE&lt;br&gt;
III.The Core Architecture: Main vs. Renderer&lt;br&gt;
IV.Setting Up Your Project&lt;br&gt;
V.Crafting the UI (The Renderer)&lt;br&gt;
VI.Designing UI with CSS&lt;br&gt;
VII.Adding Logic (The Renderer)&lt;br&gt;
VIII.Launching Your App&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;I.Introduction&lt;/strong&gt; &lt;a&gt;&lt;/a&gt;&lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Building  desktop applications used to mean learning and mastering complex, platform specific languages like  C++ or Java. However, with Electron JS, you can build cross-platform desktop apps using the web tools you already know - HTML, CSS, and JavaScript. In this tutorial, we will build DJ.MODE, a retro styled music player that allows you to load and play local audio files directly from your desktop.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fazgix5pe9f53z8bvfh9y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fazgix5pe9f53z8bvfh9y.png" alt="DJ.MODE" width="496" height="319"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;II.Features of DJ.MODE&lt;/strong&gt;&lt;a&gt;&lt;/a&gt;&lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Local Audio Playback:&lt;/strong&gt; Play MP3 and other audio files seamlessly from your local storage.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Custom Playlist Support:&lt;/strong&gt; Load multiple tracks at once and navigate through them.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dynamic UI:&lt;/strong&gt; A pixel art inspired interface with a functional progress bar and playback controls.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;III.The Core Architecture: Main vs. Renderer&lt;/strong&gt;&lt;a&gt;&lt;/a&gt;&lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Before diving into the code, it is important to understand the “brain” and the “face” of an Electron app:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; &lt;strong&gt;Main Process:&lt;/strong&gt; The “brain” that interacts with your operating system.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Renderer Process:&lt;/strong&gt; The "face" of your app - the HTML and CSS that the user sees. Electron combines Chromium (the engine behind Chrome) and Node.js to make this possible.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjjxioac7iwtffe40lj9y.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjjxioac7iwtffe40lj9y.jpg" alt="Main vs. Renderer" width="800" height="1166"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;IV.Setting Up Your Project&lt;/strong&gt;&lt;a&gt;&lt;/a&gt;&lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;To use Electron, you first need Node.js (LTS version) installed from nodejs.org. Node.js includes npm, the tool that will download Electron for you.&lt;br&gt;
Windows &amp;amp; macOS&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;     Visit &lt;a href="//nodejs.org"&gt;nodejs.org&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;     Download the LTS (Long Term Support) version.&lt;/li&gt;
&lt;li&gt;     Run the installer and click "Next" until finished.
Once installed, open your terminal and run the following commands to initialize your project:
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;code&gt;Bash&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir DJ.MODE
cd DJ.MODE
npm init -y
npm install electron --save-dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Update your &lt;code&gt;package.json&lt;/code&gt; file to include  the start script:&lt;br&gt;
&lt;code&gt;JSON&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"scripts": {
  "start": "electron ."
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a &lt;code&gt;main.js&lt;/code&gt; file. This script tells Electron how to configure and display your application window.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;JavaScript&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const { app, BrowserWindow } = require('electron');
function createWindow() {
  const win = new BrowserWindow({//this will create a new window for our app
    width: 480,
    height: 300,
    frame: false,  //this removes the default window frame      
    resizable: false,    
    webPreferences: {//these will allow us to use Node.js features in our script.js
      nodeIntegration: true,
      contextIsolation: false
    }
  });
  win.setMenu(null);   //this removes the default menu bar
  win.loadFile('index.html'); //this will load our index.html
}
app.whenReady().then(createWindow);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;V.Crafting the UI (The Renderer)&lt;/strong&gt;&lt;a&gt;&lt;/a&gt;&lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Create a &lt;code&gt;index.html&lt;/code&gt; file and link the Press Start 2P font from Google Fonts for a pixelated look.&lt;br&gt;
&lt;code&gt;HTML&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
    &amp;lt;title&amp;gt;DJ&amp;gt;MODE&amp;lt;/title&amp;gt;
    &amp;lt;!--this is a google font link for a pixelated font--&amp;gt;
    &amp;lt;link href="https://fonts.googleapis.com/css2?family=Press+Start+2P&amp;amp;display=swap" rel="stylesheet"&amp;gt;
    &amp;lt;link rel="stylesheet" href="style.css"&amp;gt;&amp;lt;!--this links to our style.css--&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
    &amp;lt;div id="close-btn-container"&amp;gt;
        &amp;lt;button id="close-btn"&amp;gt;X&amp;lt;/button&amp;gt;&amp;lt;!--this button will be used to close the application--&amp;gt;
    &amp;lt;/div&amp;gt;
    &amp;lt;div class="main-player-wrapper"&amp;gt;
        &amp;lt;h1 id="app-title"&amp;gt;DJ.MODE&amp;lt;/h1&amp;gt;
        &amp;lt;h3 id="song-title"&amp;gt;NO TRACK LOADED&amp;lt;/h3&amp;gt;&amp;lt;!--default text--&amp;gt;
        &amp;lt;div class="progress-container" id="progress-container"&amp;gt;
            &amp;lt;div class="progress-bar" id="progress-bar"&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;!--this will be updated by our script.js--&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;div class="control-group"&amp;gt;
            &amp;lt;button id="prev-btn" class="ctrl-btn"&amp;gt;PREV&amp;lt;/button&amp;gt;
            &amp;lt;button id="play-pause-btn" class="ctrl-btn main-btn"&amp;gt;PLAY&amp;lt;/button&amp;gt;
            &amp;lt;button id="next-btn" class="ctrl-btn"&amp;gt;NEXT&amp;lt;/button&amp;gt; &amp;lt;!--these buttons will be handled by our script.js--&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;button id="upload"&amp;gt;LOAD PLAYLIST&amp;lt;/button&amp;gt; &amp;lt;!--this button will open a file dialog to load a playlist--&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;audio id="audio-player"&amp;gt;&amp;lt;/audio&amp;gt; &amp;lt;!--this will be our audio player--&amp;gt;
    &amp;lt;script src="script.js"&amp;gt;&amp;lt;/script&amp;gt; &amp;lt;!--this links to our script.js that will handle the logic of our player--&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;VI.Designing UI with CSS&lt;/strong&gt;&lt;a&gt;&lt;/a&gt;&lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Create a &lt;code&gt;style.css&lt;/code&gt; file.To make the app draggable without a standard frame, use -webkit-app-region: drag.&lt;br&gt;
&lt;code&gt;CSS&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;body {
    font-family: 'Press Start 2P', cursive;
    background-color: #011638;
    color: #EFF0F2;
    user-select: none;/*prevents text selection while dragging*/
    border-radius: 3px;
    overflow: hidden;
    border: 3px solid #EEC643;
/* this centers the content vertically and horizontally */
    padding: 0;
    margin: 0;
    text-align: center;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;    
    height: 100vh;
    box-sizing: border-box;         
    -webkit-app-region: drag; /*allows you to drag the window by clicking anywhere*/  
}
.main-player-wrapper {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    width: 100%;
    padding-top: 20px;
}
#close-btn-container {   /*this keeps the close button on the top right corner*/
    position: absolute;
    top: 15px;
    right: 20px;
    -webkit-app-region: drag;
    z-index: 10;
}
#close-btn {
    background:none;
    color: #EEC643;
    border:none;
    cursor:pointer;/*this makes the cursor a pointer when hovering over the buttons*/
    font-weight: bold;
    -webkit-app-region: no-drag;
}
#close-btn:hover {
    color: #ffe347;
}
.progress-container {
    background: #13284b;
    border-radius: 5px;
    cursor: pointer;
    margin: 10px 0;
    height: 6px;
    width: 70%;
    -webkit-app-region: no-drag;
}
.progress-bar {
    background: linear-gradient(to right, #EEC643,#ecd893);
    border-radius: 5px;
    height: 100%;
    width: 0%; /*this will be updated dynamically with our script.js*/
    box-shadow: 0 0 10px #0D21A1;
}
.control-group {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 20px;/*this adds space between the buttons*/
    margin: 10px 0;
    -webkit-app-region: no-drag;
}
.ctrl-btn {
    background: #EEC643;
    border: 1px solid #0D21A1;
    color: #011638;
    border-radius: 50%;
    width: 40px;
    height: 40px;
    font-size: 8px;
    cursor: pointer;
    transition: all 0.2s ease;
    display: flex;
    justify-content: center;
    align-items: center;
    -webkit-app-region: no-drag;
}
.main-btn {
    width: 55px;
    height: 55px;
    font-size: 10px;
    background: #EEC643;
    box-shadow: 0 0 15px #011638;
}
.ctrl-btn:hover {
    transform: scale(1.1);/*this makes the buttons grow when hovered*/
    box-shadow: 0 0 20px #0D21A1;
    background: #ffe347;
}
#upload {
    background: transparent;
    border: 1px dashed #EEC643;
    border-radius: 5px;
    padding: 5px 15px;
    font-size: 10px;
    color: #d6af2e;
    cursor: pointer;
    -webkit-app-region: no-drag;
    margin-top: 5px;
}
#app-title {
    font-size: 25px;
    letter-spacing: 2px;
    color:#EEC643;
    margin: 5px 0;
}
#song-title {
    font-size: 15px;
    margin-bottom: 10px;
    max-width: 80%;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;/*this will add "..." if the title is too long*/
    line-height: 1.5;
}
audio { display: none; }/*this hides the default audio controls
                        since we are making our own custom controls*/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;VII.Adding Logic (The Renderer)&lt;/strong&gt;&lt;a&gt;&lt;/a&gt;&lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;In &lt;code&gt;script.js&lt;/code&gt;, we handle the audio logic. A key feature is using URL.createObjectURL(file) to create a temporary link to your local music files so the browser engine  can play them.&lt;br&gt;
&lt;code&gt;JavaScript&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const { ipcRenderer } = require('electron');
//these references to the HTML elements in our index.html
const audio = document.getElementById('audio-player');
const playBtn = document.getElementById('play-pause-btn');
const songTitle = document.getElementById('song-title');
const progressBar = document.getElementById('progress-bar');
const progressContainer = document.getElementById('progress-container');
const uploadBtn = document.getElementById('upload');
const closeBtn = document.getElementById('close-btn');
let playlist = [];//this will store the list of uploaded songs
let currentTrackIndex = 0;//this is to keep track of the current song playing
uploadBtn.addEventListener('click', () =&amp;gt; {//this will trigger the file input dialog when the upload button is clicked
    const input = document.createElement('input');
    input.type = 'file';
    input.accept = 'audio/*';
    input.multiple = true;
    input.onchange = (e) =&amp;gt; {
        playlist = Array.from(e.target.files);//this will store the selected files in the playlist array
        if (playlist.length &amp;gt; 0) {
            currentTrackIndex = 0;
            loadAndPlay(currentTrackIndex);//this will load and play the first selected song
        }
    };
    input.click();//this will open the file dialog
});
function loadAndPlay(index) {//this function will load and play the song at the given index in the playlist
    if (playlist.length &amp;gt; 0) {
        const file = playlist[index];
        const url = URL.createObjectURL(file);/*this will create a temporary URL for the selected file
        so that we can play it in the audio element*/
        audio.src = url;//this will set the audio source to the selected file
        songTitle.innerText = file.name.toUpperCase();
        audio.play();//this will start playing the song
        playBtn.innerText = "PAUSE";//this will show "PAUSE"on the button when the song is playing
    }
}
playBtn.addEventListener('click', () =&amp;gt; {
    if (!audio.src) return; //this will not do anything if no song is loaded 
    if (audio.paused) {
        audio.play();
        playBtn.innerText = "PAUSE";//this will show "PAUSE" on the button when the song is playing
    } else {
        audio.pause();
        playBtn.innerText = "PLAY";//while this will show "PLAY" on the button when the song is paused
    }
});
document.getElementById('next-btn').addEventListener('click', () =&amp;gt; {
    if (playlist.length &amp;gt; 0) {
        currentTrackIndex = (currentTrackIndex + 1) % playlist.length;//this will move to the next song in the playlist, and loop back to the first song if we are at the end
        loadAndPlay(currentTrackIndex);
    }
});
document.getElementById('prev-btn').addEventListener('click', () =&amp;gt; {
    if (playlist.length &amp;gt; 0) {
        currentTrackIndex = (currentTrackIndex - 1 + playlist.length) % playlist.length;//this will move to the previous song in the playlist, and loop to the last song if we are at the beginning
        loadAndPlay(currentTrackIndex);
    }
});
audio.addEventListener('ended', () =&amp;gt; {//this will automatically play the next song when the current song ends
    if (playlist.length &amp;gt; 0) {
        currentTrackIndex = (currentTrackIndex + 1) % playlist.length;
        loadAndPlay(currentTrackIndex);
    }
});
audio.addEventListener('timeupdate', () =&amp;gt; {//this will update the progress bar as the song plays
    if (audio.duration) {
        const progressPercent = (audio.currentTime / audio.duration) * 100;//this will calculate the percentage of the song that has played
        progressBar.style.width = `${progressPercent}%`;//this will set the width of the progress bar based on the percentage of the song that has played
    }
});
progressContainer.addEventListener('click', (e) =&amp;gt; {//this will allow the user to seek to a different part of the song by clicking on the progress bar
    if (!audio.src) return;
    const width = progressContainer.clientWidth;//this will get the width of the progress container
    const clickX = e.offsetX;//this will get the X coordinate of the click relative to the progress container
    const duration = audio.duration;
    audio.currentTime = (clickX / width) * duration;//this will set the current time of the audio based on where the user clicked on the progress bar
});
closeBtn.addEventListener('click', () =&amp;gt; {
    window.close(); //this will close the application when the close button is clicked
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;VII.Launching Your App&lt;/strong&gt;&lt;a&gt;&lt;/a&gt;&lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;To see your creation in action, go back to your terminal and run&lt;br&gt;
&lt;code&gt;Bash&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see a window pop up! Click the "Load Playlist" button, pick one or multiple MP3 from your computer, and enjoy your hand-built music player.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion:&lt;/strong&gt;&lt;br&gt;
You have just built a functional desktop app using the same tools used to create or build websites. However this is just the beginning of your project, you can continue to expand your desktop app by adding more advanced features and other customized functions to enhance user experience. &lt;/p&gt;

&lt;p&gt;Check out these Tutorials:&lt;br&gt;
&lt;a href="https://youtu.be/IzONNPX-tE4" rel="noopener noreferrer"&gt;The BEST way to Create Desktop Apps (Electron)&lt;/a&gt;&lt;br&gt;
&lt;a href="https://youtu.be/xANFxglaAps" rel="noopener noreferrer"&gt;how i code music player app🎶&lt;/a&gt;&lt;br&gt;
GitHub Repository:&lt;br&gt;
&lt;a href="https://github.com/a-xine/DJ.MODE/tree/main" rel="noopener noreferrer"&gt;https://github.com/a-xine/DJ.MODE/tree/main&lt;/a&gt;&lt;/p&gt;

</description>
      <category>electron</category>
      <category>tutorial</category>
      <category>javascript</category>
      <category>node</category>
    </item>
  </channel>
</rss>
