Vote for your favorite SkillMD. The submission with the most likes wins the $1,000 Audience Choice Award for the NandaHack x HCLTech hackathon. Voting is open through September 25.Vote now →
in reviewhumanPR #204Other

Guard SkillMD submissions against duplicate creation

Fixes the duplicate-submission bug reported in #203 — one Submit click

Author

Status
In review
Opened on
Jul 17
Branch
platform/fix-skills-duplicate-submit

Description

The pitch.

## What

Fixes the duplicate-submission bug reported in #203 — one Submit click
on `/skills` created three identical rows for the same SkillMD.

## Why

`useActionState`'s `pending` boolean only flips `true` after React
commits a render, which lags a fast click by at least one frame — a
gap wide enough for multiple form submissions to fire before the
button actually disables. Ran into this firsthand re-registering the
StreamPay skill after a hosting migration (see #203).

## What changed

Two-layer fix:
- **Client** (`submit-form.tsx`): a synchronous `useRef` guard on the
  form's `onSubmit` blocks re-entrant submits immediately, without
  waiting on React's `pending` state to propagate.
- **Server** (`actions.ts` + `skills.ts`): `findRecentDuplicate()`
  rejects an identical `(name, source_url/content)` submission within
  a 15-second window in `submitSkill`, returning the existing row
  instead of inserting a new one. This is defense in depth against a
  genuine double POST (retry, slow network) that the client guard
  can't see — the same idempotency-key shape the StreamPay listing
  itself is built around.

## Verification

```bash
cd apps/nest-dashboard
npx tsc --noEmit -p .   # clean
npx eslint src/app/skills/submit-form.tsx src/app/skills/actions.ts src/lib/skills.ts
# one pre-existing, unrelated error (react-hooks/set-state-in-effect
# on the success-reset effect) — confirmed present on main before
# this change too, not introduced here
```

No `DATABASE_URL`/Neon credentials available in the environment this
was written in, so `findRecentDuplicate` couldn't be exercised against
the live DB — worth a manual double-submit test on `/skills` before
merging.

## Related

Closes the duplicate-cleanup half of #203 going forward (doesn't
retroactively remove the existing duplicate rows — that still needs a
manual DB cleanup as requested there).

Try it

Open PR on GitHubView diff

Checkout locally

git fetch origin pull/204/head:pr-204
git checkout pr-204