Building an alarm clock web app // Part 1

Kathy Li
Build Builds

--

Foreword — Why the Build

I used to have in my bedroom this Hi-Fi stereo that was simply out of this world.

I had this exact same model. Source: https://www.usa.philips.com/c-p/MCM275_37/-

To quote a user review word for word, because I couldn’t have said it better myself:

How could they have such an awesome model in 2006?!

I personally have nothing against 2006. I actually think it was an excellent year. But I do wonder how Philips managed to produce such a fancy, advanced model back then. Just look at it! It’s got an auxiliary input, along with a CD player and an AM/FM radio, and it’s GOT A USB PORT!!!! You can also skip albums, play your music on an MP3 player, and you have other features like a DSC (Digital Sound Control), that offers Classical, Pop, Jazz, and Rock for music genres. It also has a DBB (Dynamic Bass Boost), which increases the bass a little. This setting is best suitable during a party or a dance. You can also have it keep time, and it has an automatic timer. It also has a control panel that ejects when you push on it. I could go on FOREVER about how AWESOME this product is! Well done, Philips!

As for me, I remember liking the ability to see a CD’s graphic design spinning through the transparent PAC-MAN-like window. I also loved how I could plug in my iPod to play custom playlists (back when storing a ton of MP3’s was still a thing) through the bass-enhanced speakers.

And when it came to my absolute favorite feature of this sleek stereo, it was hands down its programmable timer — which served as my one and only morning alarm for many a year.

Every day at 7AM sharp*, a local San Francisco Bay Area music station (somewhere on the FM radio spectrum) would come on, surely but softly pulling me out of my vivid dreams.

*Except I did have to manually set the clock twice a year to adjust for Daylight Saving Time changes, since automatic time syncs were not as widespread yet.

I miss waking up to curated, enjoyable music.

Who This Post is For

For better or worse, I decided to build a web-based alarm that will play my favorite tunes (plural being the operative part) at a preset time every day.

As the saying goes, the best products are the ones that their makers would be the first to use in real life.

Then I also made the decision to document all of my steps.

If you belong in one of the following groups, I hope you can get something useful out of this post:

  • Perhaps you find yourself waking up groggy — and are interested in trying out this alarm streamer I built.
  • Or perhaps you want to publish your own app — and are interested in following the basic steps from start to finish, with or without this alarm’s exact features.

If none of the above applies to you, I’d be curious to learn more about your back story and what draws you here. Feel free to let me know in the comments.

End Result

What I Used

  • Computer: It doesn’t really matter which OS in this case
    (I was on macOS Monterey 12.6.3)
  • Browser: Again, any modern browser should do
    (I used and tested on Chrome)
    (Note: My latest implementation may not work on Firefox)
  • Code editor: I used Visual Studio Code
  • Vanilla HTML
  • CSS: Built from Sass
  • JavaScript
  • Domain registrar: For this particular project, I went with Dynadot because a quick search said that they offered .FM domains, which I wanted for my new web-based alarm “radio.”
  • Free web hosting: GitHub Pages

One More Note Before We Begin

Because everyone’s environment and settings are different, I most likely won’t have the capacity to help troubleshoot any issues you may run into. So I apologize in advance if I can’t get back to every inquiry.

That said, I would still encourage you to post comments regarding what you might be having trouble with, just in case other readers in the community could offer their insights.

Now let’s dive in!

File Structure

For my macOS environment, I have it set up so that my localhost points to my project folders under the ~/Sites/ directory.

This is where I created the project folder, /Alarm_Streamer/

I may be able to cover more on localhost in a future post but for now, if you don’t have much clue as to what I’m talking about, feel free to skip ahead.

~/Sites/Alarm_Streamer/
├── css/
│ ├── style.css
│ ├── style.css.map
│ └── style.scss
├── js/
│ └── main.js
└── index.html

Building a Bare-Bones Website

Let’s start with a basic index.html file. This will serve as our home page.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Alarm Clock Streamer</title>
</head>
<body>
<div class="main">
<div id="alarm_time">Alarm: 7:00 AM</div>
<div id="controls">
<button type="button" id="stop_audio">STOP</button>
</div>
</div>
</body>
</html>

At this point, there is more than one way to view the page. If you have localhost set up like I did, you could view what we have built so far by entering this onto your browser’s address bar:

http://localhost/Alarm_Streamer/

Otherwise, you could also just double-click on the index.html file, and your default browser should launch a new window to display our new page.

Styling the Page with CSS

I used Live Sass Compiler, a VSCode Extension that helps to compile SASS/SCSS files into CSS files in real time. You are more than welcome to use other plugins or extensions of your choice.

With a Sass compiler installed, manual styling can be done in an SCSS file. I named mine /style.scss.

body {
font-family: "Roboto Mono";
text-align: center;
background-color: #13111E;
position: relative;
height: 100vh;
overflow: hidden;
background-size: cover;
}

.main {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 720px;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
#alarm_time {
color: #fff;
text-shadow: 2px 2px 0px #333;
font-size: 48px;
font-weight: 600;
letter-spacing: 2px;
margin: 1rem 0;
}
#controls {
color: rgba(255,255,255,.5);
font-size: 30px;
font-weight: 500;
letter-spacing: 2px;
button {
background-color: transparent;
border: 3px solid #fff;
border-radius: 15px;
color: #fff;
padding: 20px 24px;
font-size: 20px;
font-weight: 600;
letter-spacing: 2px;
cursor: pointer;
width: 250px;
margin: 20px auto;
}
button:hover {
border: 3px solid rgb(221, 59, 123);
color: rgb(221, 59, 123);
}
}
}

If you are using Live Sass Compiler, click on [Watch Sass] to compile the file into good ol’ CSS.

To link the stylesheet and the right font up, add the following lines within the <head> section of /index.html:

<link rel="stylesheet" type="text/css" href="css/style.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto Mono">

Let’s preview what this does to our basic home page:

Looking a lot sharper!

Implementing Functionality with JavaScript

As one of the final (and quite crucial) steps for Part 1, I created a /main.js file in the /js/ folder.

var set_time;

function setAlarm()
{
// Get saved time
var selected_time = new Date();
selected_time.setHours(document.getElementById("alarm_hour").value, document.getElementById("alarm_minute").value, 0);

set_time = selected_time.toLocaleTimeString([], {
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
});

// Update time every second
setInterval(updateTime, 1000);

customConsoleLog("Alarm set: " + set_time);

// Hide set button
var set_button = document.getElementById("set_alarm");
set_button.style.visibility = "hidden";
}

function updateTime()
{
// Get current time
var new_time = new Date();

var curr_time = new_time.toLocaleTimeString([], {
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
});

if (curr_time == set_time)
{
customConsoleLog("Play alarm!");

var player = document.getElementById("media_player");

player.innerHTML = '<iframe id="yt_video" width="560" height="315" src="https://www.youtube-nocookie.com/embed/i43tkaTXtwI?&autoplay=1"'
+ 'title="YouTube video player"'
+ 'frameborder="0"'
+ 'allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture;"></iframe>';

document.getElementById("yt_video").contentDocument.location.reload(true);
}
}

function stopAlarm()
{
var player = document.getElementById("media_player");

// Remove autoplay
player.innerHTML = '<iframe id="yt_video" width="560" height="315" src="https://www.youtube-nocookie.com/embed/i43tkaTXtwI"'
+ 'title="YouTube video player"'
+ 'frameborder="0"'
+ 'allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture;"></iframe>';

document.getElementById("yt_video").contentDocument.location.reload(true);

// Make set button visible again
var set_button = document.getElementById("set_alarm");
set_button.style.visibility = "visible";
}

function customConsoleLog(my_log)
{
//console.log(my_log);
}

Now to link up the JavaScript file, I inserted this line right after the <body> tag in /index.html:

<script src="js/main.js"></script>

Then I added the corresponding HTML components to work with the JavaScript. Returning to /index.html, the alarm_time <div> now features a time selection dropdown which looks like this:

<div id="alarm_time">Alarm: 
<span><select id="alarm_hour">
<option value="0">00:</option><option value="1">01:</option><option value="2">02:</option><option value="3">03:</option>
<option value="4">04:</option><option value="5">05:</option><option value="6">06:</option><option value="7">07:</option>
<option value="8">08:</option><option value="9">09:</option><option value="10">10:</option><option value="11">11:</option>
<option value="12">12:</option><option value="13">13:</option><option value="14">14:</option><option value="15">15:</option>
<option value="16">16:</option><option value="17">17:</option><option value="18">18:</option><option value="19">19:</option>
<option value="20">20:</option><option value="21">21:</option><option value="22">22:</option><option value="23">23:</option>
</select></span>
<span><select id="alarm_minute">
<option value="0">00</option><option value="1">01</option><option value="2">02</option><option value="3">03</option>
<option value="4">04</option><option value="5">05</option><option value="6">06</option><option value="7">07</option>
<option value="8">08</option><option value="9">09</option><option value="10">10</option><option value="11">11</option>
<option value="12">12</option><option value="13">13</option><option value="14">14</option><option value="15">15</option>
<option value="16">16</option><option value="17">17</option><option value="18">18</option><option value="19">19</option>
<option value="20">20</option><option value="21">21</option><option value="22">22</option><option value="23">23</option>
<option value="24">24</option><option value="25">25</option><option value="26">26</option><option value="27">27</option>
<option value="28">28</option><option value="29">29</option><option value="30">30</option><option value="31">31</option>
<option value="32">32</option><option value="33">33</option><option value="34">34</option><option value="35">35</option>
<option value="36">36</option><option value="37">37</option><option value="38">38</option><option value="39">39</option>
<option value="40">40</option><option value="41">41</option><option value="42">42</option><option value="43">43</option>
<option value="44">44</option><option value="45">45</option><option value="46">46</option><option value="47">47</option>
<option value="48">48</option><option value="49">49</option><option value="50">50</option><option value="51">51</option>
<option value="52">52</option><option value="53">53</option><option value="54">54</option><option value="55">55</option>
<option value="56">56</option><option value="57">57</option><option value="58">58</option><option value="59">59</option>
</select></span>
</div>

I added one more button to the controls <div>:

<div id="controls">
<button type="button" id="stop_audio" onclick="stopAlarm()">STOP</button><br>
<button type="button" id="set_alarm" onclick="setAlarm()">SET</button>
</div>

Right after the alarm_time <div>, I add this media_player <div>:

<div id="media_player">
<iframe id="yt_video" width="560" height="315" src="https://www.youtube-nocookie.com/embed/i43tkaTXtwI"
title="YouTube video player"
frameborder="0"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture;">
</iframe>
</div>

The media source is a temporary video for the time being.

Temporary Video

For the initial launch, because I didn’t want to spend too much time to compile my own playlist here, I basically just embedded a popular YouTube video from the Lofi Girl.

URL: https://youtu.be/i43tkaTXtwI

If everything is working correctly, the embedded video would start auto-playing at the alarm time you set.

Caveats

Before you actually go ahead and use this app as your morning alarm:

  1. While the ability to manually set an alarm time has been implemented, there is no functionality to SAVE the time yet. This means as soon as you close or refresh the browser window, the “alarm” will be gone.
  2. In this version, you will have to manually change your computer / smartphone settings so that it doesn’t go to sleep at all. Otherwise, the “alarm” will not come on. (I may be able to cover the implementation of an automated stay-awake function in a future post.)

Coming in Part 2

In the next part, I will go over the steps of publishing this web app for the world to use.

--

--

Kathy Li
Build Builds

Chronicling how we invent and build products from zero to launch. (https://kathy.li)