kimlj.dev / live
← Home
checking…

MDS Pro

In production
Demo datainvented nurses, hours and pay

Timekeeping, payroll and billing for a US nurse staffing company. Fifteen people open it every working day, and it is the system their pay runs through. The ground Time Doctor covers, built the other way round: no screenshots, and a clock the nurse cannot edit.

15 Daily users the whole office, every working day
407 Commits Jun 2026 to 13 Sep 2026
44 Migrations schema changed under live payroll
35 RLS policies row-level, enforced in Postgres

What is actually hard about it

Payroll cannot be eventually consistent. A timekeeping bug is not a wrong pixel, it is somebody underpaid, so corrections are a reviewed workflow with an audit trail rather than an edit.

The roster syncs in real time. No "apply changes" button, because a button nobody presses is a roster that is quietly wrong.

The Ask AI agent is read-only by construction. It answers from SQL and Sheets and holds no write tool at all, so the worst case of talking it past its instructions is a wrong sentence, not a changed record.

Stack

TypeScriptFastifySupabase / Postgres Row-level securityChrome MV3ExcelJS Apps ScriptAnthropic SDKDigitalOcean + Caddy Vercel

WordWarz.io

Live on iOS wordwarz.io dashboard

Real-time multiplayer word battle. Up to eleven people in a room, five ELO tiers, an entropy-driven bot that fills a lobby rather than leaving someone waiting.

Players, lifetime real accounts, bots excluded
Active today devices seen in the last 24 hours
Games played counted, not sampled
Rounds a game is several rounds
1,334 Commits Dec 2025 to 13 Sep 2026

Right now

live figures polled every 30s · a device is one install of one browser profile
Online now in a room · browsing
Peak concurrent (24h)
Returning devices came back on a later day than they arrived
Sockets connected a socket is a tab, not a person
Matches in progress mid-round, including the gaps between rounds
Active this week seen in 7d
Active this month seen in 30d

New vs returning players — per day

last 30 days

Counts devices that reached a game, not devices that opened the app. Guests playing solo or in practice are under-counted, since rounds without an account are not recorded per player — multiplayer is well covered.

Games per day

last 30 days, from the games table — not sampled

Games by mode

share of all games

Ranked ELO

classic — rated accounts

Platform

devices, and the share still active in 30d

Lobby sizes

games by number of players, bots included

Guesses to solve

unsolved

Average solve time

seconds by mode — the axis does not start at zero

Most used openers

mirror matches excluded — everyone opens on the same forced word there

Busiest days

all time

Recent games

the last fifteen
#ModeCodePlayersWinnerWhen

Stack

ReactCapacitorNode Socket.IOSupabaseSQLite Docker / NginxCodemagicPlaywright

jobsift

Personal workflow

Job-alert emails become a ranked shortlist. AI extracts and scores the roles; I decide which ones deserve an application.

579 Jobs stored scored posting records
232 Companies normalized company names
8 Sources with stored postings
24 Applied receipts + sent stages, deduped
16 Ignored marked Ignore in Sheets
552 Emails processed deduplicated inbox messages

Database snapshot · exported 2026-09-14 08:24 UTC · latest stored job 2026-09-14 02:13 UTC

SAMPLE REPLAY JOB / PY-042
● ● ● Gmail / inbox DEMO
A new role matches your alert Inbox
N
Northstar Talent Alerts alerts@northstar.example · 09:02
YOUR DAILY JOB MATCH

Python Automation Developer

Northstar Studio · Remote, Philippines

₱80,000–₱100,000 / month · Full-time

Build Python automations, integrate REST APIs and maintain SQL reporting pipelines. Looking for 2+ years of hands-on experience.

View job details ↗
Recognized alert · read without changing inbox status

From problem to output

Problem
Relevant roles are buried in repeated alerts across job boards.
I built
An email-first Python pipeline with extraction, deduplication, filters and an LLM scoring pass. A home worker feeds the droplet core.
Output
A ranked sheet, Telegram alerts, and an application history backed by SQLite.
Python LLM APIs SQLite Gmail / IMAP gspread httpx Telegram
onlinejobs_ph 255
indeed 202
jobstreet 50
jobstreet_api 48
linkedin 10
himalayas 8
workingnomads 3
jobicy 3

Counts are real snapshot evidence. Replay is illustrative. Sheet stages cover a subset of stored jobs; source adapters are counted separately.

kimlj.dev

Under the hood

The engineering behind the page you are viewing: a lightweight frontend, a bounded AI assistant, and an explicit deployment boundary.

Request paths / architecture

Open portfolio ↗
Browser Vercel / static assets + Serverless API Approved context → model

Hub status requests use a separate server-side probe. Provider credentials stay on the server.

01 / Interface

Hand-written HTML, CSS and JavaScript. Project stories render before network requests. Small scripts add motion, navigation and data views.

HTML CSS JavaScript SVG Responsive UI

02 / Assistant

Answers from approved portfolio material. A server-side model call, a rolling hourly spend cap, and no tools that can reach the filesystem or database.

Node.js Serverless LLM API Approved corpus

03 / Delivery

An allowlist defines the public output. The build copies public files into dist; the assistant’s private material is maintained separately.

GitHub Vercel Build allowlist CSP

From problem to output

Problem
Employers need evidence behind the projects and skills on a resume.
I built
A portfolio, a constrained site assistant, and this hub to walk through systems and their outputs.
Output
Project evidence in one place, with source timestamps and explicit boundaries between live status and snapshots.
Vanilla frontend GitHub Actions Aggregate snapshots

Infrastructure / panel 6

The VPS behind the products. Service reachability and a deployment map now have a dedicated sixth hub panel.

Public health and versions; restricted operational details. A read-only status endpoint is still to be built.

Open Backend / VPS with key 6. Host telemetry remains planned.

Shift Ops Console

Simulated workforce

From scattered punches to a reviewable exception queue. A working automation system for a synthetic workforce across eight countries.

100 Simulated staff synthetic roster
9 Timezones eight countries
5 Automation platforms each owns a specific job
97.0% Detection recall · 7 Sep 2026 359 / 370 planted · 7 Sep 2026
SAMPLE REPLAY SHIFT / DEMO-042
● ● ● Google Sheets / generated punches DEMO
Shift Ops / operationsSample workbook
fx Synthetic data · same shift across the workflow
Staff Date / zone Scheduled Clock-in
1 S-041 · Alex R. 14 Sep · Manila 09:00–17:00 09:04
2 S-042 · Jamie D. 14 Sep · Manila 09:00–17:00 09:24
3 S-043 · Morgan L. 14 Sep · London 09:00–17:00 09:02
time_entries exceptions decisions +
S-042 · shift DEMO-042 · punch joined to its schedule

From problem to output

Problem
Distributed shifts make missed breaks, no-shows and schedule mismatches difficult to review consistently.
I built
A rules-table-driven detector, severity routing and a manager review workflow, with planted anomalies to test detection.
Output
An exception queue, audience-specific digests, recorded decisions and KPI dashboards.
Apps Script Google Sheets n8n Make Zapier Power Automate Looker Studio

Evidence, including the limits

Caught
359 of 370 planted anomalies in the 45-day window, measured 7 Sep 2026. Eleven were missed.
Debugged
An open punch created unbounded duplicate overlaps. Diagnosis separated real detector errors from unlabelled valid exceptions.
Scope
Rules-based automation; no model decides compliance. Synthetic people and shifts, with an illustrative replay above.

Historical benchmark, not a live KPI. A sliding window changes the result; the dated measurement keeps its denominator.

Backend / VPS

DigitalOcean · service probes

One Ubuntu droplet behind Caddy, running the APIs for four products. Everything this page does is a read.

kimlj-backend

DigitalOcean droplet · 1 vCPU · 1967 MB · 24 GB

Ubuntu 24.04.3 LTS KVM uptime 0 days
CPU

1 vCPU

DO-Regular

RAM

839 / 1,967 MB

43%
DISK

10 / 24 GB

42%

Reverse proxy & services

Caddy terminates TLS and routes to the services on loopback.
Caddy :80 / :443 TLS · HTTP/3
Reverse proxy
api.casinore.ioDocker · :3001
api.wordwarz.ioDocker · :3002
wordle.casinore.ioDocker · :3002
mdspro.kimlj.devnode · :8787
Standalone services
sendit.serviceuvicorn
jobsift.servicepython worker → Telegram

Nightly backups

billing-sheet 28/28 · mdspromonitor 30/30 · multiwordle 8/8
2026-08-162026-09-14
30 / 30 nights 100.0% landed

Snapshot taken 2026-09-14 16:12 UTC. Host figures, the service states and the nightly-backup series are a dated reading, not a live feed · the four figures in the header strip are the live probe.