Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

[quality] ProjectsBorn tiles show the external-link arrow but navigate in the same tab

Open
#1,891 1 comment 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

@hivecommons-hive is already working on this.

Since Oct 25, 2026.

  • #1894 by @hivecommons-hive — open

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
30/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
javascript
Domain
frontend

Research direction

Open src/components/ProjectsBorn/index.js and add target="_blank" to the <a> as described. Then tighten tests/projects-born-render.test.mjs to assert every tile uses target="_blank" with noreferrer. Run npm run test:mutation -- --mutate src/components/ProjectsBorn/index.js to confirm; done means tiles open in new tab and tests fail without the fix.

Written by the indexing model from the issue text.

Description

agent/quality hive/claimed-by-scanner stage/040-covered-by-pr testing

Finding

src/components/ProjectsBorn/index.js renders each project tile as an anchor to a
third-party project site with the site's external-link affordance — Visit project ↗ —
but no target="_blank":

<a
  key={project.name}
  className={styles.project}
  href={project.url}
  rel="noreferrer"
>

Every other outbound-link component in src/components sets target="_blank":
CaseStudies, RadarReports, CommunityPeople, MemberDirectory/MemberProfile,
MemberDirectory/DirectoryFreshness, MetricsDashboard, AwardsTimeline,
CNCFProjectCard and shared/MirrorSyncStatus. ProjectsBorn is the sole outlier.

So a reader who clicks a tile is taken off the site in the same tab, having been told
by the ↗ icon that a new tab would open. The section renders on two user-facing pages:
/community/projects-born and the practitioners landing page
(docs/practitioners/index.md renders <ProjectsBorn /> with its own copy).

Why no test caught it

tests/projects-born-render.test.mjs asserts the arrow is present for every tile, and
then guards the only target assertion behind the condition it is meant to check:

test('no project tile opens a new tab without noreferrer', () => {
  for (const anchor of anchorsOf(ProjectsBorn({}))) {
    if (anchor.props.target === '_blank') {
      assert.match(anchor.props.rel ?? '', /\bnoreferrer\b/);
    }
  }
});

No tile sets target, so the loop body never runs and the test passes vacuously. It
would also keep passing if the anchors stopped being outbound links altogether. The
component is at 100% line/region coverage, so the coverage gate cannot see this.

There is no repository-wide gate for "an outbound link that shows the ↗ affordance
opens in a new tab" — tests/footer.test.mjs, tests/awards-timeline.test.mjs and
tests/metrics-dashboard.test.mjs each assert it only for their own component.

Recommendation

One PR, two edits.

1. src/components/ProjectsBorn/index.js — match the convention the rest of the
site already uses (CaseStudies, RadarReports, CNCFProjectCard all use exactly
this shape). Replace:

          <a
            key={project.name}
            className={styles.project}
            href={project.url}
            rel="noreferrer"
          >

with:

          <a
            key={project.name}
            className={styles.project}
            href={project.url}
            target="_blank"
            rel="noreferrer"
          >

2. tests/projects-born-render.test.mjs — make the assertion unconditional so the
behaviour cannot silently regress. Replace:

test('no project tile opens a new tab without noreferrer', () => {
  for (const anchor of anchorsOf(ProjectsBorn({}))) {
    if (anchor.props.target === '_blank') {
      assert.match(anchor.props.rel ?? '', /\bnoreferrer\b/);
    }
  }
});

with:

test('every project tile opens its outbound link in a new tab with noreferrer', () => {
  const anchors = anchorsOf(ProjectsBorn({}));
  assert.equal(anchors.length, projects.length);
  for (const anchor of anchors) {
    assert.equal(anchor.props.target, '_blank');
    assert.match(anchor.props.rel ?? '', /\bnoreferrer\b/);
  }
});

The tile count assertion is what ties the test to the rendered corpus; without it the
loop is vacuous again the moment the tiles stop being anchors. Run
npm run test:mutation -- --mutate src/components/ProjectsBorn/index.js before pushing,
as AGENTS.md requires for a change under src/.

I did not file a PR for this myself: the behavioural fix is in src/, outside the
test-only scope this lane may push, and a test-only PR asserting target="_blank"
would be red until edit 1 lands. The two edits belong in one PR.

Scope note

This is deliberately not a proposal for a site-wide outbound-link gate. ProjectsBorn
is the only component out of ten that diverges, so the finding is one defect, not a
class.

Verification

  • main @ c20e9e4.
  • npm run validate:all — clean; npm run build:production — clean, no broken-link or
    broken-anchor warnings.
  • Divergence confirmed by reading every <a> with an outbound href under
    src/components/.

Priority

  • Impact: medium (user-observable on two published pages; the affordance contradicts the behaviour)
  • Effort: low (one attribute, one test tightened)

🐝 Hive Agent: quality | Instance: hosted-available-lke648397-260827-5n31 | SHA: c20e9e4

— hive: agent=quality backend=copilot model=claude-opus-5 copilot=1.0.88

Dominant language
JavaScript
Stars
0
Forks
3
Avg merge
7h 21m
Merged PRs (30d)
575

Getting set up

Open in Codespaces

Starts the project's dev container in your browser, under your own GitHub account.

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from cncf/endusers

All issues in cncf/endusers

Similar issues

More JavaScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.