Harvard Innovation Labs · Internal Reference

Decision Logic + Update Guide

How the Program Finder quiz works, how results are built, and exactly where to go when something needs to change.

On this page

Section 1

File Architecture — What Lives Where

Two files do all the work. One file you edit often. One file you almost never touch.

✏️ ilab-data.js Edit this
  • All program signup links (LINKS)
  • Every event that can appear in results (EVENTS)
  • Every office hours session (OHS)
  • The 3 recommended steps per persona + sector (STEPS_DATA)
  • Persona card copy and colors (PERSONAS)
  • Content resolver functions (getSteps, getEvents, getOHs)
🔒 founder_xp_generator.html Rarely touch
  • Quiz questions Q1–Q5 (HTML)
  • Quiz navigation logic (pick, fwd, back)
  • Persona scoring algorithm (calcPersona)
  • Results page renderer (renderResults)
  • Visual design and layout (CSS)

Rule of thumb: If the real world changed (new event, new link, new program), edit ilab-data.js. If the quiz itself needs to behave differently (new question, different routing), edit the HTML. You should almost never need to touch the HTML.


Section 2

Quiz Flow — Start to Results

Q1
Stage
Explore · Test · Propel
Q2
Goal
Feedback · Milestones · Community · Funding
Q3
Time Commitment
Light · Moderate · Heavy
Q4
Sector
LifeSci · Climate · DeepTech · Social Impact · General
Q5
Format
Remote · Hybrid · In-Person
calcPersona() — in founder_xp_generator.html
Answers are scored → Persona is assigned
Q1, Q2, Q3, Q4 all contribute. Q5 (format) does NOT affect persona — it only affects display.
Left column
3 Steps
From STEPS_DATA in ilab-data.js
Filtered by persona + sector
Right column
Events
From EVENTS in ilab-data.js
Filtered by tags, sorted by format
Bottom grid
Office Hours
From OHS in ilab-data.js
Filtered by persona tags

Section 3

Persona Scoring — How Someone Gets Routed

Quiz answers add points to four buckets. The highest scoring bucket wins and becomes the persona. Two hard overrides skip scoring entirely and route directly.

⚡ Hard Overrides — checked first, skip all scoring
if (sector === 'socialimpact') return 'impact'; if (time === 'light') return 'community';
If either of these conditions is true, the scoring table below is never consulted. The persona is locked immediately.
Quiz Answer Explorer Validator Builder Propeller
Stage (Q1)
Stage = Explore +5
Stage = Test +3 +2
Stage = Propel +1 +5
Goal (Q2)
Goal = Feedback +2 +3
Goal = Milestones +1 +3
Goal = Community +2 +1
Goal = Funding +1 +3
Time (Q3)
Time = Moderate +1 +2
Time = Heavy +3 +1

Worked Example

Someone answers: Stage = Explore · Goal = Feedback · Time = Moderate · Sector = Deep Tech

8
Explorer
+5 +2 +1
5
Validator
+3 +2
0
Builder
0
Propeller

Result: Explorer persona. Deep Tech sector is then used to customize which step 2 they see — but it never changed the persona itself.

The Six Personas

🌱
Explorer
High explore score. Still figuring out the idea.
🧪
Validator
High feedback + moderate time. Testing a real problem.
🏗️
Sprint Builder
High builder score + heavy time commitment.
🚀
Growth Founder
High propeller score. Traction exists, building momentum.
💚
Impact Founder
Hard override: sector = Social Impact
🤝
Community First
Hard override: time = Light

Section 4

Two Dimensions — Persona and Sector

Dimension 1 — Persona

Who you are as a founder

Determined by quiz scoring. Controls the shape and tone of the results page — headline, description, recommended journey stack.

Dimension 2 — Sector

What you're building

Selected directly in Q4. Never changes the persona. Only changes which specific steps, events, and programs appear inside that persona's results.

← PERSONA
Life Sci Climate Deep Tech Social Impact General
🌱 Explorer OOH + Primer OOH + Primer OOH + Hackathon OOH + Primer + SIFF OOH + Primer + Hackathon
🧪 Validator Sys Dynamics + OOH Primer + OOH Primer + OOH Primer + OOH + SIFF Primer + OOH
🏗️ Builder Sys Dynamics + Sprint Sprint (default) Vibe Coding + Sprint Sprint + SIFF Sprint
🚀 Propeller Accel Sessions Accel Sessions AI Agents + Accel Accel Sessions + SIFF Accel Sessions
💚 Impact Always routes here when sector = Social Impact — sector column becomes irrelevant
🤝 Community Always routes here when time = Light — only community events shown, sector irrelevant

Highlighted cells = sector-specific programming exists. Others fall back to default path.


Section 5

Tag System — How Events Surface

Every event and office hour has a tags array. Think of it as a subscription list — the event declares who it is relevant to. The quiz asks "which events have subscribed this founder?" and shows those.

tags: ['builder', 'deeptech']
Builder tag: Any founder routed to the builder persona sees this event.
Deeptech tag: Any founder who selected Deep Tech as their sector sees this event surfaced first, regardless of persona.
Both tags work independently — either one is enough to surface this event.
tags: ['community', 'explorer',
'validator', 'builder',
'propeller', 'impact']
Every persona tag listed: This event shows for everyone. Used for community events like the Launch Party and Founder Circles that are open to all members.
tags: ['lifesci']
Sector tag only: This event surfaces only for Life Sci founders, regardless of their persona. Used for sector-specific workshops like System Dynamics.

All valid tag values

Persona tags

explorer validator builder propeller impact community

Sector tags

lifesci deeptech climate socialimpact general

Sort order: Events matching the founder's selected sector surface first. Then events matching their persona fill in. Within each group, events matching their format preference sort to the top. Maximum of 4 events shown per result page.


Section 6

Steps Logic — How the 3 Recommended Actions Are Built

Steps are a lookup table. Each row says: "For this persona, in this sector, at this step number — show this action." Three sector keywords control the priority.

sector: 'lifesci'

Sector-specific

Wins for founders in that exact sector. Override the default for this persona.

sector: 'default'

Fallback

Shows when no sector-specific row exists. Every persona should have one per step.

sector: 'all'

Universal

Always shows, regardless of sector. Use for steps that apply to everyone in this persona.

Priority Order — for each step number

Sector-specific row
e.g. sector: 'lifesci'
not found?
Default row
sector: 'default'
not found?
All row
sector: 'all'

Example: Builder persona — who sees what at Step 1

STEPS_DATA → builder array
persona
sector
step
action
builder
lifesci
1
Register: System Dynamics for HC + Life Sciences wins for LifeSci
builder
deeptech
1
Register: Vibe Coding Workshop wins for DeepTech
builder
default
1
Commit to the Customer Discovery Sprint wins for Climate, General, others
builder
all
3
Register for MVP Feedback Session shows for everyone

Section 7

Two Types of Updates

Every change you will ever make falls into one of two categories. Identifying the type first tells you exactly which file to open.

Type 1 — Catalog Update
Something in the real world changed

A new event was added. A link changed. A session was cancelled. A step description has an old date. These are factual updates to what exists — you're keeping the catalog accurate.

File to open: ilab-data.js — LINKS, EVENTS, OHS, or STEPS_DATA sections

Type 2 — Logic Update
Who sees what needs to change

An event should now surface for a different persona. A step should be different for Climate founders. Too many people are landing on the wrong persona. You're changing the rules of who gets shown what.

File to open: ilab-data.js (tags or STEPS_DATA) or founder_xp_generator.html (calcPersona)


Section 8

How-To — Common Update Tasks

Type 1 — Catalog Updating a link
1
Find the program row in the Links tab of your Google Sheet
The key column tells you the exact identifier (e.g. SPRINT_SIGNUP)
2
Open ilab-data.js on GitHub → find the LINKS section at the top
Ctrl+F the key name to jump directly to it
ilab-data.js → LINKS
3
Replace the '#' or old URL with the new URL
Commit the change — it goes live immediately
Type 1 — Catalog Adding a new event
1
Add a row in the Google Sheet → Events tab
Fill in all columns. Set active to yes. Decide which tags it should carry.
2
Add the same event as an object in ilab-data.js → EVENTS array
Copy an existing event object as a template. Change the id, name, date, format, tags, desc.
ilab-data.js → EVENTS
3
If it needs a signup link, add the key to LINKS first
Add the key to LINKS, then reference it in the event object if needed
Type 1 — Catalog Removing a cancelled event
1
Find the event in ilab-data.js → EVENTS
Never delete the row — future semesters you may want to bring it back
ilab-data.js → EVENTS
2
Change active: true to active: false
The event immediately disappears from all results. The row stays in your data for reference.
Type 2 — Logic Making an event show for a different persona
1
Find the event in ilab-data.js → EVENTS
ilab-data.js → EVENTS
2
Add or remove the relevant persona or sector tag from the tags array
Example: to show this event for validators, add 'validator' to tags. To stop showing it for builders, remove 'builder' from tags.
Type 2 — Logic Changing a recommended step for a persona
1
Open ilab-data.js → STEPS_DATA
ilab-data.js → STEPS_DATA
2
Find the right persona block, then the right sector and step number
e.g. builder → sector: 'lifesci' → step: 1
3
Edit the a: (action title) and/or d: (description) fields
To add a new sector-specific path, add a new row with the sector name. The default row still covers everyone else.
Type 2 — Logic Changing how personas are scored / routed
1
Open founder_xp_generator.html → find calcPersona()
This is the only function in the HTML you should ever need to edit for content reasons
founder_xp_generator.html → calcPersona()
2
Adjust the point values to change relative weighting
Higher number = stronger pull toward that persona. Refer to the scoring table in Section 3 of this page to understand current weights before editing.
3
To add a hard override, add it at the top of the function
Example: if (sector === 'climate') return 'impact'; — this skips all scoring for Climate founders

Section 9

Semester Update Checklist

Run through this at the start of every semester. In order.

  • Duplicate the Google Sheet and rename it for the new semester Google Sheet
  • Update every URL in the Links tab — confirm no '#' placeholders remain ilab-data.js → LINKS
  • Set active: false for any events that are not running this semester ilab-data.js → EVENTS
  • Add new events as objects with correct tags and format ilab-data.js → EVENTS
  • Update office hours schedules and set active: false for anything not running ilab-data.js → OHS
  • Review each step in STEPS_DATA — update dates in action titles and descriptions ilab-data.js → STEPS_DATA
  • Update the header eyebrow text ("Summer 2026") in the HTML if semester changed founder_xp_generator.html → header
  • Push all changes to GitHub
  • Test at least 6 persona combinations — one per persona — and verify links work
  • Test retake flow — confirm quiz resets cleanly from results page

Section 10

Quick Reference

I want to change… Update type File Location in file
A signup or info link Type 1 ilab-data.js LINKS section at top
An event name, date, or description Type 1 ilab-data.js EVENTS array — find by id
Hide a cancelled event Type 1 ilab-data.js EVENTS → active: false
Add a new event Type 1 ilab-data.js EVENTS → add new object
Office hours schedule Type 1 ilab-data.js OHS → sched field
Step action title or description Type 1 ilab-data.js STEPS_DATA → a: or d: fields
Persona card headline or description Type 1 ilab-data.js PERSONAS → hl: or desc: fields
Which persona or sector sees an event Type 2 ilab-data.js EVENTS → tags: [] on that event
Which persona sees an office hour Type 2 ilab-data.js OHS → tags: [] on that OH
What a persona sees at step 1, 2, or 3 Type 2 ilab-data.js STEPS_DATA → find persona + sector + step
Add a sector-specific step path Type 2 ilab-data.js STEPS_DATA → add new row with sector name
How personas are scored / weighted Type 2 founder_xp_generator.html calcPersona() function
Add a hard override (always route X to Y) Type 2 founder_xp_generator.html calcPersona() — top of function
Quiz questions or answer choices Type 2 founder_xp_generator.html Q1–Q5 HTML blocks
Design, colors, or layout Design founder_xp_generator.html CSS :root variables + style rules