Skip to content

Adding content

Every recipe below is a git-tracked file edit. Run npm run dev while you work so you see the result live, then commit and push to publish (see Local dev and deploy). Full field reference lives in Content collections.

  1. Create src/content/fsae/<slug>.mdx. The slug becomes the URL, so keep it short and hyphenated, e.g. bms-can-integration.mdx renders at /fsae/bms-can-integration.

  2. Add the frontmatter. Required: title, date, subsystem (firmware | manufacturing | autonomous), summary. Set subsystem correctly: it color-codes the post everywhere it appears.

  3. Write the body in MDX. To use content components, import them at the top:

    ---
    title: BMS to CAN Integration
    date: 2025-03-02
    subsystem: firmware
    season: 2025 Season
    summary: "Bringing the battery-management data onto the car's CAN bus."
    tags: [BMS, CAN, Firmware]
    draft: false
    ---
    import Gallery from '../../components/content/Gallery.astro';
    The BMS talks isoSPI internally, but the rest of the car speaks CAN...
    <Gallery labels={['SCOPE · isoSPI', 'BUS · CAN TRACE']} cols={2} />
  4. (Optional) Add a hero/cover image (co-locate the file and reference it, e.g. cover: ./can-trace.jpg) or a heroVideo (public/ path). Set draft: true to keep it out of the build until it is ready.

  1. Create src/content/projects/<slug>.mdx, e.g. spectrum-analyzer.mdx renders at /projects/spectrum-analyzer.

  2. Add the frontmatter. Required: title, date, kind, summary. Common optional fields: stack[], links.repo, links.demo, order (lower sorts first on the index), featured.

    ---
    title: Music Spectrum Analyzer
    date: 2025-02-10
    kind: Embedded · DSP
    stack: [STM32, C, FFT, Altium, SolidWorks]
    summary: "A 28-band acrylic spectrum analyzer driven by FFT DSP on an STM32."
    order: 1
    featured: true
    links:
    repo: https://github.com/CPollreis/spectrum-analyzer
    draft: false
    ---
    import Gallery from '../../components/content/Gallery.astro';
    I wanted to actually see music on the wall...
  3. Write the MDX body. Add a video (YouTube/Vimeo URL) for a lead demo video, or a cover/hero image for the header.

  1. Create src/content/photography/<NN-slug>.md. The numeric prefix keeps the files ordered on disk; the order field controls actual display order.

  2. Add photo frontmatter (no MDX body needed). story is the caption shown in the lightbox.

    ---
    title: Cold Start
    kind: photo
    date: 2025-01-12
    story: First frost test of the season, breath fogging the viewfinder.
    location: Winnipeg, MB
    camera: Sony α7 III
    lens: 35mm f/1.8
    iso: "400"
    aperture: f/2.0
    focal: 35mm
    image: ./cold-start.jpg
    ratio: 3/2
    order: 9
    ---
  3. Drop the image next to the Markdown file and reference it with a relative path (image: ./cold-start.jpg). astro:assets optimizes it automatically. Leave image out to render an on-brand placeholder for now.

  1. Create src/content/photography/<NN-slug>.md with kind: video.

  2. Point video at a public/ path, and provide fps/quality for the tech readout. Optionally add an image to use as the poster frame.

    ---
    title: Green Over Superior
    kind: video
    date: 2024-05-11
    story: The G5 aurora storm. The whole sky moved like curtains.
    location: Lake Superior, MN
    camera: Sony α7 III
    fps: "24"
    quality: 4K UHD
    video: /videos/green-over-superior.mp4
    image: ./green-over-superior-poster.jpg
    ratio: 16/9
    order: 1
    ---
  3. Export the clip as two files with the same basename and put both in public/videos/:

    • public/videos/green-over-superior.webm (VP9/AV1)
    • public/videos/green-over-superior.mp4 (H.264)

    Reference the .mp4 in frontmatter (video: /videos/green-over-superior.mp4). The gallery derives the .webm sibling and lists it first, so Firefox decodes the webm in software while other browsers use the mp4. Shipping only the mp4 works everywhere except it can stutter or fail to decode on Firefox/macOS, so always ship the pair. More detail in Media guidelines and the footage.ts section of Architecture.

    In the archive grid, video moments autoplay muted while scrolled into view and pause off-screen (an IntersectionObserver in src/pages/photography/index.astro manages them); the tile still opens the lightbox like any photo.

The /photography archive is a modular “Feature Lead” grid: the packer in src/components/photography/archiveGrid.ts reads the whole collection (sorted by order) and fills repeating 2-row bands on a 4-column grid, so there is no layout file to edit when the collection grows. Two frontmatter fields decide a moment’s shape:

Frontmatter Shape in the grid
vertical ratio (3/4, 2/3, 9/16) Tall: one column wide, the full band height - exactly twice the height of a 3/2 still.
feature: true (non-vertical ratios) Lead: an oversized 2x2 cell. At most one per band, and leads alternate left/right from band to band.
anything else Still: a standard cell; stills stack two per column.

Practical notes:

  • Give each band at most one feature: true moment if you care exactly where leads land; extra features simply lead later bands.
  • The typographic index tile (“12 moments · 2021 - 2026 · …”) is generated automatically from whatever cells the final band leaves open. Its counts update on their own; never edit it by hand.
  • On small screens the same tiles reflow into a 2-column dense grid and the index tile hides itself.
  • To reorder the archive, change order values (and ideally the NN- filename prefix to match); the packer re-lays everything out at build time.
  • npm run dev and open the relevant page to confirm it renders.
  • npm run build runs astro check, which fails loudly on a bad enum, a missing required field, or a broken image reference. A green build means the content is valid.