Inspiration

I'm a community college student planning to transfer, and every time I opened ASSIST.org I ended up with six tabs and a notebook. ASSIST tells you which of your college's courses satisfy a UC requirement, but it doesn't know anything about you. It won't tell you which ones you've already taken, and it only shows one school-to-school agreement at a time. So if you're deciding between three campuses, you're comparing three long PDFs by eye and hoping you didn't miss a row.

What it does

It's a Chrome extension that runs on top of ASSIST.org.

  • You paste your course history in once, from your college portal.
  • On any agreement page, courses you've already completed turn green, partial matches turn yellow, and untouched ones stay gray.
  • A sidebar shows your overall progress and groups the remaining requirements into buckets.
  • A multi-school view lets you pick several campuses and majors at once and see the combined picture, so you can tell which courses count everywhere and which ones only serve one school.
  • Everything runs locally. Your transcript never leaves your browser.
  • Full English and Chinese interface, defaulting to your browser language. ## How we built it Vanilla JavaScript, HTML and CSS as a Chrome extension, no framework.

The real work was the data. ASSIST loads its agreements from a JSON endpoint, and the response is unusual: the outer envelope is normal JSON, but every meaningful field inside it is a JSON string that has to be parsed a second time. The two fields that matter are templateAssets, which holds the requirement structure, and articulations, which holds the actual course mappings.

The articulations are a two-level boolean tree. A requirement can be satisfied by course A and B, or by C alone, and the And/Or joins are stored positionally as spans across course groups rather than as one flat operator. Matching a student's completed courses against that meant walking the tree properly instead of doing string comparison.

Transcripts are stored as raw course codes rather than pre-matched results. That single decision is what makes the multi-school view possible: one import gets re-matched against whichever agreement you open, so adding a fourth campus costs the user nothing.

Challenges we ran into

The API rejected me for two days. Every request came back 400 Bad Request. The site was reading an anti-CSRF token from a cookie and echoing it back as a request header, and my requests had the cookie but not the header. Nothing in the response said so.

I tried to intercept the page's own requests and failed. I patched fetch, and nothing fired. ASSIST uses XMLHttpRequest. Rather than patch that too, I changed approach and had the extension make its own same-origin request, which turned out cleaner anyway.

The structure lied about its own order. Rows carry a position field that doesn't match their array index — the first row in the array had position 4. Rendering in array order silently produced a scrambled requirement list. That one cost me a while, because nothing errored; it just looked slightly wrong.

The gap that changed the design. A UCSD agreement returned 8 articulations, but the requirement list had 10 rows. Requirements with no equivalent at my college simply have no entry at all. Iterating over articulations would have quietly hidden exactly the courses a student most needs to know about. I rewrote it to iterate over the requirement structure and left-join the articulations.

Parsing the transcript. My college's portal puts the grade on its own line, several lines below the course code, so line-by-line parsing produced nonsense. It had to be block-based.

Accomplishments that we're proud of

The multi-school view works, and it merges interchangeable courses — honors and support variants of the same course — into a single row instead of showing near-duplicates.

It's not hardcoded to my college. The architecture treats school, major and academic year as inputs, so it works for any pair ASSIST supports.

And it's bilingual. A lot of the students who need this most are reading requirement documents in their second language.

What we learned

Most of my time went to understanding someone else's data model, not to writing features. The 8-versus-10 discrepancy is the thing I keep thinking about: the code ran fine and produced a confident, wrong answer. I only caught it by counting rows by hand against the live page. I now check the shape of data against reality before trusting anything I build on top of it.

I also learned to stop patching around a system and just ask it directly. The fetch interception was clever and wrong; the plain request was boring and worked.

What's next for assist插件

A general education panel, tracking Cal-GETC and IGETC areas alongside the major requirements — right now the extension answers half the question, and GE is the other half.

After that, publishing it. It's been useful to me for months and I've been treating it as a personal tool. The next step is getting it in front of the students it was built for.

Built With

  • javascript?html?css?chrome-extension
Share this project:

Updates

Submission history