Creative In/Out™ Documentation
Version 1.1
Product Overview
Creative In/Out™ is an employee presence board for businesses of any size. It shows who is In, Out, or Away at a glance — from any browser, on any device, with no app to install and no per-seat fees. It also doubles as a built-in company directory with photos, phone numbers, and email accessible from every person's card.
Key Features
- Three statuses: In, Out, and a customizable third status (Away, Lunch, WFH, Remote, etc.)
- Built-in company directory: Photos, direct lines, cell numbers, and email — one click from any status card, with copy buttons on every field
- Printable directory: Choose which columns to include, preview it, and print or save as PDF
- Notes & quick presets: Each person can have a short note. Admins define common presets for one-tap entry
- Peek view: One click shows everyone's status in a compact three-column list, ignoring whatever filters are applied
- Hours report: Every status change is recorded, so admins can produce per-person hours for any date range
- Birthdays & work anniversaries: A once-a-day popup for what's coming up, plus a full year-round list on demand
- Optional PIN authentication: 4-digit PINs identify who makes each change and ensure employees can only update their own status. Can be turned on or off.
- Company Access Code: Optional 4-digit code required to view the public board — keeps the board private from anyone who stumbles across the URL
- Admin panel: Full management of people, settings, and configuration
- Backups: One-click download from the admin panel, plus an optional scheduled script that keeps hourly, daily, and weekly snapshots
- CSV export: Point-in-time snapshot for attendance records or HR documentation
- Auto-Out: Automatically marks everyone still In as Out at a set time each day (requires cron job)
- Custom menu: Add your own links — intranet, HR portal, shared calendars — to a menu on the public board
- Light/dark theme: Toggle between modes per browser
- Mobile friendly & PWA: Fully responsive, can be added to phone home screen
- Runs entirely on your server: No external services, no outbound requests, no analytics. Works on an isolated network with no internet access.
What It Is Not
Creative In/Out is a presence board, not a payroll system. It records when someone's status changed, and the Hours Report totals that up — which is genuinely useful for checking a contractor's week or settling a question about a shift. But those totals reflect what people marked, not a supervised time clock. Someone who forgets to mark Out at the end of the day will show an overlong shift until it is corrected.
Treat the Hours Report as a well-kept record to review, not as an authoritative timesheet, and don’t wire it straight into payroll. The optional Time Clock Reminder can prompt employees to clock in and out of a separate system when they change their status.
This is done per provider and quoted per project, since every payroll API differs. Contact us with your provider’s name and we’ll tell you what’s feasible.
Installation Guide
Requirements
- Web server with PHP 7.4 or higher
- Write permissions on the installation directory
- OpenSSL extension enabled (standard on most hosts including Dreamhost)
- PHP
zipextension — needed for the one-click backup download. If it is missing, everything else still works and the scheduled backup script can be used instead.
Files Included
| File | Purpose |
|---|---|
index.html | Redirects visitors to the public board |
inout-board.html | Public in/out board |
inout-admin.html | Admin panel |
inout-data.php | Data API — handles all reads and writes |
inout-upload.php | Photo upload handler |
inout-prefs.php | Per-person preferences |
inout-hours-report.php | Hours report generator |
inout-backup.php | One-click backup download |
inout-backup.sh | Optional scheduled backup script — see Section 7 |
inout-cron.php | Auto-Out cron job script |
license-validator.php | License verification — do not delete |
help-admin.html | Administrator guide bundled with the install — opened by the ? button in the admin panel |
help-user.html | Short user guide for everyday staff — opened by the ? button on the public board |
manifest.json | PWA manifest |
sw.js | Service worker — offline support and forced updates |
fonts/ | Folder of 8 font files. Without it the board still works but falls back to system fonts and looks noticeably different. |
sitelogo.png | Logo shown in the board header and on the access-code screen |
favicon.ico | Browser tab icon (multi-size) |
favicon.svg | Scalable browser tab icon |
favicon-96x96.png | High-res browser tab icon |
apple-touch-icon.png | iOS home screen icon (180×180) |
icon-192.png / icon-512.png | Android / PWA install icons. Both are required — see the note below. |
robots.txt | Blocks search engines from indexing your board |
htaccess.txt | Security rules for Apache and LiteSpeed — rename to .htaccess before uploading |
nginx.conf.txt | The same rules for nginx servers, which don't read .htaccess |
web.config.txt | The same rules for Windows IIS — rename to web.config |
README.txt | Quick-start guide |
icon-192.png or icon-512.png is missing, the service worker fails to install — which silently disables offline support and the automatic update system, with no visible error. The Install Check described below catches this.
Files Created Automatically
These appear on their own once the board is running. Do not create them by hand, but do include them in your backups.
| File | Contents |
|---|---|
inout-data.json | Everything — people, PINs, divisions, settings, notes |
inout-status-log.jsonl | Every status change ever recorded. This is what the Hours Report reads. |
inout-prefs.json | Per-person preferences |
inout-pinguard.json | Short-lived record of failed PIN attempts. Safe to delete; it rebuilds itself. |
images/ | Uploaded staff photos |
Web Server Rules
The board's data files — your roster, PINs, and the full status history — sit in the same directory as the program files. They're read and written by PHP; nothing should ever fetch them over the web. Two files are included to enforce that, and which one you use depends on your server:
| Server | What to do |
|---|---|
| Apache | Rename htaccess.txt to .htaccess. That's it. |
| LiteSpeed / OpenLiteSpeed | Same — LiteSpeed reads .htaccess directly. |
| Windows IIS | Rename web.config.txt to web.config and leave it in the same folder. IIS reads it automatically — no restart, no administrator rights. |
| nginx | Apply nginx.conf.txt to your site's server block and reload nginx. |
.htaccess, which takes effect the moment it's uploaded. On shared nginx hosting without that access, ask your host to apply them. Until they are, your data files can be downloaded by anyone who knows the URL.
Verify It Worked
Rules that silently fail to apply are worse than no rules, because the install looks fine. After renaming the file, visit this in a browser:
yourdomain.com/your-path/inout-data.json
You should get Forbidden or Not Found. If you see your data, the rules aren't being applied.
htaccess.txt produces .htaccess.txt — which looks identical in a listing and does nothing. Turn on "show file extensions" and check the name on the server. This is the most common cause by a wide margin.
If the name is right, confirm the file sits in the same folder as inout-data.json, and that your server is actually Apache or LiteSpeed — curl -I against your board, or your host's control panel, will tell you. On nginx, .htaccess is ignored entirely.
Installation Steps
- Upload all files — including the
fonts/folder — to a directory on your web server via FTP or SFTP. A dedicated subdirectory is recommended, e.g.yourdomain.com/inout/, or a subdomain likeboard.yourdomain.com. - Set directory permissions to
755. PHP needs write access to create its data files. - Create an
images/folder in the same directory and set its permissions to755. This is where staff photos are stored. - Apply the security rules for your server — this blocks direct web access to your data files, including PINs and status history. Which file you use depends on the server:
- Apache or LiteSpeed (most shared hosting, including Dreamhost) — rename
htaccess.txtto.htaccess, noting the leading dot - Windows IIS — rename
web.config.txttoweb.config; IIS picks it up automatically - nginx — apply
nginx.conf.txtto your server block and reload nginx
- Apache or LiteSpeed (most shared hosting, including Dreamhost) — rename
- Visit the board in your browser. On first load, PHP creates
inout-data.jsonwith sample data automatically. - Open the admin panel and run Install Check (Settings → Install). It confirms every required file arrived. Fix anything it flags before going further.
- Proceed to First-Time Setup — see Section 3.
Install Check
The admin panel includes a self-diagnostic that verifies every file the board depends on is actually present on the server. Open the settings panel and click Install Check.
It reports each item as green (present), amber (missing but not fatal), or red (missing and something is broken). Two failures are worth knowing about because they have no other symptom:
- Missing icons stop the service worker installing, disabling offline support and automatic updates
- A missing
fonts/folder silently substitutes system fonts, changing the board's appearance
If you ever contact support about an installation problem, running this first and reading out the red and amber lines will usually identify the cause immediately.
Dreamhost-Specific Notes
- PHP is available by default — no configuration needed
- The installation directory needs write permissions (
755) - If you see "Could not load board data", confirm
inout-data.phpandlicense-validator.phpare both uploaded to the same directory
First-Time Setup
Accessing Admin
Click the Creative In/Out logo icon in the top-left corner of the public board, or navigate directly to inout-admin.html. On first load with no admins configured, you will see a setup banner and can access admin freely to create your first admin user.
Creating Your First Admin
- Click + Add in the settings bar
- Fill in the person's name and set a 4-digit PIN
- Check the Global Admin checkbox
- Click Save
Once an admin exists, the admin panel requires a PIN on every visit, and changes to people or settings require a Global Admin PIN. This is enforced by the server, not just hidden in the interface.
Recommended Setup Order
- Run Install Check and clear anything it flags
- Set your Brand name — replaces "Creative" in the header. Max 20 characters.
- Set your Group Label (Division, Department, Location, Team…). Max 12 characters.
- Set your Away Label if "Away" isn't the word you use. Max 6 characters.
- Create your divisions and assign each a colour
- Add your people, with PINs, divisions, roles and contact details
- Add quick-note presets for the notes people type most
- Decide on Require PIN and the Company Access Code — see Section 8
- Set up backups — see Section 7
- Activate your license — see Section 9
Admin Panel Guide
Navigate to inout-admin.html and enter your 4-digit admin PIN. The admin panel shows the same board as the public view with additional controls for each person and a settings panel at the top.
Admin access requires a Global Admin PIN. A Division Admin PIN will not open the panel — division admins manage their people from the public board instead.
Settings Panel
Click Expand on the stats bar to open settings. Click Collapse ▲ at the bottom to close.
Row 1 — People, Data & Board Controls
- + Add — Add a new person to the board
- Backup — Downloads a complete, restorable copy of your board as a
.zip. See Section 7. - CSV — Downloads the current board as a spreadsheet. This is a point-in-time snapshot for reading, not a backup you can restore from.
- Sort — The public board's default sort order (Name A–Z, Division, Status, Most Recent)
- Brand — Company name in the board header. Max 20 characters. Click Save.
Row 2 — Behavior Settings
- Auto-Out — Set a daily time to mark everyone still In, or on the third status, as Out. Requires cron job setup — see Section 10.
- Timezone — The timezone Auto-Out uses. Defaults to whatever your own computer reports. Only Auto-Out depends on it; everything else already works in each viewer's own timezone.
- Require PIN? — When checked, status and note changes require a PIN. Ships disabled. Cannot be enabled until every person has a PIN assigned — a warning shows a clickable list of anyone missing one.
- Time Clock Reminder — Shows a reminder popup on status changes to clock in or out of a separate system.
Row 3 — Company Access Code
Sets a 4-digit numeric code that must be entered before the public board loads. Once entered correctly on a device it is remembered and not asked again. Leave blank to disable. Change the code at any time — every device is prompted on its next visit.
Recommended if your board URL could be discovered by people outside your organization, and strongly recommended if you run the board with PIN authentication turned off.
Row 4 — Labels
- Group Label — What to call your groups: Division, Department, Location, Team. Max 12 characters.
- Away Label — Rename the third status. Default: Away. Examples: Lunch, WFH, Remote, Break. Max 6 characters.
Row 5 — Quick-Note Presets
Define common notes for one-tap entry on the board. Type a preset and click + Add. Click the pencil to rename, × to remove, and drag the ☰ handle to reorder. Presets appear on the board immediately.
Row 6 — Public Menu
Adds your own links to a Menu button on the public board — an intranet, an HR portal, a shared calendar, a policy document. Click Manage menu to open the editor.
- Each item is either a Link (opens in a new tab) or an Embed (opens inside a panel on the board)
- Items can have sub-items — drag to reorder at either level
- Admin only hides an item from everyone except admins. Setting it on a parent applies it to all its children.
Row 7 — Install Check
Verifies every file the board needs is present on the server. See Section 2.
Row 8 — License
Shows current license status and your user limit. Paste your license key and click Activate. Once licensed, the key is shown masked — click Edit to re-enter it. See Section 9.
Managing Divisions
The Divisions panel sits below the main settings. Type a name and click + Add. Click the coloured dot to change a division's colour, the pencil to rename, and × to delete (only possible when no one is assigned to it). Drag to reorder — this order is the display order on the board.
Division names are limited to 20 characters. Longer names crowd the filter control and truncate on cards.
Auto-filter on Mark In — When enabled, the public board filters to a person's division when they mark In, and briefly shows a notification. Useful for floor or warehouse environments where employees check themselves in; turn it off for boards managed by a single receptionist marking In on others' behalf.
Managing People
Each admin card has status buttons, a note field, a contact icon, and a timestamp showing who last changed the status and when. Hover the timestamp to see recent changes.
- ✏ Edit — update a person's details
- Deactivate — remove someone from the board without deleting them
- Print — a printable admin directory including PINs, birthdays and admin flags
- Show inactive — the crossed-out-person icon beside the status filters reveals deactivated people
Deactivating vs Deleting
People are never deleted. Deactivating removes someone from the public board and frees their user seat, while keeping their record, their history, and their hours. Their PIN stays permanently reserved so it can never be reissued to someone else and confuse an old audit trail.
A deactivated person can be reactivated at any time, provided you have a free seat. Their name still resolves correctly in older history entries, so past changes continue to read "by: Casey" rather than reverting to something anonymous.
Sorting and Grouping
When Sort is set to Division and no division filter is applied, cards are grouped under collapsible headers in each division's colour, with a count. Groups start expanded; collapsing one lasts until you reload.
Edit Form Fields
| Field | Notes |
|---|---|
| Photo | JPG or WebP — max 3MB. Cropped to a square when uploaded. Shown in the contact card. |
| Name | Max 40 characters |
| PIN | 4-digit numeric, must be unique. Required for everyone when Require PIN is on. Always required for Global Admins and Division Admins regardless of that setting. Optional for regular users otherwise. |
| Birthday | MM/DD — no year. Drives the birthday popup and list. |
| Work Anniversary | MM/DD/YYYY — the year is needed to count years of service. |
| Division | Select from your configured divisions |
| Role | Job title, max 40 characters. Searchable. |
| Direct / Main / Cell | Phone numbers shown in the contact card, with copy buttons and tap-to-dial |
| Shown as a clickable mailto link with a copy button | |
| Global Admin | Full access to the admin panel and everyone in it. The last Global Admin cannot be removed. |
| Division Admin | Can change statuses and notes for their own division on the public board, and view their hours reports. No admin panel access. |
Printing an Admin Directory
The Print button on the stats row produces a directory with the columns only an admin can see — division, role, birthday, work anniversary, PIN, and admin flags — plus an option to include deactivated people, who print with their names struck through.
Public Board Guide
The public board (inout-board.html) shows every person's current status, division, role, and note. Click a person's name or the contact icon to see their photo, phone numbers, and email.
Signing In
When Require PIN is on, the header shows a Login button. Enter your PIN once and you stay signed in on that device — the button becomes your name, and status and note changes no longer prompt for a PIN.
Click your name for My Preferences and Sign Out. On a shared screen, sign out when you're done; on your own phone, staying signed in is the point.
With Require PIN off there is no sign-in at all, and anyone viewing the board can change any status or note. That is the intended behaviour for a trusted internal network — but it also means changes are recorded as "USER" rather than a name.
Changing Your Status
Desktop: click a status button on the card.
Mobile: tap the status pill on the card, which opens a panel with all three statuses and the note field.
If you're signed in and have authority over that record — your own, or anyone's if you're an admin — the change applies immediately with no prompt. Otherwise you'll be asked for a PIN.
Adding a Note
Click the note field on a card you can edit and type. Maximum 140 characters. Press Enter or click away to save. Click the ≡ icon for quick-note presets, and × to clear a note.
Notes longer than the card can show are truncated with a + indicator — hover it on desktop, or press and hold on mobile, to read the whole thing.
Your Own Card
When you're signed in, your card is pinned to the top of the board with an amber outline and a (you) marker, regardless of the current sort, filter or search. You never have to hunt for yourself in a list of fifty.
Stale Statuses
Someone marked In or Away for more than 12 hours is shown with a muted, desaturated status colour. It's a quiet signal that they probably forgot to mark themselves Out rather than that they're still at their desk at 3am. Out never goes stale.
Filtering, Sorting & Searching
- Search — matches name and role. It deliberately overrides the division and status filters, so searching for someone always finds them regardless of what's currently filtered; the division indicator reads "Searching" while the box has text in it.
- All / In / Away / Out — filter by status
- Division — filter to one division. Each option is shown in that division's own colour.
- Sort — Name, Division, Status, or Most Recent. Sorting by Division with no division filter groups the board under collapsible coloured headers.
Your sort and theme choices are personal to your browser and don't change what anyone else sees. The default sort for new visitors is set in admin.
Peek — Everyone at a Glance
The eye icon opens a compact three-column list of the entire roster with a coloured dot for each status. It ignores every filter and the search box, because the question it answers is "who's around right now". Click a name to open their contact card.
Birthdays & Anniversaries
The calendar icon opens a two-tab list of birthdays and work anniversaries for the whole year, opening at today's date. Past dates are dimmed; today and tomorrow are labelled.
Separately, once a day, a popup shows what's coming up — today through the next working day, so Friday covers the weekend and Monday. It appears only if there's something to celebrate, and can be switched off per person in My Preferences.
Print Directory
The Print button produces a staff directory. Choose which contact columns to include, preview the result, then print or save as PDF. It follows the current division filter but ignores search and status filters — a directory is a reference document, not a snapshot of who's in.
Only people with data in at least one selected column appear, so you never get a page of names and empty cells. Print is hidden on phones, where the output isn't usable.
My Preferences
Stored per person on the server, so they follow you to any device you sign in on.
- Don't auto-filter to my Division — by default, signing in narrows the board to your own division. Turn this on to start on All Divisions instead.
- Daily birthday & anniversary popup — on by default.
Custom Menu
If your administrator has configured menu items, a Menu button appears in the header with your organization's own links. If no items are configured, the button doesn't appear at all.
Hours Report
Every status change is written to inout-status-log.jsonl, an append-only record separate from the main data file. The Hours Report reads that log and totals the time each person spent In and Away over a date range.
Who Can Run It
- Global Admins — anyone on the board
- Division Admins — only people in their own division
- Everyone else — no access, including to their own hours
Enforced by the server, not just hidden in the interface.
Running a Report
Open a person's contact card — from the public board or the admin panel — and click Hours. Pick a date range and click Run Report. It defaults to the last two weeks.
Summary and Detail
Summary gives one row per day with totals for In and Away, plus a grand total. This is the view for "how many hours did they work last week".
Detail lists every period individually with start and end times. Use it when a total looks wrong and you need to see which shift caused it. Two labels matter here:
- carried in — the period began before your date range started, e.g. a night shift that started the previous evening
- still open — no closing status change was recorded, so the period runs to the end of the range. Usually someone who forgot to mark Out.
Print / PDF produces a clean printable version of whichever view you're looking at.
How Time Is Counted
- Time accrues to whichever status was active at the start of each period. Only In and Away accumulate; Out does not.
- A shift crossing midnight is split, so each day gets the hours that belong to it.
- Days are grouped by your timezone, not the server's. A shift ending at 11pm lands on the day you'd expect, even when the server sits in another timezone.
- Deactivated people can still be reported on — exactly what you need after someone leaves.
What It Can and Cannot Tell You
The report is accurate about what was recorded. It cannot know about anything that wasn't. Someone who forgets to mark Out will show an overlong shift until the record is corrected; someone who marks In from home when they meant to mark Away will be counted as In.
With Require PIN off there's a further limit: changes are recorded as "USER" with no name, so the log shows what changed but not who changed it. If you want an attributable record, turn Require PIN on.
Treat the report as a well-kept record to review and question, not as an authoritative timesheet.
Log Growth
One line per status change, roughly 80 bytes. A 50-person board with four changes each per day produces about 6MB a year — small, but it grows forever by design, because deleting it would destroy the history the report depends on. It's included in both backup methods.
Backups
Your board's data lives in files on your own server. There are two ways to protect it, and they suit different situations.
Method 1 — Download Backup (no setup)
In the admin settings panel, click Backup. You get a .zip containing:
inout-data.json— people, PINs, divisions, settings, notesinout-prefs.json— per-person preferencesinout-status-log.jsonl— the full status history behind the Hours ReportRESTORE.txt— plain instructions, so an archive found in a year explains itself
No shell access, no cron, no configuration. Works everywhere. Do this before any change you're unsure about — bulk edits, division renames, deactivating several people.
Staff photos are not included, as they're bulky and easy to re-upload. Copy the images/ folder separately if you want them covered.
Method 2 — Scheduled Backups (recommended)
inout-backup.sh takes complete snapshots automatically and thins them with age:
- hourly/ — every run, newest 48 kept (about two days)
- daily/ — first run of each day, newest 30 kept (about a month)
- weekly/ — first run of each week, newest 26 kept (about six months)
Every snapshot is a complete, standalone .zip — there's no chain to replay. To restore, open one and copy back what you need.
Setup
- Upload
inout-backup.shinto the same folder asinout-data.php - Make it executable:
chmod +x inout-backup.sh - Run
./inout-backup.sh --check
There are no paths to edit. The script works out where it is and where to put backups. --check makes no backup — it reports what it found, flags anything wrong, and prints the exact cron line to paste with your real paths already filled in:
[ok] Found inout-data.php
[ok] zip is available
[ok] Backup folder is outside the website
Add this line to your crontab to run hourly:
0 * * * * /home/yourname/yourdomain.com/inout-backup.sh
On a hosting control panel, use that path as the command and set the schedule to hourly.
Where Backups Are Stored
By default, one level above your website folder, in inout-backups/. This is deliberate: the archives contain every PIN in plain text. If they sat inside the website they could be downloaded by anyone who guessed the path. The script refuses to run if you point it somewhere web-accessible, and writes a .htaccess as a second line of defence for Apache.
inout-data.json is in there and readable.
Restoring
- Copy
inout-data.jsonfrom the archive into the folder containinginout-data.php, replacing the existing file - Do the same for
inout-prefs.jsonandinout-status-log.jsonlif present - Reload the board
That's the whole process. Program files aren't included in the one-click backup because you already have them from your download.
Security & Privacy
Two independent controls, protecting different things. Understanding which does what will save you a support call.
Company Access Code — who can see the board
A 4-digit code required before the board loads at all. Entered once per device and then remembered. This is what stops someone outside your organization viewing your staff list if they find the URL.
Require PIN — who can change what
When on, each person has a PIN and can only change their own status and note. Admins can change others'. Every change records who made it, giving you an attributable history.
When off, anyone who can see the board can change anyone's status. Changes are recorded as "USER". This is a reasonable choice for a trusted internal network or a shared wall display — but it is a convenience setting, not a security one.
| Your situation | Suggested setting |
|---|---|
| Private network, no internet access | Both optional |
| Office LAN, board on the wall | Access Code on, Require PIN off |
| Reachable from the internet | Both on |
| You need to know who changed what | Require PIN on |
| You want accurate hours reports | Require PIN on |
Brute-Force Protection
A 4-digit code is only 10,000 combinations, so both the PIN and the Access Code are rate-limited server-side. The first few wrong attempts are free — a typo costs nothing — after which each attempt is slowed progressively.
After repeated failures, PIN entry is refused from that address for 15 minutes. Entering the correct PIN clears the counter, so one person fumbling theirs won't lock out a shared office address for everyone.
The Access Code is slowed but never blocked outright — it's a shared code that every legitimate device sends, so blocking it would take out the whole office and refuse the correct code once someone finally typed it.
What Is Stored, and Where
- Everything lives in files on your own server. There is no external service, no account, and no data sent anywhere.
- The board makes no outbound requests — fonts, icons and this documentation are all served from your install. It works on an isolated network with no internet access.
- PINs are stored in plain text in
inout-data.json. They are a convenience credential for a wall board, not a password — tell your staff not to reuse a PIN they use anywhere else. - The board never receives other people's PINs. Only an authenticated Global Admin, in the admin panel, is sent them.
- Change history records an internal reference rather than a PIN, so no PIN is ever exposed through an audit trail.
Photos
Photo upload requires a Global Admin PIN. Uploaded files are checked by content rather than filename, so a file renamed to .webp won't pass.
License Activation
Creative In/Out includes a 30-day free trial with no user limit, so you can evaluate it at your real headcount. An amber banner shows the days remaining.
To Activate
- Open the admin panel and sign in
- Click Expand to open the settings panel
- Scroll to the License row
- Paste your complete license key — it is several hundred characters long, so make sure all of it is pasted
- Click Activate — the badge updates and the banner disappears
User Limits
Your license sets how many active people the board may hold. Deactivated people don't count, so someone who leaves frees their seat while their record and history are kept.
As you approach the limit, a banner warns you. At the limit, adding or reactivating someone is refused with a clear message rather than failing silently. Existing people are never affected — a board over its limit stays fully usable and you can deactivate someone to bring it back into range.
board.acme.com and acme.com are different domains. If you need to move, contact support for a replacement key.
Trial Expiry
If the trial expires without activation, the board becomes read-only. All data is preserved and nothing is deleted. Activating a valid key immediately restores full functionality.
Auto-Out Cron Job
Auto-Out marks everyone still In as Out at a set time each day. Setting the time in admin is not enough on its own — a server cron job has to trigger it.
Step 1 — Set the Time and Timezone
In the admin settings panel, set the Auto-Out time and click Save. Beside it, set your timezone and click Save.
Step 2 — Upload inout-cron.php
Confirm inout-cron.php is in the same directory as your other files.
Step 3 — Set Up the Cron Job (Dreamhost)
- Log into your Dreamhost panel at
panel.dreamhost.com - Go to Advanced → Cron Jobs → Add New Cron Job
- Command:
/usr/bin/php /home/your_username/yourdomain.com/path/to/inout-cron.php - Frequency: once per hour, or every minute for exact timing
- Click Save
How It Works
Each run checks whether the current time — in your configured timezone — matches the Auto-Out time. If it does, and it hasn't already run today, everyone still In or on the third status is marked Out, recorded as "by: auto". Deactivated people are skipped.
Clearing the third status matters: someone left on Lunch overnight is exactly the stale reading the board shows in muted colour, and leaving them there would defeat the purpose.
These changes are written to the status log like any other, so an auto-out closes the day's shift in the Hours Report rather than leaving it open indefinitely. That alone makes Auto-Out worth configuring if you use the Hours Report.
URL-Based Cron (Alternative)
If your host doesn't support command-line cron, trigger the script over HTTP. Open inout-cron.php, set a secret in CRON_KEY, then call:
https://yourdomain.com/path/to/inout-cron.php?key=your-secret-key
Updates
The board checks its own version against the server's, on load, periodically, and whenever you switch back to the tab. When they differ, every open board shows a full-screen update notice that can't be dismissed. Accepting it clears the browser's caches and reloads onto the new version.
This matters because presence boards get left open for weeks on wall displays and phones. Without it, half your users would still be running last quarter's version.
Applying an Update
Upload inout-data.php last. Everything else first, then that file. It carries the version number the clients compare against, so uploading it early makes boards start updating before the new files are in place — and they'd reload straight onto the old version.
- Take a backup first — admin → Backup
- Upload the new
.html,sw.js, and any other changed files - Upload
inout-data.phplast - Within a minute, open boards show the update notice
Your data is never touched by an update. Only program files are replaced.
The version currently running is shown in the header badge, and in the admin Install Check.
Mobile Use
Public Board on Mobile
Below 820px — phones and smaller tablets — the layout changes:
- Cards stack: status pill, contact icon, name and timestamp on one line; division and role below; the note full-width beneath that
- Tap the status pill to open a panel with all three statuses and the note field
- Tap a name or the contact icon for contact details
- Press and hold a truncated note to read it in full
- Peek and the birthday list move into the header, next to the theme toggle
- Print is hidden — the output isn't usable from a phone
Admin Panel on Mobile
Fully usable, though designed primarily for desktop. Settings rows stack and edit forms go full-width. Everything including the Hours Report and backups works.
Adding to Home Screen (PWA)
iPhone (Safari): tap Share → Add to Home Screen. The board shows a one-time banner explaining this, since iOS offers no prompt of its own. Dismiss it and it won't return.
Android (Chrome): tap the menu (⋮) → Add to Home Screen, or accept the install prompt.
Once added, the board opens full-screen with no browser bars. On Android the Back button closes whatever panel is open rather than exiting the app, closing one layer at a time.
Troubleshooting
The board looks wrong — plain fonts, everything wider
Cause: the fonts/ folder didn't make it to the server, so the browser is substituting system fonts.
Solution: upload the fonts/ folder alongside the HTML files. Install Check reports this specifically. The board works either way — it just doesn't look like the product.
"Could not load board data"
Cause: the board can't reach inout-data.php.
- Confirm
inout-data.phpandlicense-validator.phpare in the same directory asinout-board.html - Confirm the directory has write permissions (
755) - Visit
yourdomain.com/inout-data.phpdirectly — it should return text starting with{ - If it shows a PHP error, confirm PHP is enabled on your hosting
"Too many incorrect PINs. Try again in about 15 minutes."
Cause: brute-force protection. Too many wrong PINs came from your address.
Solution: wait it out — the block clears itself. A correct PIN entered later resets the counter. If a whole office shares one external address, one person repeatedly mistyping can trigger this for everyone; the block is deliberately short for exactly that reason.
"Admin Sign-In Required" when saving
Cause: changes to people or settings need a Global Admin PIN, and the session no longer has one.
Solution: sign in again and retry. If it persists immediately after an update, confirm inout-admin.html uploaded correctly — an older copy doesn't send the credential the server now requires.
Photos Not Uploading
- Create an
images/folder in the same directory, permissions755 - Photo upload requires a Global Admin PIN — confirm you're signed in as one
- Only JPG and WebP are accepted, and files are checked by content rather than by name
Backup button does nothing
Cause: usually PHP's zip extension is missing on your host.
Solution: the message will say so. Ask your host to enable it, or use the scheduled backup script (Section 7), which uses the system zip command instead.
Status Changes Not Saving
- Check the license banner — if the trial expired, activate your license
- Confirm the directory has write permissions (
755) - With Require PIN on, confirm you're signed in and have authority over that record
"by: USER" instead of a name
Cause: Require PIN is off, so there's no signed-in person to attribute the change to.
Solution: enable Require PIN and give everyone a unique 4-digit PIN. This also makes the Hours Report attributable.
Hours Report shows an impossibly long shift
Cause: someone didn't mark themselves Out, so the period is still open and runs to the end of the range. Switch to Detail view — it's labelled "still open".
Solution: configure Auto-Out (Section 10) so days close automatically.
No Hours button on the contact card
It appears only for Global Admins, and for Division Admins viewing their own division. If Require PIN is off, nobody is signed in on the public board — use the admin panel instead, which always requires a PIN.
Auto-Out Not Working
- Confirm the cron job is set up and running — see Section 10
- Confirm
inout-cron.phpis uploaded - Confirm the Auto-Out time is saved (click Save after setting it)
- It fires once per day — to test, set the time to a minute from now
Board Not Updating Automatically
The board refreshes every 10 seconds, pausing while a panel is open so it can't redraw underneath you. If changes aren't appearing on another device, force-refresh (Ctrl+F5 / Cmd+Shift+R) and confirm both are on the same URL.
An update notice keeps reappearing after reloading
Cause: the browser is still serving a cached copy of the old page.
Solution: confirm sw.js was uploaded with the rest of the update. If it persists, unregister the service worker once via the browser's developer tools (Application → Service Workers) and reload.
FAQ
Product
inout-data.json, inout-prefs.json and inout-status-log.jsonl to the new location. Because license keys are tied to a domain, contact support for a replacement key if the domain is changing.Support
inout-data.php until last, and every open board updates itself within a minute. Your data is never touched.