3
0
Fork 0
Stylish time-tracker for check-in, overtime, time off, and more.
  • Go 43.8%
  • JavaScript 38.9%
  • CSS 13.2%
  • HTML 4.1%
Find a file
2026-05-02 15:50:44 -05:00
.memsearch Clean up 2026-05-01 10:12:05 -05:00
cmd/tempo fix(server): drain shutdown clean 2026-05-02 11:44:21 -05:00
db refactor: remove Bun backend 2026-05-01 09:34:22 -05:00
internal/tempo fix(server): drain shutdown clean 2026-05-02 11:44:21 -05:00
public chore(dom): remove stale backup 2026-05-02 15:50:44 -05:00
.gitignore refactor: remove Bun backend 2026-05-01 09:34:22 -05:00
go.mod feat(go): add stdlib backend 2026-05-01 09:32:29 -05:00
logic.md refactor(dom): remove raw replacements 2026-05-02 15:50:35 -05:00
README.md feat(requests): group OT ranges 2026-05-02 15:02:22 -05:00

Tempo

The goal of this project is to build a new timekeeping utility for internal teams.

Backend

Tempo uses a Go backend built only on the standard library. net/http serves the JSON API and static files from public/. The app is expected to run behind a TLS-terminating proxy, so it serves cleartext HTTP/1.1 plus cleartext HTTP/2 to the proxy through http.Protocols.SetUnencryptedHTTP2. It does not load certificates or serve internal TLS.

The temporary data store is tempo-data.json. It is an atomic JSON file store behind the tempo.Store interface so a SQL implementation can replace it later without changing handlers. If the file does not exist, the server seeds demo shifts, users, attendance history, and requests.

Shift scheduling is built around admin-controlled shift groups. A group owns the timezone, schedule kind, and cycle anchor; plans define concrete day/night/office times; segments define on/off windows such as 3 on, 4 off, 4 on, 3 off. Users still receive one concrete shift_id, so current assignment, scoping, and future SQL replacement stay simple.

Session cookies are Secure by default because external traffic should arrive through HTTPS at the proxy. For direct local browser testing without a proxy, run with TEMPO_SECURE_COOKIES=false.

If any authenticated API call fails with 401 Unauthorized, the server expires the session cookie and the frontend redirects to the login page. This keeps stale sessions from leaving the dashboard, admin page, or event stream in a broken loading state.

Realtime UI updates use a standard-library SSE bus at /api/events?topics=.... Mutating handlers publish topic events by metro, and the frontend subscribes with EventSource instead of polling for change timestamps.

On SIGINT or SIGTERM, the server drains through http.Server.Shutdown, closes active SSE streams, and only falls back to closing active connections if the shutdown window is exceeded.

Role overview widgets use transparent surfaces with clear headings, balanced spacing, and small translucent rows. Dense employee tempo charts, forms, and full calendar panels keep card boundaries when the structure improves readability. Tooltips use a tiny shared frontend helper that clamps to the viewport and draws a black arrow back to the source element.

Technician view

Technicians get a compact seven-day "This week" strip before the tempo chart. It shows current and upcoming work, scheduled-off days, PTO, OT, pending requests, late/out notices, and missing check-in state without replacing the 30-day tempo history. The request tracker lists pending requests first, then active/upcoming approvals, then recent denials, capped to keep the dashboard compact, with human copy like "Eight hours of OT on May 2" and "On vacation from May 2 to May 5." Consecutive OT requests with the same status, hours, and reason display as one readable range until a single day changes status, and OT requests can include an optional short reason for manager review. The header calendar icon opens /calendar.html, a 31-day personal schedule calendar with work/off/PTO/OT/attention counts and a selected-day detail panel.

Senior view

Seniors keep the technician tools and get compact read-only team widgets above the team tempo cards: a today coverage snapshot, an exception queue for red/yellow roster issues, and a live recent-changes feed driven by the SSE bus. Team data stays scoped to the senior's concrete shift, and schedule-off days do not count as missing coverage. Their /calendar.html view blends the personal 31-day calendar with the same read-only roster calendar managers use.

Admin view

Super admins get an overview on the admin panel with metro health, data quality, recent audit activity, and system status. The system card reports store type/path, last write time, SSE event history/client counts, cookie mode, and session lifetime. Shift management includes compact shift-group presets for 7a-7p 3/4/4/3, 7p-7a 3/4/4/3, and 9-5 weekday schedules; concrete shifts stay assignable to a group/plan from the shift table.

Manager view

Managers get a compact "today roster" summary and operation widgets for coverage risk, approval inbox, attendance trends, and OT utilization before the "Your team's tempo" cards. Coverage risk and OT utilization badges show "Next 7 days" by default and can be clicked to rotate 7, 14, and 30 day windows. Coverage risk uses compact calendar cells, with expected/core/OT/planned-off/scheduled-off stats listed vertically in black hover/focus tooltips. Links to the dedicated /manager-calendar.html roster view appear from the summary and header calendar icon; the calendar view header uses the dashboard icon to return to /dashboard.html. Summary status counts show visible labels plus tooltips listing techs under each color, and attention items render as a compact vertical list with bullet color matching status. The dedicated view shows today plus the next 13 days. Today shows gray/blue/green/yellow/red roster counts; future days show planned gray counts and only show approved-OT blue when scheduled OT exists, so green/yellow/red remain a record of current or past attendance outcomes. The selected day lists scheduled core employees plus OT visitors. Off-cycle core employees are excluded from expected and missing counts; approved time-off removes scheduled core employees from the expected roster and shows them as planned off for the day. Approved OT visitors show an OT badge and blue status; pending OT visitors show OT?.

Status colors:

Color Meaning
Gray Scheduled core employee expected, or future pending OT request
Blue Approved OT visitor expected, or OT visitor checked in
Green Non-OT employee checked in
Yellow Late notice, pending OT, or attention needed before grace window expires
Red Out, missing after grace window, or late without notice

Run

go run ./cmd/tempo

Useful environment variables:

Variable Default Purpose
PORT 3000 Port used when TEMPO_ADDR is unset
TEMPO_ADDR :3000 Full listen address
TEMPO_DATA_PATH tempo-data.json JSON store path
TEMPO_PUBLIC_DIR public Static asset directory
SESSION_EXPIRES_HOURS 24 Session lifetime
TEMPO_SECURE_COOKIES true Mark session cookies Secure; set false only for direct local HTTP

Test

go test ./...

Demo accounts

The seeded data includes these accounts:

Role Email Password
Super admin admin@tempo.local admin123
SAMA manager john.manager@tempo.local password123
SAMA senior sarah.senior@tempo.local password123
Technician mike.tech@tempo.local password123