Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
172 changes: 172 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
# Contributing to the CoreCollective Website

This guide covers the working group page components — how they work, and how to add or update content for any working group.

## Architecture Overview

Each working group page (`/working-groups/<slug>`) is built from three sources:

1. **MDX content** (`src/content/working-groups/<slug>.mdx`) — the evergreen page body (projects, mailing list, resources)
2. **Members data** (`src/content/wg-members/<slug>.yaml`) — structured member list rendered as a logo grid
3. **News data** (`src/content/wg-news/<slug>.yaml`) — time-sensitive announcements shown above the page content

The page template at `src/pages/working-groups/[slug].astro` loads all three and renders them together. Members and news are both optional — if a YAML file doesn't exist for a given slug, that section simply won't render.

---

## WG News Feed (`WGNews` component)

The news panel appears at the top of a working group page, above the evergreen MDX content. It shows the most recent announcements (up to 3 by default, sorted by date descending).

### Adding news items

Create or edit `src/content/wg-news/<slug>.yaml`:

```yaml
heading: Latest News # optional, defaults to "Latest News"
items:
- headline: FFmpeg ARM64EC binaries now available
body: Prebuilt FFmpeg binaries for Windows on Arm are published for download.
date: 2026-07-01
links:
- { label: FFmpeg ARM64EC release page, href: https://github.com/Multicorewareinc/FFmpeg/releases }

- headline: Python 3.13 native wheels shipping
body: Pure-Python and compiled wheels now build natively on WoA CI runners.
date: 2026-06-15
```

### Field constraints

| Field | Required | Constraints |
|-------|----------|-------------|
| `headline` | Yes | 1–120 characters |
| `body` | Yes | 1–300 characters |
| `date` | Yes | Valid date (YAML date or ISO string) |
| `links` | No | Array of `{ label, href }` where `href` is a valid URL |

The build will fail if any constraint is violated — this is intentional so broken content doesn't ship.

### Behaviour

- Items are sorted by date (newest first), with deterministic tie-breaking on headline
- At most 3 items are shown (configurable in code via `selectLatestNews`)
- If no news file exists or items is empty, the news section doesn't render at all
- The "More below" chevron at the bottom is a passive visual indicator (not clickable)

---

## WG Members List (`WGMembers` component)

The members section renders below the MDX content as a responsive logo grid.

### Adding members

Create or edit `src/content/wg-members/<slug>.yaml`:

```yaml
heading: Working Group Members # optional
members:
- { name: Arm, logo: arm }
- { name: CIX, logo: cix }
- { name: Linaro, logo: linaro }
- { name: Microsoft, logo: microsoft }
- { name: Qualcomm, logo: qualcomm }
```

### Using the logo registry

The `logo` field references a key in `src/lib/companyLogos.ts`. Available keys:

| Key | Company | Notes |
|-----|---------|-------|
| `arm` | Arm | Scaled to 0.75 |
| `cix` | CIX | Scaled to 0.8 |
| `linaro` | Linaro | |
| `microsoft` | Microsoft | |
| `qualcomm` | Qualcomm | |

To add a new company to the registry, add an entry to the `companyLogos` map in `src/lib/companyLogos.ts`:

```ts
newcompany: {
src: "https://static.corecollective.dev/company_logos/newcompanyLogo.svg",
alt: "NewCompany logo",
scale: "0.9", // optional — adjusts visual size relative to peers
},
```

### Inline logos (no registry)

If a member's logo isn't in the registry, you can provide `src` and `alt` directly:

```yaml
members:
- name: NewStartup
src: https://example.com/logo.svg
alt: NewStartup logo
scale: "0.85" # optional
```

When using inline `src`, the `alt` field is required (the build will fail without it).

### Field constraints

| Field | Required | Constraints |
|-------|----------|-------------|
| `name` | Yes | 1–200 characters |
| `logo` | No* | Must match a key in the registry |
| `src` | No* | Valid URL |
| `alt` | Only with `src` | 1–300 characters |
| `scale` | No | String like `"0.75"` — applied as CSS transform |

*Each member must have either `logo` or `src` (or both, where inline values override the registry).

### Behaviour

- Members render in the order listed in YAML — this is the display order on the page
- Maximum of 50 members per working group
- If no members file exists or the array is empty, the section doesn't render
- Logos are constrained to fit uniformly with `object-contain` and responsive max dimensions

---

## Working Group MDX Content

The MDX file at `src/content/working-groups/<slug>.mdx` contains the main page body. It supports standard Markdown plus Astro components:

```mdx
---
title: Windows on Arm Working Group
description: Targeting application layer support for Windows.
---

import Note from '../../components/Note.astro';

## Section heading

Content here...

<Note>
Important callout rendered in a styled box.
</Note>
```

Don't put member lists in the MDX — use the YAML data file instead so they render as logos.

---

## Adding a New Working Group

1. Create `src/content/working-groups/<slug>.mdx` with `title` and `description` frontmatter
2. Optionally create `src/content/wg-members/<slug>.yaml` with the member entries
3. Optionally create `src/content/wg-news/<slug>.yaml` with news items
4. The page will be available at `/working-groups/<slug>/` on next build

The slug must match across all three files.

---

## Validation

All content files are validated at build time with Zod schemas. If something is wrong, the build will fail with a descriptive error message pointing to the offending field. Run `npm run build` locally to catch issues before pushing.
14 changes: 14 additions & 0 deletions src/components/Note.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
interface Props {
label?: string;
}

const { label = 'Note' } = Astro.props;
---

<div class="not-prose rounded-lg bg-white/5 p-4 text-sm text-gray-400 [&_a]:text-cc-cyan [&_a]:underline">
<p>
<strong class="text-gray-200">{label}:</strong>
<slot />
</p>
</div>
34 changes: 34 additions & 0 deletions src/components/WGMembers.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
---
import type { ResolvedMember } from '../lib/companyLogos';

interface Props {
members: ResolvedMember[];
heading?: string;
}

const { members, heading } = Astro.props;
---

{members.length > 0 && (
<section class="mt-12 pt-10 border-t border-gray-700">
{heading && (
<h2 class="text-cc-cyan text-center text-2xl font-bold mb-8">
{heading}
</h2>
)}
<ul
class="flex w-full flex-wrap items-center justify-center gap-8 px-4 sm:gap-10 md:gap-12"
>
{members.map((member) => (
<li class="flex shrink-0 items-center justify-center">
<img
src={member.src}
alt={member.alt}
class="max-h-10 max-w-[7rem] object-contain sm:max-h-12 sm:max-w-[9rem] md:max-h-14 md:max-w-[12rem]"
style={member.scale ? `transform: scale(${member.scale});` : undefined}
/>
</li>
))}
</ul>
</section>
)}
58 changes: 58 additions & 0 deletions src/components/WGNews.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
---
import type { NewsItem } from '../lib/wgNews';

interface Props {
items: NewsItem[];
heading?: string;
}

const { items, heading = 'Latest News' } = Astro.props;
---

{items.length > 0 && (
<section class="mb-10 rounded-2xl border border-gray-700 bg-gray-900/40 p-6 md:p-8">
<h2 class="text-cc-cyan mb-6 text-2xl font-bold">{heading}</h2>

<div class="space-y-6">
{items.map((item) => (
<div class="border-b border-gray-700 pb-6 last:border-b-0 last:pb-0">
<h3 class="text-cc-cyan mb-2 text-lg font-semibold">{item.headline}</h3>
<p class="text-gray-200">{item.body}</p>
{item.links && item.links.length > 0 && (
<ul class="mt-3 flex flex-wrap gap-4">
{item.links.map((link) => (
<li>
<a
href={link.href}
class="text-cc-cyan underline decoration-transparent transition-colors hover:decoration-current focus:outline-none focus:ring-2 focus:ring-cc-cyan focus:ring-offset-2 focus:ring-offset-gray-900 rounded"
>
{link.label}
</a>
</li>
))}
</ul>
)}
</div>
))}
</div>

<div class="mt-6 flex flex-col items-center text-gray-400">
<span class="text-sm">More below</span>
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="2"
stroke="currentColor"
class="mt-1 h-4 w-4"
aria-hidden="true"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M19.5 8.25l-7.5 7.5-7.5-7.5"
/>
</svg>
</div>
</section>
)}
56 changes: 56 additions & 0 deletions src/content/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,65 @@ const faqCollection = defineCollection({
),
});

const workingGroupsCollection = defineCollection({
type: 'content',
schema: z.object({
title: z.string(),
description: z.string(),
}),
});

const wgMemberSchema = z
.object({
name: z.string().min(1).max(200),
logo: z.string().min(1).optional(),
src: z.string().url().optional(),
alt: z.string().min(1).max(300).optional(),
scale: z.string().optional(),
})
.refine((m) => Boolean(m.logo) || Boolean(m.src), {
message: 'Member must provide either a `logo` key or an inline `src`.',
})
.refine((m) => !m.src || Boolean(m.alt), {
message: 'Inline `src` requires `alt` text.',
});

const wgMembersCollection = defineCollection({
type: 'data',
schema: z.object({
heading: z.string().optional(),
members: z.array(wgMemberSchema).max(50),
}),
});

const wgNewsItemSchema = z.object({
headline: z.string().min(1).max(120),
body: z.string().min(1).max(300),
date: z.coerce.date(),
links: z
.array(
z.object({
label: z.string().min(1),
href: z.string().url(),
})
)
.optional(),
});

const wgNewsCollection = defineCollection({
type: 'data',
schema: z.object({
heading: z.string().optional(),
items: z.array(wgNewsItemSchema),
}),
});

export const collections = {
blogs,
logos: logosCollection,
leadership: leadershipCollection,
faq: faqCollection,
'working-groups': workingGroupsCollection,
'wg-members': wgMembersCollection,
'wg-news': wgNewsCollection,
};
7 changes: 7 additions & 0 deletions src/content/wg-members/windows-on-arm.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
heading: Working Group Members
members:
- { name: Arm, logo: arm }
- { name: CIX, logo: cix }
- { name: Linaro, logo: linaro }
- { name: Microsoft, logo: microsoft }
- { name: Qualcomm, logo: qualcomm }
7 changes: 7 additions & 0 deletions src/content/wg-news/windows-on-arm.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
heading: Latest News
items:
- headline: FFmpeg ARM64EC binaries now available
body: Prebuilt FFmpeg binaries for Windows on Arm are published for download.
date: 2026-07-01
links:
- { label: FFmpeg ARM64EC release page, href: https://github.com/Multicorewareinc/FFmpeg/releases }
Loading
Loading