Shown in the browser tab and logo area. To make it permanent, update APP_NAME in config.php.
Workforce mapping & caseload visualization — PHP / MySQL.
Maps: Google Maps (AdvancedMarkerElement, clustered) · Geocoding: Google.
Integrations: CareerOneStop · Google Places · Microsoft 365 / OneDrive.
AI providers: Groq · OpenAI · Gemini · Claude.
Version is manual in config.php · Build is the cache-buster on script tags · Released auto-updates from the deploy date.
Click any layer to open the full-screen editor. Add, edit, import CSV, sort, or reset each layer. Changes save to server automatically.
Rename any default layer. Changes apply immediately for all users.
Uncheck fields to hide them from non-admin users across pin popups, sidebar filters, color groups, and the Data tab. Admins always see everything. Changes apply immediately on save.
Links appear in the 🔗 Links topbar dropdown. Each link opens either as a right-side panel or a new browser tab.
Keys are stored server-side in config.php. The default provider is tried first — others activate automatically as backup.
Edit config.php to add or change keys: GROQ_API_KEY, OPENAI_API_KEY, GEMINI_API_KEY, ANTHROPIC_API_KEY.
Free credentials from the US Dept of Labor. Powers "Open Positions" in Job Match. Request free access →
Maximum minutes a signed-in user stays authenticated, counted from login (not from last activity). Users get a 401 and must re-authenticate after this elapses. Allowed range: 5–1440 minutes. Default: 120.
When ON, non-admin users see only caseload rows where their CRM Name matches one of the columns configured in their role's Caseload Hierarchy Scope. Admins and superadmins always see all rows. Users with no CRM name or an unscoped role see nothing.
Before enabling, audit the user table below — any user with a ⚠ No match badge will see an empty caseload once this is on.
Combined view of Microsoft 365 users who have signed in and manually-created local users. Data loads from the database on every refresh. Roles assigned here override the default role on next login.
| Name / Email | Type | Role | Last Login | CRM Name · match status | |
|---|---|---|---|---|---|
| Loading users… | |||||
Pre-register a Microsoft 365 user with a specific role. On first sign-in the stored role takes effect.
Each role defines which layers and features users with that role can access. Admin role is always full access and cannot be modified.
When enabled, all visitors must sign in with a Microsoft account. Role (Admin / User) is determined by Azure AD group membership.
1. Azure Portal → Entra ID → App registrations → New registration
Name: FlxMap Portal · Account type: This org only
Redirect URI type: SPA → paste the URI shown above
2. Manifest tab → find groupMembershipClaims → change null to "SecurityGroup"
⚠ Critical: Without this, the groups claim is missing and ALL users are denied.
3. API permissions → Add → Microsoft Graph → Delegated:
openid · profile · email · GroupMember.Read.All
4. Entra ID → Groups → New group
Create FlxMap Admins and FlxMap Users · type: Security · Add members
5. Copy Tenant ID, Client ID, and both Group Object IDs into the fields above
Accounts get a 15-minute lockout after 5 failed sign-in attempts (per IP or per username). Use this if a user is locked out and needs immediate access.
A stricter security policy runs silently in the background. Whenever it sees something that would have been blocked under enforcement, the browser logs it here. Use these reports to see what would break before we tighten the real policy. Empty list = ready to enforce.
Decides whether the stricter policy actually blocks violations or just logs them. Permissive (default) just logs \u2014 your existing app behavior is unchanged. Strict blocks any script that\u2019s not from an approved source, raising the bar against cross-site scripting attacks. Flipping is instant either way.
Add a second layer to your sign-in: a 6-digit code emailed to you at sign-in. No app to install or keep in sync. After enrollment, you'll be asked for a code every time you sign in.
Controls whether enrolled users actually need to enter their code at sign-in. Defaults to Off so you can enroll without risk of locking yourself out. Flip to Required for enrolled users when ready.
Automatically sign people out after a period of no activity \u2014 protects an unattended, signed-in workstation. Everyone, including admins, is subject to this. A warning appears 2 minutes before sign-out with a one-click "Stay signed in".
Email a list of people when notable security events happen (e.g. an account gets locked out after repeated failed sign-ins). Off until you add recipients.
Restrict admin sign-in and admin actions to specific networks (e.g. your office). Leave blank to allow from anywhere. Use with care \u2014 the app refuses to save a list that doesn\u2019t include your current IP, but a changing/dynamic IP could still lock you out (recovery: clear the admin_ip_allowlist setting in the database).
FlxMap reads CSV files from your OneDrive and SharePoint using your Microsoft 365 sign-in. Files you can access in OneDrive, FlxMap can access for sync.
Status: Checking…
When you click Connect, Microsoft asks you to authorize FlxMap to read your files. After that, you can browse your OneDrive and SharePoint sites from inside FlxMap, pick CSV files to sync, and refresh them on demand.
Each user manages their own sync sources independently — sources you configure are saved in your browser, not shared with other users.
Note: Sync is manual — click "Refresh now" on a source whenever you want to pull updated data.
Different from the user connection above. The cron runs unattended at 3 AM with no logged-in user — it needs its own Azure app-only credentials (client credentials grant). Without this, the scheduled sync can't authenticate to Microsoft Graph.
In Azure: register an app (or reuse the existing one) with Application permissions for Files.Read.All and Sites.Read.All, then click Grant admin consent. Copy the three values below.
Stored encrypted. Leaving this blank when editing keeps the existing secret unchanged.
When the cron geocodes addresses, results are cached so repeated syncs don't re-call Google. Failed lookups (junk addresses, ZERO_RESULTS) are also cached as negative entries — they're not retried unless the cache is cleared.
If you fix address data in the source file and want the cron to re-try previously-failed rows, clear the negative cache. Successful entries stay.
One-time cleanup actions. Use after a known issue or to free space. Each action shows what it will delete before doing anything.
_old_<datetime> tables. Run once when you want to reclaim disk space; the current rolling backup is preserved.Manage the columns of the active layer's table. Adding a column lets you map and store new fields from your CRM file. Renaming preserves data. Modifying type / length is metadata-only when the new type can hold the old values. Dropping a column is irreversible.
Credentials are stored in DATA_DIR/db_config.json — never in PHP source. Create a MySQL database in cPanel → MySQL Databases first.
1. cPanel → MySQL Databases
Create database (e.g. employu_emap)
Create user → Assign ALL PRIVILEGES
2. Upload to server (same folder as index.html)
emap_setup.sql · emap_seed.php
3. Enter credentials above → Save & Connect
4. Admin Settings → Database → Run Setup SQL
Creates all tables automatically
5. Visit /emap_seed.php?key=eMapSeed2026!
Imports existing JSON layer files into MySQL
Then delete emap_seed.php from server
Download a backup of your configuration as a single JSON file you can keep offsite. Includes settings, roles & permissions, Service Status setup (templates, subscriptions, watch-folders), custom areas, dashboards, and layer schemas. Configuration + map data also includes the map layer rows (offices, businesses) and service events.
Secret values (passwords, tokens, client secrets) are redacted from the file and must be re-entered after a restore. Even so, treat the file as sensitive and store it securely.
For local users, this updates your account password. For the legacy admin login (no user record), this updates the admin-only password. Microsoft 365 users should change their password via their Microsoft account portal. You will be signed out after changing.
Used to send invite emails to new local users and test notifications. Choose how the app delivers mail.
Controls how map pins group into clusters. Applies to every layer automatically. Changes take effect immediately and for all users.