Skip to content
Closed
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
5 changes: 4 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,9 @@ unblock a PR.

### 6. Close the loop

Thank the contributor and link any follow-up work. The PR owner checks the post-merge result and
Thank the contributor and link any follow-up work. Once merged, external authors appear in the
"Thank you" section of the [Contribute page](https://microsoft.github.io/scope/community/contribute/#thank-you)
and on the landing page within about an hour. The PR owner checks the post-merge result and
coordinates a fix or revert if needed.

If a contribution is not a fit, explain why and close it promptly. When a PR is waiting on the
Expand Down Expand Up @@ -337,6 +339,7 @@ Automations depend on these exact names:
| Test Improver issues, PRs, and monthly-summary searches | `type: automation`, `topic: testing` |
| Dependabot | `type: dependencies`, plus `language: javascript` or `language: rust` |
| Pull Request Labeler | Area, topic, language, and type labels from `.github/labeler.yml` |
| Website open calls ([Contribute page](https://microsoft.github.io/scope/community/contribute/)) | Open, unassigned `good first issue` or `help wanted` issues |

Use `area: reporting` for Scope's benchmark reporting component, not daily repository activity.
Worker upgrade routing uses `type: worker-update`, not the broader `area: worker`.
Expand Down
68 changes: 66 additions & 2 deletions website/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,70 @@ components open them in a new tab (`target="_blank"
rel="noopener noreferrer"`) with a screen-reader "(opens in a new
tab)" hint; keep that pattern for any new external link.

### Contribution issues

The landing page ("Help build Scope") and **Community → Contribute**
list open, unassigned issues labeled `good first issue` or
`help wanted`. The list is data, not content, so it isn't in the
build:

- [`.github/workflows/contribution-issues.yml`](../.github/workflows/contribution-issues.yml)
runs every hour, on issue events, and on demand. It writes
`issues.jsonl` to the orphan `website-data` branch and commits only
when the file changes. Run it once by hand (`workflow_dispatch`) to
create the branch.
- `issues.jsonl` is deterministic so diffs stay small: one issue per
line, sorted by number, with sorted keys and only `number`, `title`,
and sorted `labels`. Don't add fields that change on every run
(timestamps, comment counts). An empty file means there are no open
calls.
- The browser fetches the file from `raw.githubusercontent.com`
(`DATA_URL` in
[`contribution-issues.ts`](src/scripts/contribution-issues.ts)).
Set `PUBLIC_CONTRIBUTION_ISSUES_URL` to point at another file.
- Display order is decided client-side: good first issues first, then
newest. `area:`, `difficulty:`, and `type:` labels show as chips.
- The landing section shows 4 issues at a time and rotates through all
of them every 7 seconds (`rotate` prop). The active page dot fills
as a progress bar. Rotation pauses on hover, on keyboard focus, when
off screen or the tab is hidden, and with the pause button. It never
autoplays under reduced motion; the dots still work.
- In `pnpm run dev`, if the fetch fails (no branch yet, offline), the
list falls back to
[`contribution-issues.sample.jsonl`](src/data/contribution-issues.sample.jsonl)
and shows a "Sample data · dev only" tag. Production builds drop
that branch and the sample.
- Titles and labels come from GitHub users. Render them with
`textContent` only, never `innerHTML`.
- Motion uses the Web Animations API, with no animation library. Gate
any new motion on `prefers-reduced-motion`.

### Community contributors

The landing page (an avatar wall under the open calls) and the
"Thank you" section of **Community → Contribute** (a card grid)
thank external authors of merged pull requests:

- The same workflow writes `contributors.jsonl` to `website-data` in
the same commit as `issues.jsonl`. It counts merged PRs whose
author is a user, not a bot (`[bot]` suffix), and whose
`authorAssociation` isn't `MEMBER`, `OWNER`, or `COLLABORATOR`.
- One line per person, `{"login":"…","prs":N}`, with sorted keys and
sorted by lowercase login. No avatar URLs or timestamps; avatars come
from `https://github.com/<login>.png`, and a failed image shows the
login's initial.
- The browser sorts by merged PRs, then login. The wall shows up to
`limit` items; the last slot becomes a "+N" bubble that links to
the full grid. Each person links to their merged PRs.
- Set `PUBLIC_CONTRIBUTORS_URL` to point at another file
([`contributors.ts`](src/scripts/contributors.ts)). In
`pnpm run dev` a failed fetch falls back to
[`contributors.sample.jsonl`](src/data/contributors.sample.jsonl),
which lists real external contributors only; don't pad it with other
accounts.
- Logins are user data: render them with `textContent` or attributes
only.

### Style

- Hard-wrap prose at ~70–80 columns for readable diffs.
Expand All @@ -226,7 +290,7 @@ tab)" hint; keep that pattern for any new external link.

```sh
pnpm install
pnpm test # plugin regressions, using Node's built-in test runner
pnpm test # plugin and script tests, using Node's built-in test runner
pnpm run build # writes dist/
pnpm run dev # local preview at http://localhost:4321
pnpm run refresh:openapi # generate the OpenAPI snapshot from scope-core
Expand All @@ -235,7 +299,7 @@ pnpm run refresh:openapi # generate the OpenAPI snapshot from scope-core
Both `pnpm test` and `pnpm run build` must pass. The public build uses
`SITE=https://microsoft.github.io BASE_PATH=/scope pnpm run build`;
exercise that configuration when changing links or deployment settings,
not just the local `/` default. The current snapshot produces **203
not just the local `/` default. The current snapshot produces **215
pages**, including the generated API reference. An unexpected drop in
page count can indicate a content collection file failed to parse.

Expand Down
21 changes: 16 additions & 5 deletions website/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ The product and this documentation site live in
├── src/
│ ├── assets/
│ ├── components/ # Astro landing, interactive example, header, page title, site footer
│ │ └── community/ # article/talk lists + landing teaser
│ │ ├── community/ # article/talk lists + landing teaser
│ │ └── contribute/ # open calls + contributor thanks (landing + page)
│ ├── content/
│ │ ├── docs/ # all user-facing pages (.md / .mdx)
│ │ │ ├── introduction/
Expand All @@ -28,11 +29,14 @@ The product and this documentation site live in
│ │ │ └── community/
│ │ ├── articles/ # one YAML per published article
│ │ └── talks/ # one YAML per talk
│ ├── data/ # dev-only samples: contribution issues, contributors
│ ├── openapi/scope-openapi.json # artifact generated from the API registry
│ ├── plugins/
│ │ ├── remark-base-path.mjs # applies the deployment base to internal links
│ │ └── remark-http-snippets.mjs # turns ```http blocks into multi-language tabs
│ ├── scripts/flow-demo.ts # progressive-enhancement example controller
│ ├── scripts/contribution-issues*.ts # open calls: data helpers + custom element
│ ├── scripts/contributors*.ts # contributor thanks: data helpers + custom element
│ ├── styles/landing.css # shared brand tokens + scoped landing styles
│ └── content.config.ts
├── astro.config.mjs # sidebar, plugins, starlight-openapi config
Expand All @@ -51,7 +55,7 @@ Sidebar order is defined in `astro.config.mjs`, not by directory order.
| `pnpm dev` | Start dev server at the worktree's `DOC_PORT` (fallback: 4300) |
| `pnpm build` | Build the production site to `./dist/` |
| `pnpm preview` | Preview the production build locally |
| `pnpm test` | Test site plugins with Node's built-in test runner |
| `pnpm test` | Test site plugins and scripts with Node's built-in test runner |
| `pnpm refresh:openapi` | Generate the OpenAPI snapshot from `scope-core` |

## Authoring docs
Expand Down Expand Up @@ -140,9 +144,16 @@ table of contents, code examples, and previous/next navigation.
- **Onboarding:** a concrete example before terminology, followed by
separate Portal, CLI, and API entry points. Access requirements are
explicit rather than promising instant access to a hosted service.
- **Motion:** limited to the silent showreel and the interactive
example, with pause controls and reduced-motion support. The logo
and documentation chrome remain still.
- **Motion:** limited to the silent showreel, the interactive
example, the open-calls cards (staggered entrance, count-up,
cursor glow, a rotation through all open calls), and the
contributor avatars (pop-in, hover tooltips), with pause controls
and reduced-motion support. The logo and documentation chrome remain
still.
- **Contribution:** a "Help build Scope" section lists open calls
for contributions and thanks community contributors, refreshed
hourly from a data branch without a redeploy. See "Contribution
issues" and "Community contributors" in `AGENTS.md`.

### Showreel

Expand Down
5 changes: 4 additions & 1 deletion website/astro.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,10 @@ export default defineConfig({
},
{
label: 'Community',
items: [{ label: 'Articles & talks', slug: 'community/articles-and-talks' }],
items: [
{ label: 'Articles & talks', slug: 'community/articles-and-talks' },
{ label: 'Contribute', slug: 'community/contribute' },
],
},
{
label: 'Getting Started',
Expand Down
2 changes: 1 addition & 1 deletion website/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"start": "worktree-env && astro dev",
"build": "astro build",
"preview": "worktree-env && astro preview",
"test": "node --test src/plugins/*.test.mjs",
"test": "node --test src/plugins/*.test.mjs src/scripts/*.test.mjs",
"astro": "astro",
"refresh:openapi": "cd .. && pnpm --filter api generate:openapi"
},
Expand Down
2 changes: 2 additions & 0 deletions website/src/components/Home.astro
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
---
import CommunityTeaser from './community/CommunityTeaser.astro';
import ContributeTeaser from './contribute/ContributeTeaser.astro';
import FlowDemo from './FlowDemo.astro';

const base = import.meta.env.BASE_URL.replace(/\/?$/, '/');
Expand Down Expand Up @@ -137,6 +138,7 @@ const paths = [
</section>

<CommunityTeaser />
<ContributeTeaser />

<section class="scope-cta" aria-labelledby="cta-heading">
<p class="scope-eyebrow">Bring your own question</p>
Expand Down
40 changes: 40 additions & 0 deletions website/src/components/contribute/ContributeTeaser.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
---
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

import ContributionIssues from './ContributionIssues.astro';
import Contributors from './Contributors.astro';

const allHref = `${import.meta.env.BASE_URL.replace(/\/$/, '')}/community/contribute/`;
---

<section class="scope-section scope-contrib" aria-labelledby="contrib-heading">
<ContributionIssues limit={4} variant="cards" rotate>
<div class="scope-section-heading">
<div data-reveal>
<p class="scope-eyebrow">Open source</p>
<h2 id="contrib-heading">Help build Scope</h2>
</div>
<div class="scope-contrib__intro" data-reveal>
<p>Pick an open call, then open a pull request that references it. No need to ask first.</p>
<p class="contrib-count" data-count-pill>
<span class="contrib-count__pulse" aria-hidden="true"></span>
<span aria-hidden="true"><span class="contrib-count__value" data-count>0</span> <span data-count-label>open calls</span></span>
<span class="sr-only" data-count-text></span>
</p>
</div>
</div>
</ContributionIssues>
<a class="scope-text-link scope-contrib__all" href={allHref}>See all open calls <span aria-hidden="true">&rarr;</span></a>
<Contributors variant="wall" limit={24}>
<div class="thanks-head" data-reveal>
<h3 id="thanks-heading"><span class="thanks-heart" aria-hidden="true">&hearts;</span> Thank you, contributors</h3>
<p class="contrib-count" data-count-pill>
<span class="contrib-count__pulse" aria-hidden="true"></span>
<span aria-hidden="true"><span class="contrib-count__value" data-count>0</span> <span data-count-label>contributors</span> · <span data-prs>0 merged PRs</span></span>
<span class="sr-only" data-count-text></span>
</p>
</div>
<p class="thanks-intro" data-reveal>Everyone below got a pull request merged into Scope. Hover an avatar to see how many.</p>
</Contributors>
</section>
62 changes: 62 additions & 0 deletions website/src/components/contribute/ContributionIssues.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
---
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

// Lists open, unassigned issues labeled "good first issue" or "help wanted".
// The contribution-issues workflow publishes the list to the website-data
// branch, and the browser fetches it, so it stays fresh without
// redeploying the site. See website/AGENTS.md.
import '../../styles/contribution-issues.css';
import { CONTRIBUTION_LABELS, DATA_URL, searchUrl } from '../../scripts/contribution-issues';

interface Props {
/** Maximum number of issues to show. Omit to show them all. */
limit?: number;
/** `cards` for the animated landing grid, `list` for the docs page. */
variant?: 'cards' | 'list';
/** Cycle through all issues, `limit` at a time. Needs `limit`. */
rotate?: boolean;
}

const { limit, variant = 'cards', rotate = false } = Astro.props;
const src = import.meta.env.PUBLIC_CONTRIBUTION_ISSUES_URL || DATA_URL;
const skeletons = Math.min(limit ?? 4, 4);
const [goodFirst, helpWanted] = CONTRIBUTION_LABELS.map((label) => ({ label, href: searchUrl(label) }));
---

<scope-contribution-issues class={`contrib contrib--${variant} not-content`} data-variant={variant} data-limit={limit} data-rotate={rotate && limit ? '' : undefined} data-src={src} data-state="loading">
<slot />
<p class="contrib-sample-tag" data-sample-tag hidden>Sample data · dev only</p>
<ul class="contrib-list" data-list aria-busy="true" aria-label="Open calls for contributions">
{
Array.from({ length: skeletons }, () => (
<li class="contrib-item contrib-skeleton" aria-hidden="true">
<span class="contrib-skeleton__line contrib-skeleton__line--short" />
<span class="contrib-skeleton__line" />
<span class="contrib-skeleton__line contrib-skeleton__line--mid" />
</li>
))
}
</ul>
<p class="contrib-message contrib-message--empty">
Every open call is taken right now. Check back soon, or browse
<a href={`https://github.com/microsoft/scope/issues`} target="_blank" rel="noopener noreferrer">open issues on GitHub<span class="sr-only"> (opens in a new tab)</span></a>.
</p>
<p class="contrib-message contrib-message--error">
We couldn't load the list. Browse
<a href={goodFirst!.href} target="_blank" rel="noopener noreferrer">good first issues<span class="sr-only"> (opens in a new tab)</span></a>
or
<a href={helpWanted!.href} target="_blank" rel="noopener noreferrer">help wanted issues<span class="sr-only"> (opens in a new tab)</span></a>
on GitHub.
</p>
<p class="contrib-fallback">
Browse open calls on GitHub:
<a href={goodFirst!.href} target="_blank" rel="noopener noreferrer">good first issues<span class="sr-only"> (opens in a new tab)</span></a>
·
<a href={helpWanted!.href} target="_blank" rel="noopener noreferrer">help wanted<span class="sr-only"> (opens in a new tab)</span></a>
</p>
</scope-contribution-issues>

<script>
import '../../scripts/contribution-issues-element';
</script>
53 changes: 53 additions & 0 deletions website/src/components/contribute/Contributors.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
---
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

// Thanks community contributors: external authors of merged pull requests.
// The contribution-issues workflow publishes the list to the website-data
// branch, and the browser fetches it. See website/AGENTS.md.
import '../../styles/contribution-issues.css';
import '../../styles/contributors.css';
import { CONTRIBUTORS_DATA_URL, CONTRIBUTORS_GRAPH_URL } from '../../scripts/contributors';

interface Props {
/** `wall` for the landing avatar wall, `grid` for the docs page cards. */
variant?: 'wall' | 'grid';
/** Maximum number of items on the wall, including the "+N" bubble. */
limit?: number;
}

const { variant = 'wall', limit } = Astro.props;
const src = import.meta.env.PUBLIC_CONTRIBUTORS_URL || CONTRIBUTORS_DATA_URL;
const base = import.meta.env.BASE_URL.replace(/\/$/, '');
const moreHref = `${base}/community/contribute/#thank-you`;
const openCallsHref = `${base}/community/contribute/#open-calls`;
const skeletons = variant === 'wall' ? 8 : 3;
---

<scope-contributors class={`thanks thanks--${variant} not-content`} data-variant={variant} data-limit={limit} data-src={src} data-more-href={moreHref} data-state="loading">
<slot />
<p class="contrib-sample-tag" data-sample-tag hidden>Sample data · dev only</p>
<ul class="thanks-list" data-list aria-busy="true" aria-label="Community contributors">
{
Array.from({ length: skeletons }, () => (
<li class="thanks-item thanks-skeleton" aria-hidden="true" />
))
}
</ul>
<p class="contrib-message thanks-message--empty">
No community pull request has been merged yet. Be the first:
<a href={openCallsHref}>pick an open call</a>.
</p>
<p class="contrib-message thanks-message--error">
We couldn't load the list. See
<a href={CONTRIBUTORS_GRAPH_URL} target="_blank" rel="noopener noreferrer">contributors on GitHub<span class="sr-only"> (opens in a new tab)</span></a>.
</p>
<p class="contrib-fallback">
See
<a href={CONTRIBUTORS_GRAPH_URL} target="_blank" rel="noopener noreferrer">contributors on GitHub<span class="sr-only"> (opens in a new tab)</span></a>.
</p>
</scope-contributors>

<script>
import '../../scripts/contributors-element';
</script>
37 changes: 37 additions & 0 deletions website/src/content/docs/community/contribute.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
---
title: Contribute
description: Open issues where the Scope team is calling for contributions, and how to pick one up.
---

import ContributionIssues from '../../../components/contribute/ContributionIssues.astro';
import Contributors from '../../../components/contribute/Contributors.astro';

Scope is open source, and some issues are set aside for the community.
Each one below is open and nobody is assigned to it yet.

## How to pick one up

1. Choose an issue below. **Good first issue** marks a small, well-scoped
change. **Help wanted** marks work where an outside hand helps most.
2. Read the
[contributing guide](https://github.com/microsoft/scope/blob/main/CONTRIBUTING.md)
to set up your environment and learn the conventions.
3. Open a pull request that references the issue, for example
`Fixes #123`. You don't need to comment on the issue or ask first.

The first time you contribute, a bot asks you to sign the Microsoft
Contributor License Agreement (CLA). You only sign it once.

## Open calls

The list refreshes about every hour.

<ContributionIssues variant="list" />

## Thank you

Thank you to everyone outside the Scope team who got a pull request
merged. Select a name to see their merged pull requests. This list also
refreshes about every hour.

<Contributors variant="grid" />
Loading
Loading