A browser-based IPFS node built with Helia that runs entirely on GitHub Pages. On load it automatically adds every file in the repository to IPFS and exposes a root CID, plus a browsable file tree, content fetch, and download support.
Live demo: https://randymcmillan.github.io/ipfs-gh-pages/
- In-browser Helia IPFS node (no backend required)
- Automatically adds all repository files to IPFS on startup
- Root directory CID displayed after import
- Repository file/folder tree view with per-file CIDs
- Click any CID to fetch its content (text, binary, or directory listing)
- Download button saves the actual retrieved bytes (files download as themselves, directories as a
.zip) - Publish arbitrary text and fetch by CID
npm install
npm run devOpen http://localhost:5173.
npm run build
npm run previewThe production bundle is written to ./dist.
Integration tests use headless Chrome/Chromium via the Chrome DevTools Protocol.
# start the dev server in another terminal
npm run dev
# run tests
npm run test # all tests (unit + headless Chrome integration)
npm run test:unit # pure functions only, no browser needed
npm run test:eval # inspect fetched bytes
npm run test:zip # zip a directory
npm run test:download # download flow
npm run test:share # share link: two headless browsers, auto-connect via ?connect=
node tests/cdp-ui.mjs # UI chrome regression tests (dropdown, tabs, blob view, theme)
node tests/car.test.mjs # CAR round-trip: export/import with locked deps only
npm run test:gateway # public gateway reachability for the repo root (needs a provider)
## Submodules & releases
`actions-test` is a small submodule kept as the fixture for the
per-submodule CAR build (`build-car` writes `<submodule>/<name>.car`).
Its `.car` artifacts are ignored (`ignore = untracked` in `.gitmodules`)
so the superproject stays clean.
Release procedure with submodules:
1. To update the fixture's content: commit and push inside the
submodule, then bump the gitlink here (the normal two-step).
2. `npm run build` rebuilds every submodule CAR from the checked-out
commit — the CAR's root CID changes only when the submodule's
tracked files change.
3. CI checkouts that don't initialize submodules skip the submodule
CARs gracefully; the main `dist/ipfs-gh-pages.car` is unaffected.
Releases are cut with `npm run release <version>` — it bumps,
commits, tags, and pushes this repo AND tags the actions-test
submodule at the gitlink's commit, keeping its tags in lockstep.
node tests/cdp-ui.mjs # UI chrome regression tests (dropdown, tabs, blob view, theme)Set CHROME_PATH to point at your browser binary if it is not auto-detected.
This repository is also a reusable GitHub Action. Other repositories can build (and deploy) a browser IPFS node that embeds all of their own files with a few lines of YAML:
name: Deploy IPFS site
on:
push:
branches: [main]
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: pages
cancel-in-progress: true
jobs:
build-and-deploy:
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.deploy.outputs.page_url }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Build and deploy IPFS site
id: deploy
uses: RandyMcMillan/ipfs-gh-pages@v2.2.1
with:
node-version: '20'
deploy: 'true'Inputs:
node-version(default20) — Node.js version used for the build.repo-root(default${{ github.workspace }}) — directory whose tracked files are embedded.out-dir(default${{ github.workspace }}/dist) — where the production bundle is written.deploy(defaulttrue) — whether to deploy to GitHub Pages.run-tests(defaultfalse) — run the integration suite (installs Chromium) before building.
Outputs:
dist-path— absolute path to the built bundle directory.
Set deploy: 'false' to only produce the bundle (e.g. to attach it to a release) and skip
the Pages deployment step.
.github/workflows/deploy.ymlruns the full test suite on every push and pull request; deployment to GitHub Pages only happens onmainafter tests pass..github/workflows/release.ymlruns tests, builds the project, archives./distasdist.zip, and attaches it to a GitHub Release (triggered byv*tags or manually).
index.html # app shell + UI
main.js # Helia node, IPFS import, tree, fetch, download
vite.config.js # Vite config + virtual repo-files module
tests/ # Chrome DevTools Protocol integration tests
.github/workflows/ # CI/CD pipelines
MIT