Written 2026-08-01. Nothing here is built yet.
The goal these three serve: beat I-CAR for a student with zero knowledge AND for a 20-year technician, in the same course. I-CAR's weakness is that it is one linear path that tests recall once and never comes back. Each upgrade below attacks that from a different side.
Read the storage note at the bottom before planning any video work.
Right now every student walks the same 40 slides in the same order. A first-week student drowns. A 20-year tech is bored by slide 6 and stops taking the course seriously. I-CAR has this exact problem and has never solved it.
At the start of each unit, before the first lesson, one screen:
How much of this do you already know? Nine quick questions. Not graded, nothing saved to your record. It only decides how much detail we show you. [ Start ] [ Skip, show me everything ]
Nine questions pulled live from that unit's ASE categories, mixed difficulty. Then one result screen that routes them:
| Score | Door | What it means |
|---|---|---|
| 0 to 3 | LEARN IT | Every step spelled out, every term defined, the everyday analogy first |
| 4 to 6 | DO IT | The lesson exactly as it is today |
| 7 to 9 | PROVE IT | Skip the teaching, go straight to the lab and a hard scenario |
The result screen never says "you are a beginner." It says: "You already know the basics here. We are going to skip ahead and put you straight on the car."
Inside the lesson, the door changes what renders:
A permanent escape hatch on every slide. A small control in the gear menu: "Show me more detail" / "Speed this up." A student can change doors mid-lesson and it sticks for the rest of the unit. Never trap someone behind a placement test.
In dashboard2, on the Class page, a fourth card: Where the class placed. How many students landed in each door per unit. A unit where 80% place into LEARN IT tells you that unit needs more time in class. A unit where half place into PROVE IT tells you they already know it and you can move faster. That is a teaching signal you do not get anywhere today.
generateASEExam path the simulator already uses,
filtered to the unit's ASE categories (ACADEMY_UNIT_CATS[mod][unit] already maps this).
Zero new content authored.academy_placement/{uid} = { "B5-U2": {door:"prove", score:7, at:<ms>} }.
One read on Academy open, one write per placement. Same cheap pattern as question_discovery.DEPTH: learn
(or do, or prove, default do), read by the same filter in academy-player.html that
already strips instructorOnly slides for students. The player already knows how to hide
slides from a deck without breaking numbering, and the NOAUDIO work proved we can add a
slide field without disturbing narration.academy-search-index.js) that already maps a topic to the exact slide that teaches it.
That index was built for search and it is exactly what this needs.Medium. The router, the placement doc, the depth filter, and the escape hatch are roughly a day. The real cost is content: for the LEARN IT door to mean anything, the simplest lessons need 2 to 4 extra plain-language slides each. That is an authoring pass, not a code pass, and it can be done module by module. Until those exist, LEARN IT and DO IT render identically and nothing breaks. That is the right way to ship it: turn on the router first, add depth over time.
DEPTH: always shows in every door. Safety, PPE, and HV lessons get that mark by default.A student passes the B5 battery lab in September. The ASE test is in May. By then it is gone. Every certification course on the market has this hole, including I-CAR. Closing it is the single biggest thing you can do to actually raise pass rates, and it costs almost nothing to build because the content already exists.
A new card on the simulator dashboard, under the streak card:
BRING IT BACK 6 things are ready for review. About 4 minutes. [ Start ]
Six to ten questions, each one drawn from a lesson they finished a while ago. Each question is answered, checked, and explained immediately, exactly like the existing Review practice mode. Nothing new to build in the exam engine.
The schedule per lesson, from the day they complete it: 3 days, then 10 days, then 30 days, then 90 days. If they get a lesson's question right, it moves to the next interval. If they get it wrong, it drops back to 3 days and shows a "Review the lesson" link straight to the slide that teaches it.
The nudge matters more than the feature. The dashboard card, a count badge on the Academy nav item, and an optional weekly email ("7 things are ready, about 5 minutes"). Without a nudge this gets used once and forgotten.
A streak that is worth having. Not days logged in. Days where the queue was cleared. That is a habit worth building and it is honest.
On the Class page, a fifth card: Retention. Which topics the class is forgetting, ranked worst first, measured as "answered right when first taught, answered wrong on the 30-day return." That is a completely different signal from the existing Weakest Topics card, which only shows what they never learned. This shows what they learned and lost. No other course tells an instructor that.
asetasks slide, so the mapping is already authored.
No new questions written.academy_retention/{uid} =
{ "b5-l04": {due:<ms>, step:2, lastResult:"ok"} }. One read on dashboard load, one debounced
write per session. Same shape and same cost as the flag locker._completeLesson sets fin and pushes maxReached),
so the trigger that puts a lesson into the queue already fires today.Small to medium. This is the best value in the whole document: high impact, almost no new content, and it runs on three things that already exist (the question bank, the task citations, and lesson completion). If only one upgrade gets built, build this one.
The lab rating today is a score and a set of tick boxes. It says the work happened but shows nothing. A shop hiring your student cannot see anything, you cannot settle a dispute months later, and the student has nothing to be proud of.
On the lab results slide, above the instructor rating:
Show your work Take a photo of your panel before Mr. Hernandez rates it. [ Take Photo ] (opens the phone camera directly)
One photo per attempt. It appears immediately as a thumbnail. They can retake it before the rating is saved, and not after. Once rated, the photo sits permanently next to the score, so their own lab history becomes a visual record of getting better: attempt 1 next to attempt 3.
On the grading slide, after picking the student, their photo loads next to the rubric. He grades looking at the actual work on his phone, which is how he already grades. In the dashboard2 Gradebook, a small camera icon on any row with a photo, and clicking the row shows it full size.
lab_photos/{uid}/{deckId}/{attemptNumber}.jpg.photo: "<storage path>", per attempt inside the existing
attempts[] array in lab_grades/{uid}. That array is already capped at 12 entries (first plus
latest 11), so photo count is capped for free, and the cap already protects the 1 MB document
limit.lab_photos/{uid}/ prefix, only
image content types, and only files under 300 KB. The rule is what actually enforces the
ceiling, so a bypassed or broken client cannot upload a 12 MB phone original. The 300 KB rule
sits deliberately above the 100 KB target so a rare stubborn photo still goes through, but a
raw upload never can. Read is the owner or an admin, matching the existing lab_grades rule.lines[] is positional and the export is already built, so
the photo path rides along in the existing JSON export with no schema break.Small. It is one upload control, one compression helper, one Storage rule, one field on a record that already exists, and a thumbnail in two places that already render.
lab_photos/, and deletes
anything older than 365 days, then clears the photo field on that attempt so the Gradebook
does not show a broken thumbnail. Deleting the file without clearing the field is the bug
to avoid here.Both numbers below are Mario's decisions: a 100 KB hard ceiling per photo and a one-year retention sweep.
| One photo, capped at 100 KB | 100 KB |
| One student, all 391 labs, one photo each | about 39 MB |
| A class of 50 for a year | about 2 GB |
| Firebase Storage free allowance | 5 GB stored |
| Cost past the free tier | about $0.13 per month per 10 GB |
With the one-year sweep, that 2 GB is the steady state, not a yearly addition. Storage stops growing after year one instead of climbing forever. You stay inside the free 5 GB allowance at up to roughly 120 students a year, and even at 200 students you would be paying pennies a month. The compression loop and the 300 KB Storage rule are what hold the line; without them a single class of phone originals is 40 GB.
Slide images are 685 MB and narration audio is 686 MB, and both are served from Hosting, which allows 10 GB. They do not touch the Storage allowance at all.
| Where you host it | What happens |
|---|---|
| Firebase Hosting | The whole site gets 360 MB of transfer per day free. One 50 MB clip is about 7 views before the entire site is out of bandwidth for the day. Not viable. |
| Firebase Storage | Egress is $0.12/GB. A class of 30 watching one 50 MB clip is $0.18. A hundred clips across a school year is roughly $18/month. Breaks the $0 rule. |
| Unlisted YouTube | Free, unlimited, adapts quality to the student's phone signal. |
Use unlisted YouTube, and the lesson builder already supports it. The video slide type takes
a YOUTUBE: field and embeds through youtube-nocookie.com with rel=0, so no cookie is set
before play and no unrelated videos appear at the end. Unlisted means it does not appear in
search or on your channel, and there are no ads unless you enable them.
Self-hosting is worth it only for very short clips (under about 10 seconds, no audio) that you would rather never leave the site. Those are small enough not to matter. Everything longer goes on YouTube.
One rule that stays regardless: the slide's bullet points must teach the point on their own, so a pulled or network-blocked video degrades to a normal slide instead of breaking the lesson.