Skip to content
ProFinda Learning

Internal reference

How this portal works

The objects the content is made of, how they connect, and why each part of the stack was chosen. Kept out of the main navigation, which is for learners, and linked in the footer instead. It is here for whoever maintains the portal next.

73

Content files

8

Object types

0 KB

Framework JS on a lesson

2

Interactive islands

The objects

Each object type is a folder of Markdown files under src/content/. The file name is the slug, and the slug is how everything refers to everything else. Schemas live in src/content.config.ts.

topics

9

The nine subject areas everything is filed under.

titlesummaryordericon

pathways

3

An ordered run of courses for one audience.

courses[]audiencetopicorder

courses

9

A unit of learning. Belongs to a topic, optionally to a pathway.

topicpathway?levelmandatoryrecommended

lessons

24

The pages people actually read. MDX, so they can use components.

courseorderobjectives[]related[]

docs

12

Reference material, filed into five sections.

sectionorderownertags[]

quizzes

6

A knowledge check. Questions and answers live in frontmatter.

topiccourse?questions[]

news

6

Releases, announcements and deprecations.

datetypeversion?

videos

4

Metadata only. The catalogue links out to where the video lives.

durationurltopic

How they connect

References are plain slug strings, not database joins. Structural links are validated when the site builds. Optional links are not, on purpose: a mistyped related-doc slug hides that one link instead of breaking the build.

TOPICS9 filesPATHWAYS3 filesCOURSES9 filesLESSONS24 filesgroupscourses[] in ordercourse + orderNEWS6 files · standaloneVIDEOS4 files · standaloneQUIZZES6 filesDOCS12 filesquiz.course (optional)lesson.related[] (optional)structural, checked at buildoptional, degrades quietly

Topic is the spine

Courses, pathways, quizzes and videos all carry a topic slug. That one field is what makes the topic pages and the catalogue filters possible.

A course can stand alone

pathway is optional. Courses without one are served from their own route rather than being hidden.

Docs have five sections

Getting started, Core concepts, Integrations, Administration, Troubleshooting. Administration is flagged admin-only in src/lib/sections.ts.

What happens on build

There is no server and no database. pnpm build turns the folder of Markdown into a folder of HTML, then indexes that HTML for search.

Markdownsrc/contentSchema checkcontent.configRendersrc/pagesStatic HTMLdist/Search indexpagefind

The stack, and why

Astro 7

Framework

A learning portal is documents, not an app. Astro renders every page to static HTML at build time and ships no framework JavaScript unless a component explicitly asks for it.

Markdown and MDX

Content

Content is plain text files in folders, editable without touching code. MDX is used only where a page needs a component such as a callout or a step list.

TypeScript

Schemas and logic

The collection schemas are the contract. A missing required field or a typo in an enum fails the build with a message naming the file, so mistakes never reach the live site.

Tailwind 4

Styling

Tailwind 4 is CSS-first, so there is no config file. Every colour, font and radius is a token in one @theme block in global.css.

React 19

Interactive islands

Two things genuinely need client-side state: the search palette and the charts. They load as islands. Every other page has no React on it at all.

Pagefind

Search

A search index generated from the built HTML. No search server to run and no API key to hold. It only indexes tagged content regions, so navigation and footers never appear in results.

localStorage

Personal state

Progress, bookmarks and quiz scores stay in the browser. Prototype behaviour, deliberately isolated behind one file so it can be swapped for a real backend.

What runs in the browser

Every page

Command palette

The only island on a content page. Opens with ⌘K and queries the Pagefind index.

/insights only

Recharts

Loaded lazily, and only on the one page that draws charts. It never reaches a lesson.

Progressive

Small inline scripts

Progress ticks, bookmarks and quiz answers. Plain DOM work, no framework, and the page reads fine without them.

Where personal state lives

Completions, bookmarks, saved courses, quiz scores and preferences are held in the browser under a single localStorage key. Nothing is sent anywhere, and clearing site data resets it.

Every read and write goes through src/lib/store.ts. No page touches localStorage directly, so when a real backend arrives that one file is the only thing that changes.

The routes

Files in src/pages/ become URLs. Names in brackets are built once per matching content file.

/learn

Catalogue, filters, saved and mandatory

/learn/[pathway]

Pathway overview with the progress spine

/learn/[pathway]/[course]

Course inside a pathway

/learn/course/[course]

Course with no pathway

/learn/topics/[slug]

Everything under one topic

/lesson/[slug]

A single lesson

/quiz/[slug]

A knowledge check

/docs

Docs index

/docs/[section]/[slug]

A single doc

/insights

Charts. The only page loading Recharts

Adding content never means writing code: drop a Markdown file into the right folder with the fields its schema asks for, and the catalogues, topic pages, search index and navigation pick it up on the next build.