One step in your pipeline. Every build artifact — test reports, coverage HTML, Storybook builds, API docs — gets a permanent authenticated URL accessible to the whole team.
- name: Publish artifact
run: dsp publish ./output/ --name "build-${{ github.run_id }}"
env:
DISPLAY_TOKEN: ${{ secrets.DISPLAY_TOKEN }}That's it. Every build run produces a permanent URL. Post it as a PR comment. Link it from your Slack build notification. Bookmark it for the QA lead.
Every CI run produces HTML output. Playwright test reports. Jest coverage reports. Storybook builds. Swagger UI from your OpenAPI spec. Bundle analysis visualizations. Lighthouse reports.
The current fate of most CI artifacts:
Display adds one step to your CI pipeline and gives every artifact a permanent authenticated URL.
Step 1: Add your token as a secret
In GitHub: Settings → Secrets and variables → Actions → New repository secret
Name: DISPLAY_TOKEN
Value: your Display API token (generate in Display dashboard)
Step 2: Add the publish step
- name: Install Display CLI
run: npm install -g @display-dev/cli
- name: Publish artifact
run: |
dsp publish ./output-dir/ \
--name "artifact-${{ github.run_id }}" \
--title "${{ github.workflow }} #${{ github.run_number }}"
env:
DISPLAY_TOKEN: ${{ secrets.DISPLAY_TOKEN }}Step 3: Optionally post the URL as a PR comment
- name: Comment URL on PR
if: github.event_name == 'pull_request'
uses: actions/github-script@v7
with:
script: |
const url = `https://yourco.display.dev/artifact-${{ github.run_id }}`;
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `📊 Build artifact: ${url}`
})Playwright reports:
- run: dsp publish ./playwright-report/ --name "playwright-${{ github.run_id }}"Jest coverage:
- run: dsp publish ./coverage/lcov-report/ --name "coverage-${{ github.ref_name }}"Storybook build:
- run: dsp publish ./storybook-static/ --name "storybook-${{ github.ref_name }}"Lighthouse CI report:
- run: dsp publish ./.lighthouseci/ --name "lighthouse-${{ github.run_id }}"Bundle analysis (webpack-bundle-analyzer):
- run: dsp publish ./bundle-analysis.html --name "bundle-${{ github.run_id }}"Swagger UI (built from OpenAPI spec):
- run: |
redocly build-docs openapi.yaml --output ./api-docs/index.html
dsp publish ./api-docs/ --name "api-docs"| Display | GitHub Actions ZIP | GitHub Pages (private) | Gaffer | |
|---|---|---|---|---|
| Any HTML artifact | ✅ | ❌ (no rendering) | ✅ | ❌ (Playwright only) |
| Company SSO | ✅ | ❌ | ❌ / $2,100/mo | ✅ |
| Permanent URLs | ✅ | ❌ (expires) | ✅ | ✅ |
| PR comment integration | ✅ | ❌ | ✅ | ✅ |
| CI setup time | 5 min | 0 | 20+ min | 10 min |
| Monthly price | $49 flat | $0 | $2,100/mo | Paid |
Free — one-time password auth, 50MB, unlimited viewers
Teams ($49/month) — Google + Microsoft SSO, 25GB, custom domain, unlimited viewers
Yes. The CLI works anywhere Node.js is available. Replace GitHub Actions variables with GitLab CI equivalents:
Yes. Install the CLI with npm install -g @display-dev/cli and run dsp publish as a shell step. Works with any CI that can run Node.js commands.
Yes. Use unique names per build: --name "playwright-${{ github.run_id }}". Each build run gets its own permanent URL. The history accumulates in your Display workspace.
Manage artifacts via the Display dashboard or REST API — delete old runs programmatically. Or use the --ttl flag (coming soon) to set automatic expiration for transient artifacts.
The free tier (50MB total storage) is limited for high-frequency CI publishing. Teams tier (25GB) is sized for active CI pipelines — hundreds of builds per month.
Free tier. No credit card. One-time password auth on free, Google + Microsoft SSO on Teams ($49/month flat).