Commit 37c7c806 authored by Wohlgemuth, Jason's avatar Wohlgemuth, Jason
Browse files

dev: Add cross-platform build tasks and copilot config

parent a07b9130
Loading
Loading
Loading
Loading
Loading
+129 −0
Original line number Diff line number Diff line
# Copilot Instructions: Research Activity Index

## Project Overview
This is an Astro-based catalog website showcasing ORNL research projects. Content is managed through JSON files and synchronized from GitLab repositories using the custom **ACORN CLI tool** (Accessible Content Optimization for Research Needs).

## Architecture

### Content Pipeline
- **Source of Truth**: Research project data lives in external GitLab repositories (defined in `buckets.json`)
- **ACORN CLI**: Custom Rust tool (`./acorn`) downloads, validates, and formats JSON content
- **Data Location**: `src/data/{project-id}/index.json` - each project has its own directory with JSON + media
- **Content Collection**: Astro's content layer (`src/content.config.ts`) uses glob loader to ingest all `src/data/**/*.json` files
- **Static Routes**: `src/pages/[project].astro` generates individual project pages at build time

### Data Schema
All project JSON files follow this structure:
```json
{
  "meta": {
    "identifier": "project-slug",
    "archive": false,
    "draft": false,
    "websites": [],
    "media": [{"caption": "...", "contentUrl": "00.png"}],
    "keywords": [],
    "technology": []
  },
  "title": "Project Title",
  "subtitle": "Brief description",
  "sections": {
    "mission": "...",
    "challenge": "...",
    "approach": [],
    "impact": [],
    "research": {"focus": "...", "areas": []}
  },
  "contact": {"givenName": "...", "familyName": "...", "email": "..."}
}
```

## Critical Workflows

### Content Management
```bash
# Install ACORN CLI (first time setup)
# Linux/Mac: ./scripts/install_acorn.sh
# Windows: .\scripts\install_acorn.ps1

# Download all project data from GitLab buckets (requires ACORN CLI)
npm run download  # Cleans src/data, downloads from buckets.json, formats, copies to public/

# Manual operations
npm run clean     # Removes src/data and public/data
npm run format    # Validates and formats JSON using ACORN
npm run copy      # Copies src/data to public/data for runtime access
```

**Key Insight**: `src/data` is the build-time source (Astro content collections), `public/data` is runtime source (for image paths, API-like access).

**Cross-Platform**: All npm scripts use `scripts/run.js` wrapper that automatically selects the correct binary (`acorn` on Linux/Mac, `acorn.exe` on Windows).

### Development
```bash
npm run dev       # Astro dev server with --host --open flags
npm run build     # Runs build:pdf and build:src in parallel
npm run build:pdf # Exports PDFs using ACORN CLI
```

### Linting & Testing
```bash
npm run lint       # Runs lint:code and lint:data in parallel
npm run lint:code  # ESLint with custom stylistic rules
npm run lint:data  # ACORN schema validation
npm test           # Playwright tests (configured for Chromium only)
```

## React/Astro Hybrid Pattern
- **Astro Components**: Static layout (`Header.astro`, `Footer.astro`, `Section.astro`)
- **React Islands**: Interactive components use `client:only` or `client:load` directives
  - `<Controls client:only />` - Search/filter controls (no SSR, prevents hydration issues)
  - `<Listing client:only />` - Project cards with Fuse.js search
  - `<Carousel client:load />` - Image carousel (loads after hydration)

**Why client:only?** These components depend on browser APIs (window.location, URLSearchParams) and have no meaningful SSR output.

## Key Conventions

### File Organization
- `src/pages/*.astro` - Routes (index = catalog, [project] = dynamic detail pages)
- `src/components/*.{astro,tsx}` - Mixed Astro/React components
- `src/components/ui/` - shadcn/ui components (ESLint ignored)
- `src/lib/utils.ts` - Shared utilities (URL params, string sorting)

### Styling
- **TailwindCSS** via `@astrojs/tailwind` (base styles disabled, using shadcn/ui globals)
- **Scoped CSS** in `.astro` files for component-specific styles
- **CSS Variables**: Font families loaded via Astro's experimental font provider (Lato, Open Sans, Oswald, Roboto)

### ESLint Rules (custom)
- 4-space indentation (not 2)
- 1TBS brace style
- Arrow parens: `as-needed`
- Semicolons: required
- Ignores: `src/components/ui/` (shadcn), `src/env.d.ts`, test examples

## Search & Filtering
- **Fuse.js** powers fuzzy search across 15+ fields (title, subtitle, mission, keywords, contact info)
- **URL-based state**: Search/filter state persists via query params (`?q=keyword&search=term`)
- **Keywords**: Clickable labels that update URL params to filter catalog
- See `src/components/Listing.tsx` for implementation details

## Image Handling
Images are loaded dynamically using Astro's `import.meta.glob`:
```javascript
const images = import.meta.glob('src/**/*.{png,jpg,jpeg}', { import: 'default' });
const path = `/src/data/${project}/${contentUrl}`;
```
Images must exist in `src/data/{project}/` for build-time optimization.

## Common Pitfalls
1. **Don't manually edit `src/data/`** - It's generated by `npm run download`
2. **ACORN CLI required** - Run `scripts/install_acorn.sh` (Linux/Mac) or `scripts/install_acorn.ps1` (Windows) to get the binary
3. **Double data copies** - `src/data` (build) vs `public/data` (runtime) is intentional
4. **GitLab dependencies** - `buckets.json` references private ORNL GitLab repos; external contributors can't run `npm run download`

## Testing
- Playwright configured for Chromium only (Firefox/WebKit commented out)
- Run tests with `npm test` (uses `tests/*.spec.ts`)
- CI/CD runs ESLint but skips Playwright in GitLab pipeline
+2 −2
Original line number Diff line number Diff line
@@ -28,8 +28,8 @@
        "**/.git": true,
        "**/.svn": true,
        "**/.hg": true,
        "**/CVS": true,
        "**/.DS_Store": true,
        "**/Thumbs.db": true
        "**/Thumbs.db": true,
        "**/CVS": true
    }
}
 No newline at end of file
+4 −4
Original line number Diff line number Diff line
@@ -8,17 +8,17 @@
    "dev": "astro dev --host --open",
    "dev:mac": "astro dev --host",
    "predownload": "npm run clean",
    "download": "./acorn download --buckets buckets.json --output src/data",
    "download": "node scripts/run.js download --config ../buckets.json --output ../src/data",
    "postdownload": "run-s format copy",
    "start": "astro dev",
    "build:pdf": "./acorn export src/data --output public/pdf",
    "build:pdf": "node scripts/run.js export ../src/data --output ../public/pdf",
    "build:src": "astro build",
    "build": "run-p build:*",
    "preview": "astro preview",
    "astro": "astro",
    "format": "./acorn format src/data --ignore highlight -vv",
    "format": "node scripts/run.js format ../src/data --ignore highlight -vv",
    "lint:code": "eslint --fix --config ./eslint.config.js",
    "lint:data": "./acorn check src/data",
    "lint:data": "node scripts/run.js check ../src/data",
    "lint": "run-p lint:*"
  },
  "dependencies": {

scripts/acorn.exe

0 → 100644
+35.6 MiB

File added.

No diff preview for this file type.

+14 −0
Original line number Diff line number Diff line
# PowerShell script to install ACORN CLI for Windows
$ACORN_VERSION = "0.1.27"
$URL = "https://code.ornl.gov/api/v4/projects/16689/packages/generic/x86_64-pc-windows-msvc/v$ACORN_VERSION/acorn.exe"

Write-Host "Downloading ACORN CLI version $ACORN_VERSION for Windows..."
Invoke-WebRequest -Uri $URL -OutFile "acorn.exe"

if (Test-Path "acorn.exe") {
    Write-Host "ACORN CLI installed successfully!"
    & .\acorn.exe --version
} else {
    Write-Error "Failed to download ACORN CLI"
    exit 1
}
Loading