Online Course Template Template
A complete one-page site for selling a single online course, built around a draggable pace planner: set your hours per week and watch the curriculum re-pack itself into real weeks with a live finish date.
About This Template
A production-ready one-pager for selling a single online course from one credible instructor. The fictional course is cyanotype printing, and the art direction is the subject itself: a bright cobalt ground (a cyanotype is a saturated blue print), paper-white panels for the dense content, white botanical silhouettes as authored SVG, and a cursive mono face writing the margin notes a printer pencils on a test strip. There are no photographs anywhere - every image is designed CSS or hand-authored SVG, so nothing needs sourcing or licensing.
The signature is the pace planner. A draggable hours-per-week slider re-packs the eight curriculum modules into real weeks as you drag: the week-by-week plan restacks live, each week's load bar resizes, and the projected finish date rolls to its new value. It is real arithmetic, not theatre - the planner reads each module's stated hours out of the curriculum section's own markup, so when a buyer edits their module list the plan recomputes itself. The slider snaps to whole hours, works fully from the keyboard, and on touch only claims horizontal gestures, so a vertical swipe on the handle still scrolls the page.
Around it the page makes the case a course page has to make: a promise-led hero with a framed print, an hour-stated curriculum, the instructor's story with a designed monogram portrait, count-up results, one honest price with a guarantee, and a FAQ written the way a confident teacher actually answers. Swap the course, the instructor and the module hours, point the enrol button at your checkout, and deploy it as static files - there is no build step.
What's Included
- Complete deployable one-page site: nav, promise-led hero, curriculum, pace planner, instructor, results, enrolment card, FAQ, footer
- Signature pace planner: a draggable hours-per-week slider that re-packs the curriculum into weeks, resizes each week's load bar, and rolls the finish date - all computed from the module hours stated in the markup
- The planner is honest arithmetic: edit a module's data-hours in the curriculum and the whole plan recomputes; delete the curriculum section and the planner degrades to its static default
- Full slider accessibility: role=slider with aria-valuenow/min/max and a spoken valuetext, arrow keys, Home, End and PageUp/Down, visible focus rings that swap colour by surface
- Touch-safe dragging: coordinates read null-safe from the raw event, nothing commits on a touch press, and only a proven-horizontal gesture scrubs - a vertical swipe on the handle scrolls the page
- No photography to source: the hero print, student prints and instructor portrait are authored SVG and designed CSS panels with hand-written margin annotations
- Count-up stats and scroll reveals that ship with final values in the markup, so no-JS and reduced-motion readers see finished numbers
- Gabarito display, Albert Sans body, and Victor Mono's cursive italic doing the test-strip annotations - a pairing used nowhere else
- Six-colour token block with RGB triples and a measured contrast table in the stylesheet header - a reskin is a six-value edit
- Degrades completely: with JavaScript off the default six-hour plan renders as a readable static list and every section reads in full
- Reduced motion keeps the planner fully working - plan, bars and date update instantly instead of animating, via both the CSS media query and the matchMedia branch
- Lenis smooth scrolling wired in and fully optional
Perfect For
- Course creators selling one cohort or self-paced course from their own site
- Workshops, masterclasses and craft schools with a stated curriculum
- Coaches and trainers whose programme is measured in hours per week
- Membership or bootcamp landing pages that need an honest time-commitment story
- Learning Draggable: a real, arithmetic-driven example of a slider that drives page content
How It Works
Structure
One script initialises everything inside a single gsap.context, with gsap.matchMedia keyed only on reduced motion so exactly one branch runs on every device. Every querySelector is guarded, so any section - the stats, the instructor, the whole planner - can be deleted and the rest keeps working. Reveal start states are double-gated behind a has-js class and the motion media query, so a blocked CDN or a reduced-motion preference both leave a complete static page.
The pace planner
The planner reads each module's data-hours out of the curriculum section's markup, then packs them greedily into weeks of the chosen size, letting a module span a week boundary the way real study does. Dragging the slider recomputes the pack at every whole-hour stop: the week rows restack with a stagger, each load bar grows to its share of a ten-hour week, and the week count and finish date tween to their new values through GSAP proxies. The finish date is real calendar arithmetic - next Monday plus the plan, landing on the final Friday.
The drag itself
Draggable runs with allowNativeTouchScrolling, and the handler reads coordinates from the raw event, null-safe, never from the cached pointer. A touch press commits nothing; the gesture only starts planning once it has proved more horizontal than vertical, so a finger swiping up the page scrolls the page. A mouse click anywhere on the track seeks immediately, and the handle snaps onto its stop on release.
Accessibility and reduced motion
The handle is a real slider: role=slider, aria-valuemin/max/now, and an aria-valuetext that speaks the whole answer - hours, weeks and finish date - on every change. Arrow keys, PageUp/Down, Home and End all work, and focus rings swap colour per surface because marigold vanishes on marigold. Under reduced motion the planner stays fully interactive but everything updates instantly, and Lenis is never created.
Without JavaScript
The default six-hour plan is authored into the HTML as a plain list, character for character what the script would render, and the readout column states the same answer in words. Stats ship with their final figures in the markup and the FAQ is native details elements, so the page reads complete with scripting off.