🎯 Office Culture Event Tracker · Zero-server · 100% local

Track, celebrate, and
reward your team culture

CultureHub is a pure-browser app for managing company culture events — check-ins, leaderboards, photo galleries, and printable reports. No sign-up, no server, no cloud. All data lives in your browser.

🚀 Open CultureHub Explore Features ↓
culturehub/dashboard.html
Participants
24
Events
8
Points Awarded
137
Winners
12
🏆 Leaderboard
🥇
AJ
Alice Johnson
Engineering
21
🥈
GK
Grace Kim
Engineering
18
🥉
BS
Bob Smith
Marketing
14
#4
ED
Emma Davis
Sales
11

✨ Feature set

Everything in one tab

Eight pages, one CSS file, one data layer. Add people, run events, check in attendees, and celebrate winners — all without leaving the browser.

📅
Event Management
Create and edit events with title, date, type, location, and description. Filter by type or search by name. Each event card shows live check-in counts and points at a glance.
CRUD Filter & search 6 event types
👥
Roster & Import
Manually add people with name, team, and email, or bulk-import from a JSON file. Supports native format and Microsoft Teams / Azure AD export (displayName, mail, department).
JSON import Teams/Azure AD Team filter
Check-In & Scoring
Click any attendee card to check them in (+1 pt). Mark winners for bonus points (+3 pts). Undo check-ins, bulk-check all, and search within an event's roster — all in real time.
Points system Winner flag Bulk check-in
📺
TV Dashboard & Leaderboard
A live leaderboard with animated ranks, a scrolling ticker, and event attendance bars. One click enters full-screen TV Mode for lobby displays — auto-refreshes every 30 seconds.
TV Mode Auto-refresh Ticker
🖼
Photo Gallery
Upload photos per event via drag-and-drop or file picker. Tap any photo to open a fullscreen slideshow with keyboard navigation (arrow keys, Escape).
Drag & drop Slideshow Keyboard nav
🔍
Search & Reports
Global search across people and events with a split-panel detail view. Generate print-ready PDF reports for overview, individual events, or per-person stats.
Global search PDF export Per-person stats

🚀 Quick start

Up and running in 3 steps

No install, no build step, no account. Open the HTML file and you're done.

1
⚙️
Configure your org
Open Settings and set your organization name. Load the built-in sample data to explore all features instantly, or import your real team from a JSON file.
2
📅
Create events & roster
Add team members in Roster (or bulk-import from Teams/Azure AD). Create your first event in Events with a date, type, and location.
3
Check in & celebrate
Open Check-In on the day, tap people to check them in, mark winners for bonus points, then put the Dashboard on the TV.
💡 Day-of workflow: Open checkin.html on a tablet or laptop at your event. As people arrive, tap their card. Winners get 3 pts, attendees get 1 pt. The leaderboard on dashboard.html updates live — put it on a screen for the room.

🏷 Classification

Event types

Six built-in types, each with a distinct color badge for quick visual scanning.

🎮 Game 🥂 Social 🤝 Team Building 🎉 Holiday ❤️ Charity 📌 General

⭐ Scoring

Points system

1 pt
Attending an event and checking in
🏆
3 pts
Winning an event (event host marks winner)
📊
Points accumulate across all events, no cap
Leaderboard tie-breaking: Equal points → sorted by number of events attended. Marks are live — toggling winner status re-scores immediately.

🗂 Data model

How data is structured

Everything lives in a single culturehub_data key in localStorage as a JSON object with three top-level keys.

{
  "version": 1,

  "settings": {
    "orgName": "Our Organization",
    "theme":   "dark"            // "dark" | "light"
  },

  "people": [
    {
      "id":     "lx3k8a",        // uid() — base36 timestamp + random
      "name":   "Alice Johnson",
      "team":   "Engineering",
      "email":  "alice@company.com",
      "avatar": ""               // reserved, auto-generated from initials
    }
  ],

  "events": [
    {
      "id":          "m2p9xq",
      "title":       "Summer Trivia Night",
      "date":        "2025-07-15",     // ISO date string
      "type":        "Game",
      "description": "Teams compete in trivia!",
      "location":    "Rooftop",
      "gallery": [
        { "id": "…", "url": "data:image/jpeg;base64,…", "caption": "" }
      ],
      "attendees": [
        {
          "personId":  "lx3k8a",  // foreign key → people[].id
          "checkedIn": true,
          "points":    3,
          "isWinner":  true
        }
      ]
    }
  ]
}
⚠️ Gallery storage limit: Photos are stored as base64 data URLs inside localStorage, which browsers typically cap at 5–10 MB. Use the built-in Backup feature regularly, and delete old photos if you hit the limit. A "Storage full" toast will appear if the quota is exceeded.

🧱 Architecture

How it's built

No framework, no bundler, no build step — pure HTML, CSS, and vanilla JS. Three files drive everything.

📄 data.js data layer

An IIFE that wraps all localStorage access behind a clean API. Every mutation calls save(), which serialises the whole object to localStorage and fires a CustomEvent so every page re-renders reactively.

IIFE module localStorage CustomEvent bus uid() — base36
window.CH  // global singleton
CH.getPeople()       CH.addPerson(…)
CH.getEvents()       CH.addEvent(…)
CH.checkIn(…)        CH.toggleWinner(…)
CH.getLeaderboard()  CH.exportBackup()
CH.getPersonStats()  CH.importBackup()
🛠 utils.js UI helpers

Shared utilities loaded on every page after data.js. Provides the nav template, theme system, toast notifications, modal helpers, avatar generation, date formatting, and PDF report builders.

Theme (dark/light) Toasts Modals PDF reports navHTML()
Theme.toggle()         toast(msg, type)
openModal(html)        confirmDialog(msg)
avatarEl(name, size)   fmtDate(dateStr)
eventTypeBadge(type)   generateReport(…)
navHTML()              setActiveNav()
🎨 style.css design system

A single CSS file with a complete token-based design system. Dark and light themes are declared as CSS custom properties on html[data-theme]. Components are utility-first with semantic class names.

CSS variables Dark + Light Responsive Outfit + Jakarta Sans
.card    .btn-primary  .badge-accent
.modal   .stat-card    .progress-bar
.avatar  .chip         .type-game
.grid-2  .form-control .empty-state
⚡ Page pattern each .html

Every page follows the same pattern: inject nav, call render(), and subscribe to the culturehub:updated event so the page re-renders whenever data changes (even if changed in another tab on the same origin).

innerHTML render Event-driven No virtual DOM
// Every page — verbatim pattern
document.getElementById('nav-root')
  .innerHTML = navHTML();
setActiveNav();

function render() { /* build innerHTML */ }
window.addEventListener(
  'culturehub:updated', render);
render();
FOUC prevention: Each page has an inline <script> in <head> that reads the theme from localStorage and sets data-theme on <html> before the stylesheet is parsed — eliminating the flash of unstyled (light) content on load.

📁 File map

Project structure

culturehub/
├── index.html      Home — stats overview, top-5 leaderboard, upcoming events
├── events.html     Create / edit events, filter by type
├── roster.html     Add / import people, view per-person stats
├── checkin.html    Day-of attendance with check-in and winner flags
├── dashboard.html  Live leaderboard, TV mode, activity feed, ticker
├── search.html     Global search across people & events with detail panel
├── gallery.html    Per-event photo grids with drag-drop upload and slideshow
├── settings.html   Org name, backup/restore, import, danger zone
│
├── data.js         CH singleton — all CRUD, leaderboard, import/export
├── utils.js        Theme, toasts, modals, avatars, date helpers, PDF reports
├── style.css       Complete design system — dark + light, 380 lines
│
└── docs/
    └── index.html  ← you are here

💾 Data portability

Backup & restore

Exporting

The Backup button (nav bar) or Settings → Download Backup JSON saves the full culturehub_data object as a dated .json file. Photos are embedded as base64 — the file is self-contained.

Filename format: culturehub-backup-YYYY-MM-DD.json

Restoring

Settings → Restore — load a backup file or paste JSON directly. The restore validates the people and events keys before writing, then fires culturehub:updated so all open tabs refresh.

Replaces all current data. Always backup first.

⌨️ Keyboard

Keyboard shortcuts

Available throughout the app.

Enter / exit TV Mode (Dashboard)
Alt T
Enter / exit TV Mode (Dashboard)
F11
Exit TV Mode
Esc
Next photo in slideshow
Previous photo in slideshow
Close slideshow / modal
Esc