Vitest’s HTML reporter is excellent: interactive, fast, and genuinely useful for debugging. But it generates local files. When your teammate asks “what failed?”, you can’t just send them a link. You end up screenshotting terminal output or walking them through downloading CI artifacts.
The Sharing Problem
After vitest run, your HTML report lands in a local directory. To share it with your team, you need to get that file to them somehow. Here’s what most teams do:
Common (Bad) Solutions
1. CI artifacts
- GitHub Actions keeps artifacts for 90 days max, other CI systems are shorter
- Finding the right artifact means clicking through workflow runs
- Recipient downloads a zip, extracts it, opens
index.htmllocally - QA might not even have CI access
2. Email or Slack the file
- “Here’s the test report” with a zip attachment
- Recipient has to download, extract, open in browser
- Version confusion when multiple runs are in flight
3. Upload to S3 manually
- Works, but someone has to set up the bucket, permissions, and cleanup
- Manual step every time, so it gets skipped when things are busy
4. Paste terminal output
- Loses all the interactive HTML goodness
- Hard to parse in a Slack thread
- Can’t reference it later
Better: Hosted Vitest Reports with Shareable Links
The fix is straightforward: upload your Vitest reports to a hosting service after every CI run. Every test run gets a permanent URL that anyone on your team can open.
What This Looks Like
- CI runs your Vitest tests
- Reports upload automatically
- You get a URL like
https://app.gaffer.sh/reports/abc123 - Share it in Slack, GitHub PRs, Jira, or anywhere else
- Anyone with access sees the full interactive report
No downloads. No manual steps. No expiring artifacts.
Setting Up Vitest Report Sharing with Gaffer
Step 1: Configure Vitest Reporters
Make sure you’re generating output Gaffer can parse. CTRF gives the richest analytics:
npm install vitest-ctrf-json-reporter --save-devimport { defineConfig } from 'vitest/config'
export default defineConfig({ test: { reporters: [ 'default', ['vitest-ctrf-json-reporter', { outputDir: '.', outputFile: 'ctrf-report.json' }], ], }})If the reporter fails with ENOENT, see why jest-ctrf-json-reporter throws ENOENT. Gaffer also accepts Vitest’s built-in HTML and JSON reporters if you prefer those; the Vitest JSON reporter output format is documented field by field. If you also want to set up a Vitest coverage report and track it across runs, that’s a separate upload step covered in the coverage guide.
Step 2: Add the Upload Step to CI
GitHub Actions:
- name: Run tests run: npm test
- name: Upload to Gaffer if: always() uses: gaffer-sh/gaffer-uploader@v2 with: gaffer_upload_token: ${{ secrets.GAFFER_PROJECT_TOKEN }} report_path: ./ctrf-report.json commit_sha: ${{ github.sha }} branch: ${{ github.ref_name }}GitLab CI:
test: script: - npm ci - npm test after_script: - | curl -X POST https://app.gaffer.sh/api/upload \ -H "X-API-Key: $GAFFER_PROJECT_TOKEN" \ -F "[email protected]" \ -F 'tags={"commitSha":"'"$CI_COMMIT_SHA"'","branch":"'"$CI_COMMIT_REF_NAME"'"}'Step 3: Share the Link
After upload, Gaffer returns a URL. Share it anywhere: Slack, GitHub PR comments, Jira tickets. Recipients see the full report in their browser.
For people outside your organization, you can generate a public share link with configurable expiration. They view the full interactive report without needing a Gaffer account.
Slack and Webhook Notifications
Instead of checking CI manually, get notified when tests finish:
Slack integration:
- Pass/fail summary posted to your channel
- Direct link to the full report
- Filter by branch: only notify on
main, skip feature branches
Webhooks:
- Send test results to any endpoint
- Integrate with your existing alerting or workflow tools
- Trigger custom actions on failure
No more “did the tests pass?” messages. Your team sees failures as they happen, with a link to investigate.
GitHub Integration
Commit statuses show test results directly on PRs. No clicking through to CI logs. You see pass/fail right on the commit.
One Dashboard for Every Suite
Most JavaScript teams run Vitest for unit tests and Playwright or Cypress for end-to-end. Gaffer aggregates multiple test frameworks into one dashboard, so unit and e2e results land in the same place instead of separate report folders.
What About Flaky Tests?
Vitest’s --retry flag handles flaky tests within a single run. Gaffer tracks flakiness across runs, identifying tests that sometimes pass and sometimes fail over time. Different problem, complementary solution.
Get Started
Gaffer’s free tier includes 500 MB of storage with 7-day retention. Paid plans offer extended retention up to 90 days.