Marketing pages
Pilot inventory of Gradeful’s public marketing, catalog, legal, and contact routes.
Live student-facing copy is the source of truth in the app. Marketing copy was restored from Git a7de9a9 (the commit immediately before the tutoring-platform rewrite), with factual/legal exceptions documented in 07-release-status.md and 08-known-limitations.md.
This file covers unauthenticated marketing surfaces only.
Related inventories:
- 00-how-everything-connects.md — registration, checkout, dashboard, settings, study
- 02-auth-onboarding.md
- 03-checkout.md
- 04-dashboard-and-workspace.md
- 05-settings.md
- 06-study-views.md
Admin (/admin/*) is still not in this set.
Scope
Included:
/homepage/pricing/courseslisting/courses/[slug]public course preview/about/contact/support/tutoring/policies/privacy/terms/refunds/academic-integrity/site-map- Redirects:
/faq,/access,/content-standards /markitup(public cinematic site; not Gradeful marketing chrome)
Excluded from this file: /login, /signup, /forgot-password, /reset-password, /welcome, /checkout, /dashboard, /my-courses, /admin, /maintenance, /dev.
There is no App Router (marketing) group. These pages live at the app root and share SiteHeader + SiteFooter except /markitup.
Normal access for every Gradeful page below is public (no login required) except /: logged-in users with active user_access are redirected to /dashboard before the marketing homepage HTML is rendered (proxy.ts + app/page.tsx). Logged-in users without active access still see /. Active users may still open /pricing, /courses, public course pages, and legal/help on purpose. If platform_settings key maintenance_mode is "true", non-admins are sent to /maintenance instead.
Shared chrome
Used on every Gradeful marketing page in this file except /markitup. Documented once. Each PAGE still lists header then footer in render order and points here, plus any page-specific exception.
Site header (components/site/SiteHeader.tsx + NavAuthButton.tsx)
SECTION: Site header
Copy: Logo image alt Gradeful. Desktop and mobile nav labels Courses, Pricing, About. Logged-in extras documented on elements. Logged-out CTA Get access and Sign in. Mobile control Open menu / Close menu.
Data shown: Current path (underline active nav). Auth session from Supabase Auth. Profile fields profiles.avatar_url, profiles.full_name, profiles.university, profiles.campus, profiles.major, profiles.second_major, profiles.role. Active paid access from user_access.plan_type, user_access.payment_status, user_access.expires_at (rows with payment_status in paid or confirmed and unexpired). Header is sticky except homepage (sticky={false}).
ELEMENT: Gradeful (logo)
Action: navigate
Destination: /
Writes to: none
Reads from: none
ELEMENT: Courses
Action: navigate
Destination: /courses
Writes to: none
Reads from: none
ELEMENT: Pricing
Action: navigate
Destination: /pricing
Writes to: none
Reads from: none
ELEMENT: About
Action: navigate
Destination: /about
Writes to: none
Reads from: none
ELEMENT: My courses
Action: navigate
Destination: /my-courses
Writes to: none
Reads from: Visible only when logged in and at least one active user_access row (payment_status in paid/confirmed, expires_at null or in the future)
ELEMENT: Admin
Action: navigate
Destination: /admin
Writes to: none
Reads from: Visible only when profiles.role is admin
ELEMENT: Open menu / Close menu
Action: toggle
Destination: mobile nav panel #site-mobile-menu
Writes to: none
Reads from: none (mobile only)
ELEMENT: Get access
Action: navigate
Destination: /checkout
Writes to: none
Reads from: Shown when logged out, except on /pricing and /checkout. When logged in with no paid plan (getNavAccessCtaLabel tier none), same label. Hidden while auth is still loading.
ELEMENT: Add more courses
Action: navigate
Destination: /checkout
Writes to: none
Reads from: Shown when logged in with an active paid user_access.plan_type (tier partial). Desktop header uses avatar-only layout, so this CTA appears in the mobile menu, not the desktop bar.
ELEMENT: Sign in
Action: navigate
Destination: /login
Writes to: none
Reads from: Shown when logged out
ELEMENT: Dashboard
Action: navigate
Destination: /dashboard
Writes to: none
Reads from: Shown when logged in, in the mobile NavAuthButton full layout only (desktop logged-in header is avatar-only)
ELEMENT: Open settings (gear)
Action: navigate
Destination: /dashboard?settings=profile
Writes to: none
Reads from: Shown when logged in (AccountChrome)
ELEMENT: Open account menu (avatar / initials)
Action: open modal
Destination: account flyout menu
Writes to: none
Reads from: profiles.avatar_url, profiles.full_name, auth email; initials derived from name/email
Account flyout (opens from avatar; also used from header on marketing pages):
ELEMENT: Settings
Action: navigate
Destination: /dashboard?settings=profile
Writes to: none
Reads from: none
ELEMENT: Get help
Action: navigate
Destination: /dashboard?settings=help
Writes to: none
Reads from: none
ELEMENT: Upgrade plan
Action: navigate
Destination: /pricing
Writes to: none
Reads from: none
ELEMENT: Dashboard
Action: navigate
Destination: /dashboard
Writes to: none
Reads from: none
ELEMENT: Learn more Action: toggle Destination: Learn more submenu Writes to: none Reads from: none
ELEMENT: About Gradeful
Action: navigate
Destination: /about
Writes to: none
Reads from: none
ELEMENT: Privacy policy
Action: navigate
Destination: /privacy
Writes to: none
Reads from: none
ELEMENT: Terms of service
Action: navigate
Destination: /terms
Writes to: none
Reads from: none
ELEMENT: Refund policy
Action: navigate
Destination: /refunds
Writes to: none
Reads from: none
ELEMENT: Academic integrity
Action: navigate
Destination: /academic-integrity
Writes to: none
Reads from: none
ELEMENT: All policies
Action: navigate
Destination: /policies
Writes to: none
Reads from: none
ELEMENT: Log out / Logging out…
Action: submit
Destination: / after supabase.auth.signOut()
Writes to: clears Auth session cookies (no Gradeful table write)
Reads from: none
Site footer (SiteFooter in components/site/PublicPageShell.tsx)
SECTION: Site footer
Copy: Logo alt Gradeful. Body: Course-specific study packs for AUB and LAU students. Built for focused self-study. Copyright: © 2026 Gradeful. Column headings Platform and Policies.
Data shown: static
ELEMENT: Home
Action: navigate
Destination: /
Writes to: none
Reads from: none
ELEMENT: Courses
Action: navigate
Destination: /courses
Writes to: none
Reads from: none
ELEMENT: Pricing
Action: navigate
Destination: /pricing
Writes to: none
Reads from: none
ELEMENT: Privacy Policy
Action: navigate
Destination: /privacy
Writes to: none
Reads from: none
ELEMENT: Terms of Service
Action: navigate
Destination: /terms
Writes to: none
Reads from: none
ELEMENT: Refund Policy
Action: navigate
Destination: /refunds
Writes to: none
Reads from: none
ELEMENT: Academic Integrity
Action: navigate
Destination: /academic-integrity
Writes to: none
Reads from: none
PAGE: /
Purpose: Search-first marketing homepage for course-specific study packs (notes, formula sheets, flashcards, exam review) and plan CTAs.
Access: public for anonymous and logged-in users with no active plan. Logged-in users with active user_access are redirected to /dashboard (no homepage flash).
Entry points: Direct URL; footer Home; header logo; site map; post-logout redirect (AccountFlyout signs out to /); external links to gradeful.app.
SECTION: Site header Copy: Shared chrome. Homepage header is not sticky. Data shown: Shared chrome ELEMENT: all Shared chrome elements apply
SECTION: Hero
Copy: Course-specific study packs
Stop studying from scattered sources that weren't built for your course.
Notes, formula sheets, flashcards, and exam review, all organized around your exact syllabus. Currently serving AUB and LAU students.
Data shown: static
SECTION: Course search
Copy: Screen-reader label Search courses. Input aria-label Search courses. Placeholder: Search by course code or name, e.g. CHEM201, Calculus III
Empty suggestions: No matching course yet.
Suggestion row secondary label (sm+): Open
Data shown: Suggestion rows are dynamic from getCourses(): courses.code, courses.title, courses.slug, universities.short_name, pack count from related course_packs rows. Catalog limited to courses.is_active = true, non-sample, and course_packs.length > 0. Query uses first 50 courses.
ELEMENT: Search form (no visible submit button; submitting the field)
Action: submit
Destination: If a highlighted suggestion is active → /courses/[courses.slug]. Else if query non-empty → /courses?q={typed query}. Else → /courses. Note: /courses does not currently read ?q=; the listing search state is client-only.
Writes to: none
Reads from: courses.* / universities.short_name / course_packs as above
ELEMENT: [university short name] [course code] [course title] (each suggestion)
Action: navigate
Destination: /courses/[courses.slug]
Writes to: none
Reads from: universities.short_name, courses.code, courses.title, courses.slug
ELEMENT: Search all courses
Action: navigate
Destination: /courses?q={typed query}
Writes to: none
Reads from: Visible when the dropdown is open and no suggestion matches
ELEMENT: Request this course
Action: navigate
Destination: /courses#course-request
Writes to: none
Reads from: Visible when the dropdown is open and no suggestion matches
SECTION: Hero course marquee
Copy: Each tile shows a compatibility university short name (when display mode is compatibility) and a display course code. Pack counts are not shown.
Data shown: Rendered only when heroCourses.length > 0 and platform_settings key show_course_catalog is true (default true). Courses from getCourses() as above.
ELEMENT: [university] [code]
Action: navigate
Destination: /courses/[courses.slug]
Writes to: none
Reads from: universities.short_name via formatUniversityShortName, courses.code, courses.slug. Visibility also reads platform_settings key show_course_catalog.
SECTION: Request prompt under search
Copy: Don't see your course? then link Request it →
Data shown: static
ELEMENT: Request it →
Action: navigate
Destination: /courses#course-request
Writes to: none
Reads from: none
SECTION: Available now
Copy: Available now
Admin-selected study packs built for your exact course at AUB and LAU.
Slider helper (mobile): Swipe sideways or use the arrows to see more courses.
End card: badge Full catalog; Check more; Find your next course pack.; Browse the full Gradeful catalog and open every course available for AUB and LAU.; Browse all courses
Data shown: Section omitted when no featured courses. Cards from getHomepageCourses(): courses where is_active = true and is_homepage_featured = true, ordered by courses.homepage_sort_order then courses.code, max 10, then isListedCatalogCourse. Card fields: universities.short_name (compatibility display), courses.code, courses.title, courses.description, courses.semester_label, courses.slug; pack count from course_packs. Instructor names stay off unless NEXT_PUBLIC_GRADEFUL_SHOW_INSTRUCTOR_NAMES=true. Badge: 1 pack / {n} packs; Access required if any related pack is locked, else Preview open. Label Semester: is a static prefix.
ELEMENT: Scroll course previews left Action: toggle Destination: none (scrolls the slider) Writes to: none Reads from: none
ELEMENT: Scroll course previews right Action: toggle Destination: none (scrolls the slider) Writes to: none Reads from: none
ELEMENT: [course title] (card heading link)
Action: navigate
Destination: /courses/[courses.slug]
Writes to: none
Reads from: courses.title, courses.slug
ELEMENT: Preview pack
Action: navigate
Destination: /courses/[courses.slug]
Writes to: none
Reads from: courses.slug; aria-label is dynamically View pack for {courses.code} {courses.title}
ELEMENT: Check more courses / Browse all courses (end card)
Action: navigate
Destination: /courses
Writes to: none
Reads from: none
ELEMENT: Browse all courses →
Action: navigate
Destination: /courses
Writes to: none
Reads from: none
SECTION: Testimonials
Copy: Testimonials section removed. Hardcoded quotes are not shipped. lib/reviews.ts is an empty list until consented testimonials exist.
Data shown: none
SECTION: Comparison
Copy: The usual way
WhatsApp PDF from last semester. No solutions.
YouTube videos that skip the course you are actually taking.
Classmate notes from a different section.
Practice with no answer key.
Googling at 2am the night before.
With Gradeful
Notes built for your exact course.
Formula sheet organized by chapter. Printable.
Practice quiz written for this course.
Exam review for the week before finals.
One place. Everything ready. Nothing missing.
Data shown: static
SECTION: Pack tools
Copy: Everything you need. Nothing you don't.
Everything you'd normally chase across different sources, organized once, for your exact course.
Cards:
Notes — Built for your exact chapter. Not a generic overview.
Formula sheets — One page. Everything organized. Print-ready.
Flashcards — Drill the ideas until they stick.
Practice quizzes — Original questions to check your understanding.
Mock exams — Timed Gradeful practice under exam-like pressure.
Exam review — Condensed version for finals week.
Mistake fixes — What students get wrong in this course, fixed.
AI explanations — Ask anything. Grounded in your pack. Badge: Coming soon
Data shown: static
ELEMENT: Preview a sample pack
Action: navigate
Destination: /courses
Writes to: none
Reads from: none
SECTION: Pricing
Copy: Straightforward access.
Starting at {formatStartingPrice(plans)}. Less than one textbook chapter. from getPaymentPlans() (catalog lib/payments/catalog.ts plus optional plan_overrides).
Per card: plan display name, price, unit label, duration, benefits, and CTA from the same live plan record. Default names: Focus, Balance, Full Load, Crunch. Price via formatPlanPrice. Unit/duration from catalog helpers (/1 course, /2 courses, /up to 6 courses, /up to 4 courses; semester window or {n}-day sprint). Badge Recommended on Full Load. Badge {n} days on Crunch.
Data shown: getPaymentPlans() → lib/payments/catalog.ts merged with platform_settings.plan_overrides.
ELEMENT: Get Focus
Action: navigate
Destination: /checkout?plan=focus
Writes to: none
Reads from: none
ELEMENT: Get Balance
Action: navigate
Destination: /checkout?plan=balance
Writes to: none
Reads from: none
ELEMENT: Cover my semester
Action: navigate
Destination: /checkout?plan=fullload
Writes to: none
Reads from: none
ELEMENT: Prep for Finals
Action: navigate
Destination: /checkout?plan=crunch
Writes to: none
Reads from: none
ELEMENT: Compare full features →
Action: navigate
Destination: /pricing#compare
Writes to: none
Reads from: none
SECTION: Closing CTA
Copy: Finals are coming. Find your course before the panic starts.
Search available courses or request the one you need next.
Data shown: static. WhatsApp URL is hardcoded https://wa.me/96179057533 (not platform_settings.whatsapp_contact).
ELEMENT: Find your course pack →
Action: navigate
Destination: /courses
Writes to: none
Reads from: none
ELEMENT: WhatsApp →
Action: external link
Destination: https://wa.me/96179057533
Writes to: none
Reads from: none
SECTION: Site footer Copy: Shared chrome Data shown: static ELEMENT: all Shared chrome footer elements apply
PAGE: /pricing
Purpose: Compare Focus / Balance / Full Load / Crunch and send the student into checkout.
Access: public
Entry points: Header/footer Pricing; homepage Compare full features; about is not a source; contact secondary “How access works” goes to /access which redirects here; /faq redirect; /access redirect; account flyout Upgrade plan; site map.
SECTION: Site header
Copy: Shared chrome. Exception: logged-out Get access is hidden on this path.
Data shown: Shared chrome
ELEMENT: Shared chrome except Get access
SECTION: Hero
Copy: Pricing for AUB and LAU course packs
Pick the access that matches your semester.
Choose a plan and get instant access to course-specific study packs.
Data shown: static
ELEMENT: View plans
Action: navigate
Destination: in-page #plans (smooth scroll)
Writes to: none
Reads from: none
SECTION: Plans
Copy: Eyebrow Plans
Simple pricing. Clear coverage.
Focus on one course, cover two difficult classes, unlock your semester load, or use Crunch for finals pressure.
Cards use getPaymentPlans() so admin overlays apply. Names, prices, unit labels, duration, benefits, and CTAs come from lib/payments/catalog.ts.
Data shown: live plan records, not hardcoded dollar amounts.
ELEMENT: Get Focus
Action: navigate
Destination: /checkout?plan=focus
Writes to: none
Reads from: none
ELEMENT: Get Balance
Action: navigate
Destination: /checkout?plan=balance
Writes to: none
Reads from: none
ELEMENT: Cover my semester
Action: navigate
Destination: /checkout?plan=fullload
Writes to: none
Reads from: none
ELEMENT: Prep for Finals
Action: navigate
Destination: /checkout?plan=crunch
Writes to: none
Reads from: none
SECTION: Compare plans
Copy: Eyebrow Compare plans
The full picture before you choose.
Every plan includes the same course tutoring tools. The difference is how many courses you cover and how long access lasts.
Toggle closed label Compare all features; open label Hide comparison.
Table headers: Outcome plus live plan names
Rows from live plans + tutoringMessagesLabels():
Courses covered — catalog coursesCoveredLabel (1 / 2 / up to 6 / up to 4)
Access duration — catalog durationShortLabel
Lessons + reference sheets — checkmark (sr-only Included) all plans
Flashcards + quizzes — Included all plans
Exam prep + common traps — Included all plans
AI tutor — fair-use tutoring message counts from lib/payments/economics.ts (not a credit wallet)
Best for — catalog comparisonBestFor
Footnote: tutoring messages are a fair-use allowance, not credits; core lessons/practice/review do not consume it.
Data shown: getPaymentPlans() plus economics labels. Hash #compare auto-opens the table.
ELEMENT: Compare all features / Hide comparison
Action: toggle
Destination: #pricing-feature-table (show/hide)
Writes to: none
Reads from: none
SECTION: Which plan
Copy: Which plan should I choose?
Match the plan to the pressure.
The right plan depends on how many courses need structure, not on a generic subscription tier.
Choose Focus — Not sure if Gradeful is worth it? Try one course first. If it helps, you'll know before spending more.
Choose Balance — Tried one course and it worked. Now cover the other one. Two courses for $7 more than Focus.
Choose Full Load — live copy from choiceGuidance (up to 6 courses at checkout).
Choose Crunch — live copy from choiceGuidance (up to 4 courses for {durationDays} days).
Data shown: choiceGuidance(plans) from lib/payments/catalog.ts
SECTION: FAQ
Copy: Eyebrow FAQ
Answers before you choose a plan.
What is inside, how access works, and what to do if your course is not listed yet.
Accordion from PricingFaq + live plans:
What is inside each pack? / worked notes, formula sheet, flashcards, practice quizzes, exam review, mistake fixes for the specific AUB or LAU course
How long does access last? / Focus, Balance, Full Load {durationDays} days; Crunch {durationDays} days
Can I share my account with friends? / No, one student per account
Is there a free preview? / Yes — open any course to see the pack structure before buying
What if my course is not listed? / Request it on the courses page
Can I switch or upgrade my plan? / Focus can move to Balance or Full Load by paying the difference via WhatsApp; self-serve upgrades are not live
Do I pick my courses when I buy? / Focus 1, Balance 2, Full Load up to 6, Crunch up to 4. No schedule upload to buy.
Can I access on my phone? / Yes
What is the refund policy? / REFUND_POLICY.studentCopy from lib/payments/transitions.ts
Footer: Didn't find your answer? Ask directly and get a straight answer.
Data shown: live plans + refund policy module
ELEMENT: [each FAQ question] Action: toggle Destination: that item’s answer region Writes to: none Reads from: none
ELEMENT: Ask on WhatsApp
Action: external link
Destination: https://wa.me/96179057533
Writes to: none
Reads from: none
SECTION: Refund footnote
Copy: Refunds are reviewed for documented course withdrawals or drops with university confirmation. Contact us before requesting access if you are unsure about your enrollment. then Read our refund policy →
Data shown: static
ELEMENT: Read our refund policy →
Action: navigate
Destination: /refunds
Writes to: none
Reads from: none
SECTION: Site footer Copy: Shared chrome Data shown: static ELEMENT: all Shared chrome footer elements apply
PAGE: /courses Purpose: Browse AUB/LAU course packs and request a missing course. Access: public Entry points: Header/footer Courses; homepage search, marquee, Browse all courses, Preview a sample pack, Find your course pack; contact Browse courses; support Request a course; about Request a course; site map.
SECTION: Site header Copy: Shared chrome Data shown: Shared chrome ELEMENT: all Shared chrome elements apply
SECTION: Hero
Copy: AUB + LAU course packs
Study smarter with packs made for your course.
Access organized notes, formula sheets, flashcards, and exam review for the AUB and LAU courses you take. plus the course compatibility statement.
Image alt: Gradeful study pack preview showing lecture notes, formula sheets, flashcards, and exam review
Data shown: static (/assets/courses-hero-graphic.png)
SECTION: Catalog error (only if getCourses fails)
Copy: Course catalog is being built. Check back soon.
The public catalog is not available yet. The page is ready and will show courses once Supabase is connected and seeded.
Data shown: static strings from catalogUnavailable() in lib/catalog.ts (not database content)
SECTION: Filters (when catalog loads without issue)
Copy: Screen-reader Search courses by code, title, or university. Placeholder: Search by course code or name, e.g. MATH 201. Group aria-label Filter by university compatibility. Tab labels All plus each universities.short_name present in offerings.
Data shown: URL state q and university (stable short_name slug). Listing dataset is getCourses({ limit: 200 }) then client ranker. Sample slug/title/code stay hidden. Active in-development courses are listed with status, not hidden for empty packs.
ELEMENT: Search courses (input)
Action: toggle
Destination: /courses?q= via replaceState (shareable; does not break back/forward)
Writes to: none
Reads from: compact course codes, titles, offering aliases on course_universities, university names, topic keywords. Instructor names are secondary only.
ELEMENT: All
Action: toggle
Destination: clears university query param via pushState
Writes to: none
Reads from: none
ELEMENT: University compatibility tabs
Action: toggle
Destination: /courses?university={short_name} via pushState
Writes to: none
Reads from: offerings on course_universities plus primary courses.university_id fallback
ELEMENT: Clear filters
Action: toggle
Destination: /courses via pushState
Writes to: none
Reads from: Visible when a university filter or search is set
SECTION: Empty catalog (loaded, zero listed courses)
Copy: Course catalog is being built. Check back soon.
Published courses will appear here once the catalog is seeded.
Data shown: static (this empty state is separate from the fetch-issue banner)
SECTION: Filtered empty
Copy: No courses found for "{search}" (search preserved) then Keep your search. Request the course so Gradeful can prioritize it.
Data shown: {search} is the typed filter string.
ELEMENT: Request this course →
Action: navigate
Destination: in-page #course-request (opens request collapsible and prefills from search)
Writes to: none
Reads from: current search string used as prefill
SECTION: Course table
Copy: Column headers Course Compatibility Coverage Last reviewed Action
Row: course title and courses.code; compatibility badges from course_universities (neutral text, no logos); availability (Available / Preview available / In development) and coverage (Full support / Core topics / Early access) derived from published module items; last reviewed from max module_pack_items.updated_at; one action (Open course / Preview / Notify me).
Data shown: courses.id, courses.slug, courses.code, courses.title, offering codes, computed availability/coverage.
ELEMENT: Open course / Preview (row link)
Action: navigate
Destination: /courses/[courses.slug]
Writes to: none
Reads from: courses.slug
ELEMENT: Notify me
Action: toggle
Destination: in-page #course-request
Writes to: none
Reads from: course code prefill
SECTION: Pagination
Copy: Show {10|20|50} per page then {start}–{end} of {totalItems}. Ellipsis …. Controls aria-label Previous page / Next page / Courses per page / Course list pagination.
Data shown: Counts from the filtered in-memory list, not a SQL offset.
ELEMENT: 10 / 20 / 50 Action: toggle Destination: none (changes page size) Writes to: none Reads from: none
ELEMENT: Previous page Action: toggle Destination: none (previous page) Writes to: none Reads from: disabled on page 1
ELEMENT: [page number] Action: toggle Destination: none (that page) Writes to: none Reads from: none
ELEMENT: Next page Action: toggle Destination: none (next page) Writes to: none Reads from: disabled on last page
SECTION: Course request collapsible
Copy: Closed header: Don't see your course? Request it and we'll prioritize by demand. trailing Request a course
Open eyebrow: Course request
Fields: Course code placeholder MATH201; Course name placeholder Calculus III; University with Select university / AUB / LAU / Other; Your email placeholder your@university.edu; Notes placeholder Instructor name, section, anything specific about what you need
Submit: Send request or Sending...
Success: Request sent. We prioritize by demand.
Error body uses formError when insert fails: Request could not be sent yet. The public request table may still be setting up. Field errors include Enter a valid email address. and Add a university, course code, or course title. and Keep this under {n} characters.
Data shown: Success is client state. Insert writes course_requests. Prefill may copy the catalog search string into code or title.
ELEMENT: Request a course (header button)
Action: toggle
Destination: expands the form (aria-expanded)
Writes to: none
Reads from: none
ELEMENT: Send request / Sending...
Action: submit
Destination: none (stays on /courses; success state in place)
Writes to: course_requests.id, course_requests.email, course_requests.university_name, course_requests.course_code, course_requests.course_title, course_requests.instructor_name (hidden empty), course_requests.notes
Reads from: none
SECTION: Site footer Copy: Shared chrome Data shown: static ELEMENT: all Shared chrome footer elements apply
PAGE: /courses/[slug]
Purpose: Public preview of one course pack (what’s included, locked module outline) and checkout CTA.
Access: public (page itself). View formula sheet may send a logged-out user toward a protected study URL.
Entry points: Homepage search/marquee/cards; courses table; direct/shared URL; internal course links.
SECTION: Site header Copy: Shared chrome Data shown: Shared chrome ELEMENT: all Shared chrome elements apply
SECTION: Load error
Copy: Back to courses
Couldn't load this course right now. Try refreshing.
Data shown: static. Shown when getCourseBySlug throws/returns an issue.
ELEMENT: Back to courses
Action: navigate
Destination: /courses
Writes to: none
Reads from: none
(Unknown slug uses Next notFound() — custom 404, not this page.)
SECTION: Course header
Copy: Breadcrumb Courses / {subject} / {courses.title} where subject is mapped from course-code prefix (BIOL→Biology, CHEM→Chemistry, ECON→Economics, MATH/MTH→Mathematics, MECH→Mechanical Engineering, PHYS→Physics, else the letter prefix or Course).
Badges: {universities.short_name} · {courseCode} from getUniversityCourses.
Heading: courses.title
Optional body: courses.description
Data shown: courses.title, courses.description, courses.code, courses.slug, universities.short_name, related university course codes. JSON-LD BreadcrumbList uses those same fields.
ELEMENT: Courses
Action: navigate
Destination: /courses
Writes to: none
Reads from: none
ELEMENT: Get access →
Action: navigate
Destination: /checkout?plan=focus&course={courses.id}
Writes to: none
Reads from: courses.id
ELEMENT: View formula sheet
Action: navigate
Destination: /my-courses/{courses.slug}?module={course_modules.id}&tab=formula_sheet when a module has course_modules.is_free_preview and a formula_sheet pack item
Writes to: none
Reads from: course_modules.is_free_preview, module_pack_items.item_type, courses.slug
ELEMENT: Unlock formula sheet
Action: navigate
Destination: /pricing
Writes to: none
Reads from: Shown when no free-preview formula sheet exists
SECTION: What's included
Copy: What's included
Cards: Notes Formula sheet Flashcards Practice quiz Exam review Mistake fixes
Data shown: static labels (not read from module_pack_items on this grid)
SECTION: Course modules
Copy: Course modules
Shared-track rows: course_modules.title; status chips Not published yet (no visible pack items) or Up next when course_modules.status === "up_next"; expanded chips {module_pack_items.label} optionally · {module_pack_items.count} (label omitted when stored as empty/default).
Divider: Tracks split by school from here
Columns: AUB {aubCourse.courseCode ?? courses.code} track and LAU {lauCourse.courseCode ?? courses.code} track listing locked course_modules.title for track aub / lau.
Data shown: course_modules.title, course_modules.sort_order, course_modules.status, course_modules.track, course_modules.is_free_preview, module_pack_items.label, module_pack_items.count, module_pack_items.item_type (flagged items hidden). Modules with zero student-visible items treated as unpublished.
ELEMENT: [module title] (shared-track row)
Action: toggle
Destination: expands that module’s pack-item chips
Writes to: none
Reads from: course_modules.title; first shared module defaults open
ELEMENT: Get access to unlock all modules →
Action: navigate
Destination: /checkout?plan=focus&course={courses.id}
Writes to: none
Reads from: courses.id
SECTION: Site footer Copy: Shared chrome Data shown: static ELEMENT: all Shared chrome footer elements apply
PAGE: /about Purpose: Founder story, product beliefs, independence disclaimer, and contact. Access: public Entry points: Header About; account Learn more → About Gradeful; site map.
SECTION: Site header Copy: Shared chrome Data shown: Shared chrome ELEMENT: all Shared chrome elements apply
SECTION: Why Gradeful exists
Copy: Why Gradeful exists
Built by an engineering student who couldn't make sense of Dynamics.
The rules weren't hard. The textbook made them hard.
So I built a pack for Dynamics. Worked notes. A formula sheet that organized the rules by type. Practice problems that escalated. It made the course click — not because it leaked an exam, but because the ideas finally had a path.
That was the idea. If one pack could do that for Dynamics, the same approach could work for every course at AUB and LAU.
Data shown: static
SECTION: What we believe
Copy: What we believe
01 Generic material fails specific courses. MATH201 is not the same as a random Calculus III playlist. Your course has a scope. Your workspace should follow that scope — without pretending to be the university.
02 Organized beats comprehensive. A 200-page textbook is not the problem. Not knowing which ideas to practice first is. Gradeful sequences lessons, drills, and review.
03 Practice should feel like pressure. Original quizzes and practice exams train the method. They are not copies of anyone's live assessment.
Data shown: static
SECTION: Independence
Copy: Independence
Canonical independence statement from lib/brand/copy.ts.
Data shown: static
SECTION: Get in touch
Copy: Get in touch
Questions about a specific course, a workspace you think is missing, or anything else. Reach out directly.
Data shown: static
ELEMENT: WhatsApp
Action: external link
Destination: https://wa.me/96179057533
Writes to: none
Reads from: none
ELEMENT: Request a course
Action: navigate
Destination: /courses#course-request
Writes to: none
Reads from: none
SECTION: Site footer Copy: Shared chrome Data shown: static ELEMENT: all Shared chrome footer elements apply
PAGE: /contact
Purpose: Public intake for course requests and support topics.
Access: public
Entry points: Policies Contact Gradeful; checkout/support copy linking /contact; direct URL.
SECTION: Site header Copy: Shared chrome Data shown: Shared chrome ELEMENT: all Shared chrome elements apply
SECTION: Hero
Copy: Eyebrow Contact Gradeful
Requests, corrections, and launch questions in one place.
The most useful message is specific: university, course code, course title, instructor if relevant, and the kind of material that would help.
Badges: Course requests Corrections Access questions
Decorative visual label contact
Data shown: static
ELEMENT: Browse courses
Action: navigate
Destination: /courses
Writes to: none
Reads from: none
ELEMENT: How access works
Action: navigate
Destination: /access (immediately redirects to /pricing)
Writes to: none
Reads from: none
SECTION: What to send
Copy: Eyebrow What to send
Make the request specific enough to act on.
Short, precise course details are more useful than broad feedback. If you are reporting an error, include the course and section where you saw it.
Course requests — Tell Gradeful which AUB or LAU course, instructor, or topic should be prioritized next.
Access questions — Ask about pricing, payment confirmation, or course coverage.
Corrections — Flag unclear explanations, possible mistakes, missing formulas, or outdated course details.
Campus partners — Students, ambassadors, tutors, and reviewers can reach out when campus programs open.
Support band: Support Send the course details Gradeful needs to help. For fastest support, include your university, course code, instructor if relevant, and the specific material or access question.
Data shown: static
SECTION: Request a course form
Copy: Request a course
Tell Gradeful what you need next.
Share the course code, university, and anything specific your section needs. We use requests to prioritize what gets built next.
Labels: Email placeholder you@example.com; University placeholder AUB or LAU; Course code placeholder MATH201; Course title placeholder Calculus III; Instructor placeholder Instructor name, if relevant; Notes placeholder Tell us what materials would help.
Submit: Submit request / Sending...
Success: Request sent Gradeful has your course request. Reference number: {course_requests.id} Gradeful can use this to prioritize courses.
Fail banner: Request could not be sent yet. The public request table may still be setting up.
Data shown: Success reference is the generated course_requests.id.
ELEMENT: Submit request / Sending...
Action: submit
Destination: none (success state on /contact)
Writes to: course_requests.id, course_requests.email, course_requests.university_name, course_requests.course_code, course_requests.course_title, course_requests.instructor_name, course_requests.notes
Reads from: none
SECTION: Site footer Copy: Shared chrome Data shown: static ELEMENT: all Shared chrome footer elements apply
PAGE: /support
Purpose: Public help landing (same Help & contact content used in settings).
Access: public
Entry points: Direct URL; account scheme Get help href is /support but the header flyout currently opens /dashboard?settings=help instead; site map does not list it.
SECTION: Site header Copy: Shared chrome Data shown: Shared chrome ELEMENT: all Shared chrome elements apply
SECTION: Help & contact
Copy: Help & contact
Reach out or browse common answers
Chat with us — Usually responds within a day
Request a missing course — We prioritize by demand
Policy links: Privacy Policy Terms of Service Refund Policy Academic Integrity
Data shown: static
ELEMENT: Open WhatsApp
Action: external link
Destination: https://wa.me/96179057533
Writes to: none
Reads from: none
ELEMENT: Request a course
Action: navigate
Destination: /courses#course-request
Writes to: none
Reads from: none
ELEMENT: Privacy Policy
Action: navigate
Destination: /privacy
Writes to: none
Reads from: none
ELEMENT: Terms of Service
Action: navigate
Destination: /terms
Writes to: none
Reads from: none
ELEMENT: Refund Policy
Action: navigate
Destination: /refunds
Writes to: none
Reads from: none
ELEMENT: Academic Integrity
Action: navigate
Destination: /academic-integrity
Writes to: none
Reads from: none
SECTION: Site footer Copy: Shared chrome Data shown: static ELEMENT: all Shared chrome footer elements apply
PAGE: /tutoring Purpose: Public tutoring/help request intake (stored as a course request). Access: public Entry points: Direct URL (not in main nav or footer).
SECTION: Site header Copy: Shared chrome Data shown: Shared chrome ELEMENT: all Shared chrome elements apply
SECTION: Hero
Copy: Need help beyond a study pack?
Need a tutor for your course?
Request help for an AUB or LAU course when you need more than a pack: a difficult chapter, a topic explanation, exam prep, or a course that is not covered yet.
Side card: How it works This is a request path, not a full tutoring marketplace. Gradeful collects the course and topic details first. If help is available, the team can follow up with next steps. If not, the request still helps prioritize future packs and support.
Data shown: static
ELEMENT: Request help
Action: navigate
Destination: in-page #request
Writes to: none
Reads from: none
ELEMENT: View study pack plans
Action: navigate
Destination: /pricing
Writes to: none
Reads from: none
SECTION: Use cases
Copy: Eyebrow Use cases
Ask for specific help, not vague tutoring.
The better the course and topic details, the easier it is to tell whether Gradeful can help.
You are stuck before an exam — Send the course, topic, and deadline so Gradeful can understand what kind of help would actually matter.
One chapter is blocking everything — Ask for help with a specific chapter instead of searching through generic videos and old group chats.
You need a topic explained — Use the request form for a focused explanation path connected to the course you are taking.
Your course is not covered yet — Requests help Gradeful see which AUB and LAU courses need packs or support next.
Data shown: static
SECTION: Request form
Copy: Eyebrow Request
Tell us the course, topic, and kind of help you want.
This uses Gradeful's existing safe public request system. No payment is collected here, and no tutor match is promised before Gradeful reviews the request.
Form: Request help Tell us what you are stuck on. This is an intake request. It does not promise a tutor match, but it gives Gradeful the details needed to respond clearly.
Labels: Email placeholder you@example.com; University Select university / AUB / LAU / Other; Course code placeholder MATH201; Topic or chapter placeholder Sequences, organic mechanisms, circuits...; Preferred help type options Exam prep / Specific chapter / Topic explanation / Course not covered yet; Details placeholder Tell us what you need help understanding and when your exam or quiz is.
Submit: Send help request / Sending...
Success: Request sent Gradeful has your help request. Reference number: {id}. The team can use this to understand what course support students need next.
Data shown: Success {id} is course_requests.id. Topic is stored in course_requests.course_title (fallback Tutoring request). Notes are composed as Tutoring/help request plus preferred help type, topic, and details (max 500 chars).
ELEMENT: Send help request / Sending...
Action: submit
Destination: none (success state on /tutoring)
Writes to: course_requests.id, course_requests.email, course_requests.university_name, course_requests.course_code, course_requests.course_title, course_requests.instructor_name (empty), course_requests.notes
Reads from: none
SECTION: Site footer Copy: Shared chrome Data shown: static ELEMENT: all Shared chrome footer elements apply
PAGE: /policies Purpose: Index of legal/trust pages. Access: public Entry points: Account flyout All policies; direct URL.
SECTION: Site header Copy: Shared chrome Data shown: Shared chrome ELEMENT: all Shared chrome elements apply
SECTION: Hero
Copy: Eyebrow Policies
The trust layer behind the study packs.
These pages set public expectations for privacy, access, refunds, academic integrity, and original study material.
Badges: Privacy Terms Academic integrity
Data shown: static
ELEMENT: Contact Gradeful
Action: navigate
Destination: /contact
Writes to: none
Reads from: none
ELEMENT: Integrity rules
Action: navigate
Destination: /academic-integrity
Writes to: none
Reads from: none
SECTION: Policy library
Copy: Eyebrow Policy library
Legal and trust pages students can actually scan.
These policies are written for the public site and paid course-pack access. They should be reviewed by counsel before a major launch.
Rows from policyLinks: Privacy Policy note Student, schedule, usage, and support data.; Terms of Service note Rules for course packs and platform use.; Refund Policy note Course drops, withdrawals, and access issues.; Academic Integrity note Honest studying, practice, AI expectations, and original content. Each row CTA Read policy.
Data shown: static
ELEMENT: Privacy Policy / Read policy
Action: navigate
Destination: /privacy
Writes to: none
Reads from: none
ELEMENT: Terms of Service / Read policy
Action: navigate
Destination: /terms
Writes to: none
Reads from: none
ELEMENT: Refund Policy / Read policy
Action: navigate
Destination: /refunds
Writes to: none
Reads from: none
ELEMENT: Academic Integrity / Read policy
Action: navigate
Destination: /academic-integrity
Writes to: none
Reads from: none
SECTION: Operating principles
Copy: Eyebrow Operating principles The short version. Every policy should reinforce the same product posture: useful study help, honest access, original content, and no university-affiliation implication.
Independent — Gradeful is not affiliated with AUB, LAU, or any instructor.
Original — Published study material should be independently created and reviewed.
Student-safe — Policies explain data, access, refunds, and fair-use expectations in plain language.
Data shown: static
SECTION: Site footer Copy: Shared chrome Data shown: static ELEMENT: all Shared chrome footer elements apply
PAGE: /privacy Purpose: Privacy policy. Access: public Entry points: Footer; policy nav; policies index; account Learn more; support list; site map.
SECTION: Site header Copy: Shared chrome Data shown: Shared chrome ELEMENT: all Shared chrome elements apply
SECTION: Policy nav
Copy: Privacy Policy Terms of Service Refund Policy Academic Integrity
Data shown: Active path styles the current pill.
ELEMENT: Privacy Policy
Action: navigate
Destination: /privacy
Writes to: none
Reads from: usePathname() for active state
ELEMENT: Terms of Service
Action: navigate
Destination: /terms
Writes to: none
Reads from: pathname
ELEMENT: Refund Policy
Action: navigate
Destination: /refunds
Writes to: none
Reads from: pathname
ELEMENT: Academic Integrity
Action: navigate
Destination: /academic-integrity
Writes to: none
Reads from: pathname
SECTION: Title
Copy: Privacy Policy
Last updated: June 2026
Data shown: static
SECTION: Overview
Copy: Overview
Gradeful is an independent study platform for AUB and LAU students. We collect only the information needed to run course previews, course requests, support, safety, and paid course-pack features.
Gradeful is not affiliated with AUB, LAU, or any instructor. Do not upload university documents, professor materials, exam files, or private third-party content unless you have the right to share them.
Data shown: static
SECTION: Information we may collect
Copy: Information we may collect
Contact details, such as email address or support messages.
Course request details, such as university, course code, course title, instructor name, and notes.
Account details when accounts are active, such as login method, course access, and subscription status.
Schedule or enrollment proof if required to verify course access.
Payment and access records when paid access is active.
Usage, device, and security data, such as pages visited, feature usage, IP address, browser, and device identifiers.
Content feedback, correction reports, and academic-integrity reports.
Data shown: static
SECTION: How we use information
Copy: How we use information
To provide course previews, course packs, and student support.
To prioritize new AUB and LAU course content.
To verify access, payment status, and course eligibility.
To prevent abuse, account sharing abuse, scraping, or cheating.
To improve explanations, quizzes, and platform reliability.
To comply with legal, safety, and academic-integrity obligations.
Data shown: static
SECTION: AI and study assistance
Copy: AI and study assistance
If Gradeful offers AI study assistance, prompts and interactions may be processed to provide answers, improve safety, prevent abuse, and debug the product. AI features should be grounded in Gradeful course material and are not a substitute for university rules or instructor guidance.
Data shown: static
SECTION: Sharing information
Copy: Sharing information
Gradeful may share information with service providers that help run the platform, including hosting, database, analytics, email, payment, support, security, and AI providers. We may also disclose information when required by law, to protect rights and safety, or to investigate misuse.
Gradeful does not sell student personal information as a standalone data product.
Data shown: static
SECTION: Retention and deletion
Copy: Retention and deletion
We keep information for as long as needed to provide the platform, keep records, prevent abuse, resolve disputes, and comply with legal obligations. Students may request deletion of personal data, subject to records Gradeful must keep for security, payment, academic-integrity, or legal reasons.
Data shown: static
SECTION: Student responsibilities
Copy: Student responsibilities
Students should not submit confidential, copyrighted, or restricted course materials. If you believe content on Gradeful includes protected material or personal information, contact Gradeful with the course, page, and details so it can be reviewed.
Data shown: static
SECTION: Site footer Copy: Shared chrome Data shown: static ELEMENT: all Shared chrome footer elements apply
PAGE: /terms Purpose: Terms of service. Access: public Entry points: Footer; policy nav; policies index; account Learn more; support; site map.
SECTION: Site header Copy: Shared chrome Data shown: Shared chrome ELEMENT: all Shared chrome elements apply
SECTION: Policy nav
Copy: Same four pills as /privacy
Data shown: pathname for active pill
ELEMENT: same four policy nav links as /privacy
SECTION: Title
Copy: Terms of Service
Last updated: June 2026
Data shown: static
SECTION: Independent platform
Copy: Independent platform
Gradeful is an independent academic support platform. It is not affiliated with, sponsored by, or endorsed by AUB, LAU, any university, or any instructor.
Data shown: static
SECTION: Educational use
Copy: Educational use
Gradeful provides study materials, previews, practice tools, and course-pack features to support self-study. Gradeful does not guarantee grades, exam results, course outcomes, admission outcomes, or academic standing.
Students remain responsible for attending class, reading official course material, following instructor requirements, and obeying university policies.
Data shown: static
SECTION: Accounts and access
Copy: Accounts and access
Each account is intended for the approved student or approved access group only. Gradeful may limit access, revoke access, or request verification if it detects misuse, suspicious activity, or account sharing outside the allowed plan.
Data shown: static
SECTION: Payments and refunds
Copy: Payments and refunds
Paid access and payment confirmation are subject to the plan shown at purchase. Refunds are handled under the Refund Policy.
Data shown: static
SECTION: Academic integrity
Copy: Academic integrity
Students may not use Gradeful to cheat, plagiarize, submit generated or copied work as their own, bypass exam rules, or violate university policy. Gradeful may remove users or reports connected to misuse.
Data shown: static
SECTION: Content ownership and restrictions
Copy: Content ownership and restrictions
Gradeful content may not be copied, resold, scraped, uploaded to other platforms, or redistributed without permission. Students may not upload professor slides, exams, copyrighted books, paid materials, or private university files unless they have permission.
Data shown: static
SECTION: Availability and changes
Copy: Availability and changes
Gradeful may change course availability, pricing, features, policies, and access rules as the platform develops. Public catalog pages may show setup states when course data is unavailable.
Data shown: static
SECTION: Limitation of responsibility
Copy: Limitation of responsibility
Gradeful is provided as a study support service. To the maximum extent allowed by law, Gradeful is not responsible for indirect losses, academic decisions, missed deadlines, exam performance, or university disciplinary outcomes.
Data shown: static
SECTION: Site footer Copy: Shared chrome Data shown: static ELEMENT: all Shared chrome footer elements apply
PAGE: /refunds Purpose: Refund policy. Access: public Entry points: Footer; policy nav; pricing footnote; account Learn more; support; site map.
SECTION: Site header Copy: Shared chrome Data shown: Shared chrome ELEMENT: all Shared chrome elements apply
SECTION: Policy nav
Copy: Same four pills as /privacy
Data shown: pathname
ELEMENT: same four policy nav links as /privacy
SECTION: Title
Copy: Refund Policy
Last updated: June 2026
Data shown: static
SECTION: General rule
Copy: General rule
Gradeful generally issues refunds only for official course withdrawal or course drop cases that are verified with university documentation.
Refund requests are reviewed under this policy. Submitting a request does not guarantee approval.
Data shown: static
SECTION: Usually eligible for review
Copy: Usually eligible for review
Official withdrawal from the course connected to the paid pack.
Official course drop with documentation showing the relevant course and date.
Duplicate payment for the same student and same access period.
A Gradeful-side access issue that prevents use and cannot be resolved within a reasonable support window.
Data shown: static
SECTION: Usually not refundable
Copy: Usually not refundable
Change of mind after access is approved.
Partial semester use or low usage.
Exam failure, grade dissatisfaction, or course difficulty.
Missing university deadlines or ignoring official course rules.
Account removal for cheating, redistribution, abuse, or other terms violations.
Data shown: static
SECTION: How to request a refund
Copy: How to request a refund
Send the student name or account email, course code, plan purchased, payment reference if available, and official university drop or withdrawal documentation. Gradeful may ask for additional verification before approving a refund.
Data shown: static
SECTION: Processing
Copy: Processing
Approved refunds are normally returned through the original payment path when possible. Processing time may depend on the payment method, bank, wallet, or gateway.
Data shown: static
SECTION: Site footer Copy: Shared chrome Data shown: static ELEMENT: all Shared chrome footer elements apply
PAGE: /academic-integrity
Purpose: Academic integrity and original-content rules.
Access: public
Entry points: Footer; policy nav; policies Integrity rules; account Learn more; support; /content-standards permanent redirect; site map.
SECTION: Site header Copy: Shared chrome Data shown: Shared chrome ELEMENT: all Shared chrome elements apply
SECTION: Policy nav
Copy: Same four pills as /privacy
Data shown: pathname
ELEMENT: same four policy nav links as /privacy
SECTION: Title
Copy: Academic Integrity
Last updated: June 2026
Data shown: static
SECTION: What Gradeful supports
Copy: What Gradeful supports
Reviewing concepts before class, quizzes, exams, or finals.
Practicing with original questions and worked examples.
Learning from mistakes and improving problem-solving habits.
Using flashcards, formula sheets, and summaries for recall.
Asking for explanations that help you understand the method.
Data shown: static
SECTION: What Gradeful does not allow
Copy: What Gradeful does not allow
Using Gradeful during an exam, quiz, or assessment if prohibited.
Submitting Gradeful explanations or AI output as your own work.
Uploading professor slides, private exams, answer keys, or restricted files.
Requesting solutions to active graded assignments in a dishonest way.
Redistributing paid Gradeful materials outside the approved access plan.
Data shown: static
SECTION: AI study help
Copy: AI study help
If AI features are available, they should explain concepts, diagnose mistakes, and guide practice. They should not be used to bypass learning, complete prohibited work, or violate course rules.
Data shown: static
SECTION: Student contributions
Copy: Student contributions
Students, tutors, or reviewers who contribute material must only provide content they have the right to share. Contributions should be original, consented, and free of protected institutional material.
Data shown: static
SECTION: Original study material
Copy: Original study material
Gradeful materials should be independently created from student knowledge, tutor expertise, public concepts, and original synthesis. Content should explain ideas in Gradeful's own words and examples.
Gradeful should not publish professor slides, private course files, copyrighted textbooks, restricted exams, paid answer keys, or institutional materials without permission.
Data shown: static
SECTION: Review and corrections
Copy: Review and corrections
Collect student pain points and common confusion areas.
Create notes, examples, and practice from original synthesis.
Review for accuracy with tutors or subject-matter reviewers.
Use AI-assisted checks for consistency where helpful.
Publish with a correction pathway for students.
Students should be able to report unclear explanations, errors, outdated course details, or suspected protected material. Reports should include the course code, pack, section, and a clear description of the issue.
Data shown: static
SECTION: Removal requests
Copy: Removal requests
If someone believes Gradeful content infringes rights or includes restricted material, they should send enough detail for review. Gradeful may remove or revise content while the report is investigated.
Data shown: static
SECTION: Reports and enforcement
Copy: Reports and enforcement
Gradeful may remove content, restrict access, investigate reports, or suspend accounts connected to cheating, copyright misuse, harassment, scraping, redistribution, or academic-integrity violations.
Data shown: static
SECTION: Site footer Copy: Shared chrome Data shown: static ELEMENT: all Shared chrome footer elements apply
PAGE: /site-map Purpose: Internal public route tracker (not linked from header/footer). Access: public Entry points: Direct URL only.
SECTION: Site header Copy: Shared chrome Data shown: Shared chrome ELEMENT: all Shared chrome elements apply
SECTION: Hero
Copy: Eyebrow Route dashboard
Every public Gradeful route in one polished tracker.
Use this page to check the live homepage sections, public pages, policies, and account routes.
Badges: Public pages Account Policies
Data shown: static
ELEMENT: Back home
Action: navigate
Destination: /
Writes to: none
Reads from: none
SECTION: Counts
Copy: Number {publicRoutes.length} then Public pages. Number {accountRoutes.length} then Account routes. Number {policyLinks.length} then Policy routes.
Data shown: Counts are publicRoutes.length (Homepage, Sign in, Sign up, Forgot password, Reset password, plus Courses/Pricing/About from siteNavLinks), accountRoutes.length (1), policyLinks.length (4). Not database.
SECTION: Public pages
Copy: Heading Public pages and {n} routes. Each card: label, path, note, badge Open.
Homepage — / — Main public search homepage.
Sign in — /login — Email, social, and phone authentication entry point.
Sign up — /signup — Student account creation and email verification entry point.
Forgot password — /forgot-password — Password recovery email request form.
Reset password — /reset-password — Secure new-password form for recovery links.
Courses — /courses (no note on siteNavLinks)
Pricing — /pricing
About — /about
Data shown: static lists in app/site-map/page.tsx + siteNavLinks
ELEMENT: Open (each row)
Action: navigate
Destination: that row’s href
Writes to: none
Reads from: none
SECTION: Account
Copy: Account {n} routes
My courses — /my-courses — Protected dashboard for active student course access.
Data shown: static
ELEMENT: Open
Action: navigate
Destination: /my-courses (middleware sends logged-out users to login)
Writes to: none
Reads from: none
SECTION: Policies
Copy: Policies {n} routes plus the four policyLinks labels/notes from Shared chrome / PublicPageShell
Data shown: static policyLinks
ELEMENT: Open
Action: navigate
Destination: /privacy /terms /refunds /academic-integrity
Writes to: none
Reads from: none
SECTION: Homepage sections
Copy: Homepage sections {n} routes
Homepage hero — / — Search-first landing hero.
What's inside — / — Homepage tutoring tools overview.
Data shown: static
ELEMENT: Open
Action: navigate
Destination: /
Writes to: none
Reads from: none
SECTION: Site footer Copy: Shared chrome Data shown: static ELEMENT: all Shared chrome footer elements apply
PAGE: /faq Purpose: Legacy FAQ URL; not a rendered page. Access: public Entry points: Old bookmarks/external links.
SECTION: Redirect
Copy: none (no page body)
Data shown: none
ELEMENT: none — next.config.ts redirects /faq → /pricing (temporary)
PAGE: /access
Purpose: Legacy “how access works” URL; not a rendered page.
Access: public
Entry points: Contact hero How access works; leftover /access links.
SECTION: Redirect
Copy: none (no page body)
Data shown: none
ELEMENT: none — redirect("/pricing")
PAGE: /content-standards Purpose: Legacy content-standards URL; not a rendered page. Access: public Entry points: Old bookmarks/external links.
SECTION: Redirect
Copy: none (no page body)
Data shown: none
ELEMENT: none — permanentRedirect("/academic-integrity")
PAGE: /markitup Purpose: Separate public cinematic site for MarkItUp (Beirut marketing studio). Does not use Gradeful header/footer or brand tokens. Access: public Entry points: Direct URL only (not in Gradeful nav/footer).
SECTION: Preloader (skipped when prefers-reduced-motion: reduce)
Copy: Loading
Skip control uses Skip the sequence
Giant numeric progress 00–100 (dynamic)
Lighting the street
markitup.lb
Data shown: Progress is client animation, not a database.
ELEMENT: Skip the sequence Action: toggle Destination: none (dismisses preloader) Writes to: none Reads from: none
SECTION: Fixed header
Copy: Wordmark MARKIT + U (rocket glyph). Instagram chip @{markitup.handle} → @markitup.lb
Data shown: static lib/markitup/content.ts
ELEMENT: @markitup.lb
Action: external link
Destination: https://www.instagram.com/markitup.lb/
Writes to: none
Reads from: none
SECTION: Scroll film
Copy: Screen-reader h1: We don’t just market. We move brands.
Hint: Scroll
Chapter copy is dynamic from scroll progress (lib/markitup/film.ts filmChapters), not a CMS:
01 — Beirut, at night / A quiet brand is already falling. / Lights off. Nobody looking. The rocket waits in the window like a thing that never launched.
02 — The mark / We don’t just market. / A gold line is drawn. The object becomes a mark. The night starts to move.
03 — Consulting / We sit with the business first. / Through the glass, onto the table. Maps, the gap, the rocket in the centre.
04 — Strategy / Every post is a move. / The rocket lifts. Gold lines connect. Noise becomes a system.
05 — Full-service / We move brands. / The street is the same. The window is not. The rocket leaves the sill.
06 — MarkItUp / DM us to get started. / Consulting. Strategy. Full-service packages. The work begins in a message.
Data shown: static chapter table; visible chapter depends on scroll position.
ELEMENT: @markitup.lb (shown on last chapter)
Action: external link
Destination: https://www.instagram.com/markitup.lb/
Writes to: none
Reads from: Visible when chapter.showCta is true (signal chapter)
Notes
/courses?q=and?university=hydrate catalog search. University filters useuniversities.short_nameslugs.- Course request forms use
#course-request. Tutoring help on/tutoringkeeps its own#requestform. - Pricing cards use code
PLANS; homepage prices can followplatform_settings.plan_overrides. platform_settings.show_pricing_publiclyis stored in admin but does not gate/pricing.- Course request + tutoring request both insert
course_requests(no tutoring table). - Marketing Get access / plan CTAs enter 03-checkout.md; Sign in enters 02-auth-onboarding.md.