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 :::features to filter clientPortalCards.json per client.
      • Parse :::portfolio and render PortfolioCard items directly on the landing page.
      • Parse :::vocabulary and :::concepts and 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 toProperCase in fallback title logic.
      • Refactored to use processEntries from site/src/utils/slugify.ts to normalize entries similarly to the reference index page.
      • Converted processed entries into ReferenceItem shape expected by ReferenceGrid.
  • MOC files
    • Added/updated per-client files with directive blocks:
      • content/moc/Laerdal.md
      • content/moc/Tonguc.md
      • content/moc/Param.md
      • content/moc/Hypernova.md
      • content/moc/Avalanche.md
      • content/moc/Flourish.md
      • content/moc/Colearn.md
      • content/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
    • :::portfolio list parsed from content/moc/<Client>.md.
    • Resolution uses existing resolvePortfolioId in site/src/utils/toolUtils.ts and the client-portfolios collection; no new path logic.
    • Each resolved entry is rendered with PortfolioCard in a responsive grid at the top of the landing page.
  • Reference terms (vocabulary, concepts)
    • The layout parses :::vocabulary and :::concepts and passes arrays to ClientReferenceSection.
    • The section uses processEntries to normalize collection entries and then maps the passed titles to ReferenceItems for ReferenceGrid.
    • Casing is preserved by avoiding automatic title-casing transforms.
  • Environment-aware content path
    • All filesystem reads for client content and MOC use contentBasePath/resolvedContentPath from envUtils, preserving deploy-specific roots.

Integration Points

  • PortfolioCard remains the canonical UI for portfolio entries; now also used on the client landing page.
  • ReferenceGrid continues 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

  1. For each client, ensure a content/moc/<Client>.md exists (Proper Case, spaces allowed).
  2. Move any reference terms from deleted reference-terms.json into the appropriate MOC blocks:
    • :::vocabulary for vocabulary entries
    • :::concepts for concept entries
  3. If using featured portfolio, add a :::portfolio block with a bullet list of references (backlink syntax preferred: [[Name]]).
  4. Optionally add a :::features block to control which portal cards display.

Breaking Changes

  • JSON fallback for reference terms has been removed. If :::vocabulary/:::concepts are 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.astro demonstrates processEntries normalization now mirrored in ClientReferenceSection.

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).