What This App Does (Plain English) #
This web app helps you plan your academic journey term-by-term (Summer, Fall, Winter) from your start term to your graduation year. It shows a horizontal timeline with clickable cards. You can type notes for each term, and the app saves them in your browser so they stay there even if you navigate away or close the tab. You can also export your plan as a well-formatted
.txt file or print/save it as a PDF with a clean layout.
Quick Start (How to Use) #
- Open index.html in a modern browser (Chrome, Edge, Firefox, Safari).
- In the top form, choose your Start Term, Start Year, and Expected Grad Year.
- Click Generate timeline.
- Scroll left/right with the arrow buttons, drag the white area, or swipe on mobile.
- Click any term card to add or edit notes. Press Ctrl+Enter (or Cmd+Enter on Mac) to save quickly.
- Export with Download .txt or Print / Save as PDF.
- Use Clear notes if you want to remove all saved notes (there’s a confirmation dialog).
Project Structure #
index.html The main HTML page (structure, modals, print view).
styles.css Theming, layout (brand colors, timelines, modals, print rules).
app.js Logic: build timeline, save notes, export/print, scrolling, modals.
assets/ Logos and webfonts (.woff2).
High-Level Architecture #
Data Flow Diagram #

Key Concepts #
Terms and Years #
An academic year has three terms in this order: Summer, Fall, Winter. Cards are placed in three horizontallanes and many columns (one column per term).
Persistence (Saving Notes) #
Notes are saved in localStorage with a predictable key pattern:
<Term>-<Year>-<Index> e.g.,Summer-2026-0
Export and Print #
- Download .txt: Builds a structured text summary with headers, years, and terms.
- Print / Save as PDF: Switches to a hidden, print-optimized layout and uses the browser’s print dialog.
HTML Overview (Structure and Roles) #
Brand Bar and Header #
The brand bar shows TRU logos and the title. The header contains the action buttons and a small “How to use” list.

| < div class =” actions ” > < button id =” export Txt ” class =” secondary ” > Download . txt </ button > < button id =” print Pdf ” class =” primary ” >Print / Save as PDF </ button > </ div > |
Timeline Shell #
A left arrow, a scrollable viewport with the timeline content, and a right arrow:

| < div class =” track – shell ” aria – label =” Timeline ” role =” region ” > < button class =” nav left ” id =” nav Left ” > </ button > < div class =” viewport ” id =” viewport ” > < div class =” lane – labels ” id =” lane Labels ” > … </ div > < div class =” content ” id =” content ” ></ div > < div class =” years Track ” id =” years Track ” ></ div > </ div > < button class =” nav right ” id =” nav Right ” > </ button > </ div > |
Modals #
There are two modals:
- Editor (add/edit notes).
- Confirm Clear (safety before wiping notes).
Styling Highlights (CSS) #
Theme Variables #
Your CSS uses custom properties for easy theming:
| : root { — brand : #004 d66 ; — brand -2: #0 f6b82 ; — accent : #2 d6cdf ; — ink : #0 f1a2b ; — muted : # 667085 ; — bg: # f 6 f 8 fb ; — card : # ffffff ; — border : # e 5 e 7 eb ; — card – w: 220 px; — card – h: 110 px; — gap – x: 14 px; — gap – y: 10 px; — lane – label – w: 100 px; } |
Responsive and Print #
- @media (max-width: 840px) shrinks cards, labels, and logos.
- @media print hides interactive UI and shows a clean #printView.
JavaScript API (What Each Function Does) #
All logic is in app.js. Below are the most important functions in accessible, simple terms.
buildTerms(startTerm, startYear, gradYear) #
Tip: Creates an array like [{term: ’Summer’, year: 2026}, …] covering every term from your chosen start to your grad year.

| function build Terms ( start Term , startYear , grad Year ){ const items = []; let t = start Term , y = Number ( start Year ); while ( y <= grad Year ){ items . push ({ term : t, year : y }); const next Idx = ( ORDER . index Of ( t) + 1) % TERMS_PER_YEAR ; t = ORDER [next Idx ]; if ( t === ” Summer “){ y += 1; } // wrap to next academic year } return items ; } |
render(startTerm, startYear, gradYear) #
Tip: Builds and positions the clickable cards and the year ruler. Reads CSS variables so layout matches the theme.
Key steps:
- Read CSS metrics (–card-w, –gap-x, etc.).
- Create cards for each term (absolute positioning).
- For each card, attach a click handler that opens the editor modal.
- Build the bottom year ruler aligned with the cards.
- Reset horizontal scroll and enable/disable nav arrows appropriately.
getNote(key) and localStorage Keys #

| function get Note ( key ){ return local Storage . get Item ( key ) || “”; } |
Save happens when you click Save in the modal: the note is written to localStorage and the card preview shows the first line of your text.
groupByYear() & buildTxt() #
groupByYear() collects all current notes and sorts terms within each year (Summer, Fall, Win- ter). buildTxt()creates a neat, readable plain-text export including metadata and structured sections.

| export Txt Btn . add Event Listener (” click “, () => { const txt = build Txt (); const blob = new Blob ([ txt ], { type :” text / plain ; charset =utf -8 “}); const a = document . create Element (” a”); a. href = URL . create Object URL ( blob ); a. download = ” TRU_Timeline . txt “; a. click (); URL . revoke Object URL ( a. href ); }); |
refreshPrintView() & Print/PDF #
Builds a clean, print-only table view with headings, labels, and formatted notes. Then window.print()
opens the browser’s dialog, where Save as PDF is available.
Scrolling and Dragging #
- Arrow buttons adjust an x offset and apply transform: translateX(x).
- Dragging on desktop and swipe on mobile update the same x value.
Safety: “Clear Notes” Confirmation #
Clicking Clear notes opens a confirmation modal. Only when you confirm does the code remove timeline-related keys from localStorage.
Accessibility and Keyboard Shortcuts #
- Modals declare role=”dialog” and aria-modal=”true”.
- Esc closes modals; Ctrl+Enter / Cmd+Enter saves notes in the editor.
- The timeline region has aria-label=”Timeline”.
Design Decisions (Why Things Are This Way) #
- Vanilla JS only: fast to load, no bundler or framework needed for students.
- localStorage: simple, persistent per-browser storage; perfect for a single-user planner.
- CSS variables: easy to retheme (e.g., update –brand, –accent once).
- Print view: a separate, hidden section generates a professional PDF without custom libraries.
Customization Guide #
Change Colors and Sizes #
Edit these in styles.css:

| : root { — brand : #004 d66 ; / * primary button , headings */ — accent : #2 d6cdf ; / * links and highlights */ — card – w: 220 px; / * card width */ — card – h: 110 px; / * card height */ } |
Adjust Logos and Title #
Look for the .brandbar and .brand-logo.left rules to resize logos; update the page title in
Add More Terms (Advanced) #
If your school has more/different terms:
- Update ORDER (e.g., add “Spring”).
- Update CSS layout (increase lanes/height).
- Update year ruler math if terms per year change.
Troubleshooting #
- My notes disappeared: localStorage is per browser and per device. If you switch browsers or clear site data, notes reset.
- Nothing prints: Make sure pop-ups/print dialogs aren’t blocked; use Print / Save as PDF.
- Drag doesn’t work: Don’t start your drag on a card—start on the white space in the viewport.
- Accessibility: Use keyboard shortcuts ( Esc , Ctrl+Enter / Cmd+Enter ). Screen read- ers should announce dialogs due to ARIA attributes.
Testing Checklist #
- Generate timeline with valid years
- Invalid years show alert
- Click card opens editorSave updates previewEsc closes editor
- Clear notes asks to confirm
- Export TXT shows headers/years
- Print view shows clean table
- Arrows scroll content
- Drag/Swipe scrolls content
- Modals close via backdrop
- Easter egg appears once
Glossary (Beginner-Friendly) #
localStorage A simple browser feature that stores small key–value data on your device.
Modal A pop-up dialog that appears above the page to focus user atten- tion.
ARIA Accessibility attributes that help assistive technologies understand the UI.
Viewport The visible portion of the timeline that can be scrolled horizontally.
Transform A CSS feature used here to move the timelinesmoothly (translateX).
Security and Privacy Notes #
- Notes are stored locally on your device; no data is sent to a server.
- If multiple people share a computer account, they can see each other’s notes.
- To remove all notes, use Clear notes or clear your browser storage for the site.
Appendix: Representative Code Snippets #
Save Note and Update Preview #

| save Note Btn . add Event Listener (” click “, () => { if (! current Key ) return ; const text = ( edit Textarea . value || “”). trim End (); local Storage. set Item ( current Key , text ); if ( current Card ){ current Card . text Content = text . split (/\ r?\ n/) [0] || ” Click to add notes “; } modal . class List . add (” hidden “); check Easter Egg (text ); }); |
Clear All Timeline Notes (Scoped by Key Pattern) #

| confirm Clear Btn . add Event Listener (” click “, () => { Object . keys (local Storage ). for Each ( k => { if (/^( Summer | Fall | Winter ) -\ d {4} -\ d+$/. test ( k)){ localStorage . remove Item ( k); } }); document . query Selector All (“. term . preview “) . for Each ( p => p. text Content = ” Click to add notes “); confirm Modal .class List . add (” hidden “); }); |
Print/PDF Flow #

| print Pdf Btn . add Event Listener (” click “, () => { refresh Print View (); window . print (); }); |