Client Portal uses MOC directives for Features, Portfolio, and Reference Terms
Summary
Re-architected the Client Portal to be fully markdown-driven via MOC (Map of Contents) directives. The portal now reads per-client feature toggles, featured portfolio items, and reference terms (vocabulary and concepts) directly from
content/moc/<Client>.md. Removed legacy JSON fallback for reference terms and preserved original capitalization throughout the reference pipeline. Also added a featured portfolio grid to the client landing page.Why Care
- Single source of truth in markdown: editors can author all client-facing selections in one place.
- Eliminates brittle JSON duplication and reduces drift between data sources.
- Preserves capitalization (e.g., "AI Models", "AI Avatars") for higher fidelity presentation.
- Enables fast per-client customization (cards, portfolios, terms) without code changes.
Implementation
Changes Made
- Client landing layout
- Edited:
site/src/layouts/ClientPortalLayout.astro- Parse
:::featuresto filterclientPortalCards.jsonper client. - Parse
:::portfolioand renderPortfolioCarditems directly on the landing page. - Parse
:::vocabularyand:::conceptsand pass them as props to the reference section. - Added responsive grid styling for the featured portfolio section.
- Reference section
- Edited:
site/src/components/client-portals/ClientReferenceSection.astro- Switched to markdown-driven props (
selectedVocabulary,selectedConcepts) only. - Removed JSON filesystem fallback and all fs/path imports.
- Preserved original casing; removed
toProperCasein fallback title logic. - Refactored to use
processEntriesfromsite/src/utils/slugify.tsto normalize entries similarly to the reference index page. - Converted processed entries into
ReferenceItemshape expected byReferenceGrid.
- MOC files
- Added/updated per-client files with directive blocks:
content/moc/Laerdal.mdcontent/moc/Tonguc.mdcontent/moc/Param.mdcontent/moc/Hypernova.mdcontent/moc/Avalanche.mdcontent/moc/Flourish.mdcontent/moc/Colearn.mdcontent/moc/Obsidian Plugin Community.md
- Each may include:md
:::features - Reader - Projects - Portfolio - Recommendations ::: :::portfolio - [[Aalo Atomics]] - [[Pencil Spaces]] ::: :::vocabulary - [[Agile]] - [[AI Models]] ::: :::concepts - [[Coherence]] - [[AI Avatars]] :::
- Removed files (JSON fallback for reference terms)
- Deleted:
content/client-content/Laerdal/reference-terms.json - Deleted:
content/client-content/Param/reference-terms.json - Deleted:
content/client-content/Tonguc/reference-terms.json
Technical Details
- Features filtering
- The layout loads
src/content/messages/clientPortalCards.json(unchanged structure) and filters by normalized names from:::features. - Includes alias handling (e.g., common misspelling "Reccomendations" → "Recommendations").
- Featured portfolio
:::portfoliolist parsed fromcontent/moc/<Client>.md.- Resolution uses existing
resolvePortfolioIdinsite/src/utils/toolUtils.tsand theclient-portfolioscollection; no new path logic. - Each resolved entry is rendered with
PortfolioCardin a responsive grid at the top of the landing page.
- Reference terms (vocabulary, concepts)
- The layout parses
:::vocabularyand:::conceptsand passes arrays toClientReferenceSection. - The section uses
processEntriesto normalize collection entries and then maps the passed titles toReferenceItems forReferenceGrid. - Casing is preserved by avoiding automatic title-casing transforms.
- Environment-aware content path
- All filesystem reads for client content and MOC use
contentBasePath/resolvedContentPathfromenvUtils, preserving deploy-specific roots.
Integration Points
PortfolioCardremains the canonical UI for portfolio entries; now also used on the client landing page.ReferenceGridcontinues to render list items, now driven by processed entries to unify behavior with the reference index page.- No changes required to
content.config.ts; existing collections are reused.
Migration Steps
- For each client, ensure a
content/moc/<Client>.mdexists (Proper Case, spaces allowed). - Move any reference terms from deleted
reference-terms.jsoninto the appropriate MOC blocks::::vocabularyfor vocabulary entries:::conceptsfor concept entries
- If using featured portfolio, add a
:::portfolioblock with a bullet list of references (backlink syntax preferred:[[Name]]). - Optionally add a
:::featuresblock to control which portal cards display.
Breaking Changes
- JSON fallback for reference terms has been removed. If
:::vocabulary/:::conceptsare not defined for a client, their reference section will be empty.
Documentation
- Authoring MOC blocks occurs in
content/moc/<Client>.md. - Reference:
site/src/pages/more-about/index.astrodemonstratesprocessEntriesnormalization now mirrored inClientReferenceSection.
Follow-ups
- Add validation or build-time warnings when MOC references cannot be resolved (e.g., portfolio names that don’t match entries).
- Consider surfacing counts/logs on the client page to aid troubleshooting (hidden dev mode).