Gradeful
CoursesPricingAbout

How Gradeful connects

Raw markdown

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
  • /courses listing
  • /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 use universities.short_name slugs.
  • Course request forms use #course-request. Tutoring help on /tutoring keeps its own #request form.
  • Pricing cards use code PLANS; homepage prices can follow platform_settings.plan_overrides.
  • platform_settings.show_pricing_publicly is 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.
Gradeful

Course-specific study packs for AUB and LAU students. Built for focused self-study.

Gradeful is an independent study-support service. Universities named on this site are listed only so you can match a Gradeful pack to the course you are taking. Those universities do not provide, sponsor, or endorse Gradeful, and Gradeful does not claim access to their official materials or assessments.

© 2026 Gradeful.

Platform

HomeCoursesPricing

Policies

Privacy PolicyTerms of ServiceRefund PolicyAcademic Integrity