✦
Next Assignment
Up next
Learn it.
Build it.
Use it.
Coursework
Learn · Build · Operate
Build the knowledge, systems, and habits to become stronger in modern office, operations, and business-support roles.
Your eight-week business operations learning journey
This track breaks down both this course app and your interactive digital card. You will work from structure to styling, typography systems, custom themes and behavior, then into browser storage, autosave architecture, Supabase, SQL security, and Netlify deployment.
HTMLStructure and meaningCSSLayout and visual systemJavaScriptBehavior and stateSQL + SupabaseCloud data and access rulesStart with the anatomy of a web page.
These controls update CSS custom properties. This is the same concept used by the original digital card's :root variables and by this app's design system.
Click through the app anatomy, connect sections to Build Lab lessons, and inspect the live project source. In the source viewer, clicking a line selects it and identifies the lesson that explains that region.
Each visible region has an HTML structure, CSS rules, and often JavaScript behavior attached to it.
<body>Browser pageContains the app and scripts.<main>App shellShared wrapper around Nextra.<header> + <nav>NavigationBrand, tabs, autosave status..tab-pageApp screensCoursework, Build, Code, Sync.#courseAssignmentsRendered from JavaScript data.#buildLessonsLessonsAlso rendered from data.localStorageBrowser memoryProgress and preferences.SupabaseCloud layerAuthentication and synced state.Each dropdown defines the important syntax and links to official documentation.
The browser begins with the document shell. The head contains metadata, fonts, the PWA manifest, and CSS. The body contains the visible app and JavaScript behavior.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Nextra — Career Learning</title>
</head>
<body>
<main>...</main>
<script>...</script>
</body>
</html>lang="en"Declares the document language.charset="utf-8"Selects UTF-8 text encoding.viewportControls mobile viewport scaling.<body>Contains the rendered page content.The app shell contains the shared header plus separate Coursework, Build Lab, Code Lab, and Sync sections. JavaScript toggles the active class so only one app page is visible at a time.
<main class="app-shell">
<header>...</header>
<section id="pageCoursework" class="tab-page active">...</section>
<section id="pageBuild" class="tab-page">...</section>
<section id="pageCode" class="tab-page">...</section>
<section id="pageSync" class="tab-page">...</section>
</main>idA unique element identifier.classA reusable styling/behavior hook.activeA state class used to show the selected page.<section>A semantic thematic region.The navigation buttons call setTab(). That function updates app state, toggles active classes on pages and buttons, and triggers page-specific rendering when necessary.
function setTab(tab) {
page.classList.toggle("active", tab === "coursework");
buildPage.classList.toggle("active", tab === "build");
codePage.classList.toggle("active", tab === "code");
}functionDeclares reusable JavaScript logic.classList.toggle()Adds or removes a class based on a condition.onclickRuns JavaScript when a control is activated.DOMThe browser's object representation of the HTML document.Coursework uses CSS Grid for the main content and sidebar. Media queries collapse the grid on smaller screens, allowing the same HTML to work on desktop and mobile.
.coursework-layout {
display: grid;
grid-template-columns: minmax(0, 1fr) 286px;
gap: 14px;
}
@media (max-width: 1080px) {
.coursework-layout { grid-template-columns: 1fr; }
}display:gridCreates a Grid layout context.grid-template-columnsDefines the grid column tracks.minmax()Sets minimum and maximum track sizing.@mediaConditionally applies responsive CSS.The assignment cards are generated from JavaScript data rather than copied into HTML 32 times. render() reads assignment objects plus saved state, creates DOM nodes, and inserts them into the course container.
assignments.forEach(a => {
const card = document.createElement("article");
card.innerHTML = `<strong>${a.title}</strong>`;
course.appendChild(card);
});arrayAn ordered JavaScript collection.objectA set of named key/value properties.createElement()Creates a DOM element.template literalA backtick string supporting ${expression}.The theme system stores independent design tokens for the page background, foreground panels, and accent. JavaScript writes those values into CSS custom properties and derives readable supporting colors.
:root {
--user-background: #121014;
--user-panel: #cbc7cc;
--theme-accent: #d4479a;
}
.card { background: var(--user-panel); }--custom-propertyA reusable CSS variable.var()Reads a custom property.setProperty()Updates a CSS property from JavaScript.color-mix()Creates a color by mixing two inputs.Course progress, notes, due dates, and preferences are serialized to localStorage. That keeps state available after refreshes before cloud synchronization happens.
localStorage.setItem(
STORE,
JSON.stringify(state)
);
const restored = JSON.parse(
localStorage.getItem(STORE) || "{}"
);localStorageBrowser key/value storage for the current origin.JSON.stringify()Converts a JavaScript value to JSON text.JSON.parse()Converts JSON text back to JavaScript.originThe scheme/host/port boundary used by browser storage.Changes write to localStorage immediately. When signed in, a short debounce schedules cloud sync. syncNow() merges local and remote state, then upserts the result to Supabase.
function saveLocal() {
localStorage.setItem(STORE, JSON.stringify(state));
clearTimeout(saveDebounce);
saveDebounce = setTimeout(() => {
syncNow(false);
}, 650);
}debounceDelays repeated work until activity settles.setTimeout()Schedules a callback later.async / awaitSyntax for promise-based asynchronous work.upsertInsert a missing row or update an existing one.The manifest describes the installable app. The service worker caches the app shell and can answer requests from CacheStorage, helping the installed PWA load reliably.
self.addEventListener("install", event => {
event.waitUntil(
caches.open(CACHE).then(cache => cache.addAll(ASSETS))
);
});service workerA background browser worker.CacheStorageBrowser API for cached responses.manifest.jsonMetadata for an installable web app.fetch eventA network request intercepted by a service worker.Supabase stores course state in Postgres. The table contains a user_id, JSON state/preferences, and timestamps. RLS policies compare auth.uid() to user_id so each signed-in user can only access their own row.
create table public.course_state (
user_id uuid primary key
references auth.users(id),
state jsonb not null default '{}',
preferences jsonb not null default '{}'
);
alter table public.course_state
enable row level security;uuidA universally unique identifier.jsonbPostgreSQL JSON storage type.primary keyUniquely identifies a row.RLSRow Level Security.auth.uid()Current authenticated Supabase user UUID.The upload box receives File objects from the browser. Nextra stores the binary Blob in IndexedDB, keeps lightweight metadata in course state, and can optionally mirror the Blob into a private Supabase Storage bucket for cross-device downloads.
<input type="file" multiple>
const file = input.files[0];
await putWorkBlob({ blob: file });
const url =
URL.createObjectURL(file);
type="file"Creates a browser file picker.multipleAllows more than one selected file.File / BlobBrowser objects representing binary file data.IndexedDBBrowser database that can persist Blobs and structured objects.createObjectURL()Creates a temporary URL that can download or display a Blob.The learning drawer separates category-level navigation from page-level navigation. Career currently contains Business Operations. Coding contains Build Lab and Code Lab. Because the drawer is generated from LEARNING_AREAS, future tracks such as Python can be added to the Coding category without rebuilding the menu from scratch.
const LEARNING_AREAS = [
{
id: "coding",
pages: [
{ tab: "build" },
{ tab: "code" }
]
}
];
nested arrayPages are grouped inside a learning-area object.data-drawer-tabStores which app page a rendered menu button opens.aria-expandedCommunicates whether the drawer is open.Escape keyProvides keyboard dismissal for the side panel.The source-line selector highlights matching lessons here.
Open any term while reading the source.
<header>⌄Introductory or navigation content.
Official reference ↗<nav>⌄Navigation region.
Official reference ↗<main>⌄Dominant document content.
Official reference ↗<section>⌄Thematic section.
Official reference ↗<article>⌄Self-contained composition.
Official reference ↗<aside>⌄Related secondary content.
Official reference ↗<details>⌄Native expandable disclosure.
Official reference ↗<summary>⌄Clickable label for <details>.
Official reference ↗id⌄Unique element identifier.
Official reference ↗class⌄Reusable styling and behavior classes.
Official reference ↗aria-label⌄Accessible name for a control or region.
Official reference ↗data-*⌄Custom data stored on an HTML element.
Official reference ↗href⌄Navigation/resource target.
Official reference ↗type⌄Defines control/input behavior.
Official reference ↗value⌄Current/default form-control value.
Official reference ↗placeholder⌄Hint displayed in an empty form control.
Official reference ↗:root⌄Root pseudo-class, commonly used for global variables.
Official reference ↗--custom-property⌄Author-defined CSS variable.
Official reference ↗var()⌄Reads a CSS custom property.
Official reference ↗display:grid⌄Two-dimensional Grid layout.
Official reference ↗display:flex⌄One-dimensional Flexbox layout.
Official reference ↗@media⌄Conditional responsive CSS.
Official reference ↗::before / ::after⌄Generated pseudo-elements.
Official reference ↗!important⌄Raises declaration priority in the cascade.
Official reference ↗const / let⌄Block-scoped variable declarations.
Official reference ↗function⌄Reusable executable logic.
Official reference ↗getElementById()⌄Finds an element by id.
Official reference ↗querySelector()⌄Finds the first element matching a CSS selector.
Official reference ↗classList⌄Adds/removes/toggles classes.
Official reference ↗addEventListener()⌄Registers an event callback.
Official reference ↗async / await⌄Promise-based asynchronous control flow.
Official reference ↗localStorage⌄Persistent origin-scoped browser storage.
Official reference ↗fetch()⌄Promise-based network request API.
Official reference ↗CREATE TABLE⌄Creates a database table.
Official reference ↗uuid⌄UUID data type.
Official reference ↗jsonb⌄Binary JSON storage type.
Official reference ↗PRIMARY KEY⌄Uniquely identifies a row.
Official reference ↗RLS policy⌄Row-level database access rule.
Official reference ↗auth.uid()⌄Current authenticated user's UUID.
Official reference ↗Mapped source regions have a subtle accent marker. Selecting a line keeps it highlighted and reveals the relevant Build Lab lesson.
Connect your Supabase account once per device, then your completed assignments, notes, and reminder preferences can sync through the cloud.
Once signed in, coursework, adjustable due dates, notes, Build Lab progress, reminders, and your personal color theme save locally immediately and sync to Supabase automatically. Each authenticated user keeps a separate course row, so multiple people can use the same published Netlify app without sharing progress or theme settings. Manual sync is only a fallback.
Use this on both phone and desktop. The account fingerprint should match on both devices. Background checks are now read-only unless there is actually something new to save.
Do not clear its browser or PWA storage. Open that device first after deploying this version, make sure the account fingerprint matches your other device, then press Verify + merge now.
Your browser still keeps a local copy. Export a JSON backup periodically; restore merges the newest version of each assignment back into the app.