v1.0.0 — open source

devclockify.js

A full clock utility library. Stopwatch, timer, alarm, audio & formatters — all in one file.

get started view on github
npm $ npm install devclockify-js
clockify.css
cdn cdn.jsdelivr.net/.../clockify.css
<!-- in your HTML head -->
<link rel="stylesheet"
  href="cdn.jsdelivr.net/
  .../clockify.css">

<!-- then use ck- classes -->
<div class="ck-app">
  <div class="ck-time">
    00:00.00
  </div>
  <button class="ck-btn main">
    start
  </button>
</div>
index.js
cdn cdn.jsdelivr.net/.../index.js
// via CDN script tag
<script src="cdn.jsdelivr.net/
  .../index.js"></script>

// then use window.Clockify
const sw =
  Clockify.createStopwatch();

sw.onTick((ms, fmt) => {
  el.textContent = fmt;
});

sw.start();
3
modules
~8kb
file size
0
dependencies
MIT
license
what's inside

everything you need

No dependencies. No bloat. Just a single JS file with clean, well-documented functions.

stopwatch

Start, pause, reset, lap. Accurate time tracking using real timestamps with fastest/slowest lap detection.

timer

Countdown from any hours/minutes/seconds. Pause and resume with drift-free accuracy. onDone callback.

alarm

Set alarms by time and day of week. Persistent via localStorage. No duplicates. onRing callback.

audio

Web Audio API beeps with no audio files required. Customisable frequency and duration. startRinging / stopRinging.

formatters

pad2(), fmtSW(), fmtTM() — clean time formatting helpers for any display use case.

storage

Alarms auto-save to localStorage. Survive page refresh. Custom storage key support.

code examples

quick start

Drop it in and go. Works with npm, ES modules, or a plain script tag.

import { createStopwatch } from 'devclockify-js';

const sw = createStopwatch();

sw.onTick((ms, formatted) => {
  console.log(formatted); // "01:23.45"
});

sw.onLap((lap, allLaps) => {
  console.log('Lap:', lap.formatted);
});

sw.start();
sw.lap();
sw.pause();
sw.reset();

sw.getTime();    // "01:23.45"
sw.getLaps();    // [{n:1, t:5430, formatted:"00:05.43"}]
sw.isRunning(); // true / false
import { createTimer } from 'devclockify-js';

const timer = createTimer();

timer.set(0, 5, 30); // 0h 5m 30s

timer.onTick((secondsLeft, formatted) => {
  console.log(formatted); // "05:28"
});

timer.onDone(() => {
  console.log('Timer done!');
});

timer.start();
timer.pause();
timer.reset();

timer.getTime();        // "04:58"
timer.getSecondsLeft(); // 298
import { createAlarmManager } from 'devclockify-js';

const manager = createAlarmManager();

manager.add('07:00', 'wake up', [1,2,3,4,5]); // Mon–Fri
manager.add('09:00', 'weekend', [0,6]);        // Sat & Sun
manager.add('12:00', 'lunch');               // every day

manager.onRing((alarm) => {
  console.log('Ringing:', alarm.label);
  setTimeout(() => manager.stopRing(), 10000);
});

manager.start();

manager.getAll();
manager.toggle(alarmId);
manager.delete(alarmId);
manager.isRinging();
import { makeBeep, startRinging, stopRinging } from 'devclockify-js';

makeBeep();           // default 880Hz, 0.35s
makeBeep(440, 0.5);   // lower pitch, longer
makeBeep(1200, 0.1);  // high ping

const ring = startRinging();
setTimeout(() => stopRinging(ring), 5000);
reference

full api

Every function, parameter and return value.

stopwatch
methoddescriptionreturns
.start()Start or resume the stopwatchvoid
.pause()Pause the stopwatchvoid
.reset()Reset everything to zerovoid
.lap()Record current lap splitlapObj | null
.getMs()Get elapsed millisecondsnumber
.getTime()Get formatted time string"MM:SS.cs"
.getLaps()Get all recorded lapsarray
.isRunning()Check if runningboolean
.onTick(cb)Callback every ~50msvoid
.onLap(cb)Callback on lap recordedvoid
timer
methoddescriptionreturns
.set(h, m, s)Set countdown durationvoid
.start()Start or resume countdownvoid
.pause()Pause the countdownvoid
.reset()Reset to last set durationvoid
.getTime()Get formatted time remaining"MM:SS"
.getSecondsLeft()Get seconds remainingnumber
.isRunning()Check if runningboolean
.onTick(cb)Callback every ~200msvoid
.onDone(cb)Callback when donevoid
alarm manager
methoddescriptionreturns
.add(time, label, days)Add a new alarmalarm | null
.delete(id)Remove an alarm by idvoid
.toggle(id)Toggle alarm on/offvoid
.getAll()Get all alarmsarray
.getById(id)Get single alarmalarm | null
.clearAll()Delete all alarmsvoid
.start()Start the alarm checkervoid
.stop()Stop the alarm checkervoid
.stopRing()Stop currently ringing alarmvoid
.isRinging()Check if ringingboolean
.onRing(cb)Callback when alarm firesvoid
.onStop(cb)Callback when ring stopsvoid
.getDayNames(days)Convert day numbers to namesstring[]
Documentation

Architecture & System Guides

Understand the inner engine details of devclockify-js, lifecycle handling, state persistence, and styling mechanics.

1. Structural Concept

devclockify-js balances drift-free accuracy with performance optimization. Instead of processing simple increments inside a standard setInterval (which natively suffers from runtime throttling and frame drifts), the system relies on physical system clock differences (delta time) calculated from instances of Date.now().

2. Event Lifecycle Subscriptions

Modules invoke dynamic rendering loops through callbacks. It is recommended to mount and clear listeners within application component context rules to optimize rendering operations:

3. State Storage Sync Engine

The Alarm Manager operates with persistent data binding layers:

4. Web Audio Framework Policy

Audio utilities use raw synthesizer nodes powered by the browser's native Web Audio API context, generating distinct oscillators without requiring static audio file paths.

Note: Modern browsers block sound patterns unless a deliberate interaction event (Click/Touch) from the viewport user explicitly triggers the process first.