profileShare
profileShare creates time-limited, read-only snapshots of selected GitHub repositories. Anyone with a valid link can search the snapshot, switch frozen branches and tags, browse repositories and files, preview Markdown and raster images, open line-linked source, review file history, inspect commit diffs, read issues and pull request reviews, and inspect releases without a GitHub account.
Requirements
- Node.js 24 or later
- A GitHub account that can create a GitHub App
Check your Node.js version:
node --version
Local setup
Install dependencies:
npm installCreate a GitHub App at GitHub Settings > Developer settings > GitHub Apps > New GitHub App. Use these settings:
Setting Local value GitHub App name Any unique name Homepage URL http://localhost:3000Callback URL http://localhost:3000/auth/github/callbackSetup URL http://localhost:3000/github/installedWebhook Clear Active Repository permissions: Contents Read-only Repository permissions: Issues Read-only Repository permissions: Metadata Read-only Repository permissions: Pull requests Read-only Where can this GitHub App be installed? Only on this account No webhook secret, private key, or user permission is needed. Keep Request user authorization (OAuth) during installation cleared because profileShare authorizes the owner before starting installation.
Open the new GitHub App's settings page and create a client secret. Copy the Client ID, generated client secret, and app slug. The slug is the final part of the app's public URL, such as
my-profile-shareinhttps://github.com/apps/my-profile-share.Copy the example environment file:
PowerShell:
Copy-Item .env.example .envmacOS or Linux:
cp .env.example .envFill in
.env. Generate a stable session secret with:node -e "console.log(require('node:crypto').randomBytes(32).toString('hex'))"Keep this secret unchanged while using the same database. It is used to encrypt stored GitHub access tokens. Changing it makes existing owner records unreadable.
Start the app:
npm startOpen
http://localhost:3000, connect GitHub, and choose Only select repositories during GitHub App installation. Back in profileShare, select repositories, choose an expiry from 1 to 365 days, and create the link.
For automatic restart while editing:
npm run dev
Configuration
| Variable | Required | Default | Purpose |
|---|---|---|---|
NODE_ENV |
No | None | Set to production for deployment safety checks |
GITHUB_CLIENT_ID |
Yes | None | GitHub App client ID |
GITHUB_CLIENT_SECRET |
Yes | None | GitHub App client secret |
GITHUB_APP_SLUG |
Yes | None | GitHub App URL slug |
SESSION_SECRET |
Yes | Development fallback | Token-encryption secret |
BASE_URL |
No | http://localhost:3000 |
Public origin used for OAuth callbacks and generated share links |
PORT |
No | 3000 |
HTTP port |
DATABASE_PATH |
No | data/profileshare.db |
SQLite database path |
For a deployed instance, set NODE_ENV=production, set BASE_URL to its HTTPS origin, and update the GitHub App callback and setup URLs to the same origin. Generated links use BASE_URL, so it must be reachable by viewers.
Snapshots are stored in the SQLite database. The owner workspace lists created links and lets the signed-in owner copy, open, or revoke active links. Revoking a link removes its stored repository content. When an expired link is opened, its stored snapshot content is removed and the expired message is shown.
Verify
Run the complete test suite:
npm test
Run an individual spec check:
npm test -- auth
npm test -- snapshot
npm test -- e2e
Manual acceptance check:
- Create a link with a known set of repositories.
- Open it in a private browser window and confirm no viewer login is requested.
- Confirm only the selected repositories appear.
- Search for a file or code phrase across the snapshot.
- Switch between a repository's branches and tags, and confirm each ref shows its frozen files and commits.
- Open the Issues and Pull requests tabs, then inspect a conversation and a changed-file diff.
- Open Releases, inspect the release notes and asset metadata, and browse its tag.
- Confirm the repository overview shows topics, license, languages, stars, forks, branches, and tags.
- Browse a nested folder, preview a Markdown file and a raster image, switch Markdown to source, follow a line link, and open file history.
- Open a commit diff and confirm the full commit list appears for each selected repository.
- Filter the profile's repository tab by name and language.
- Change a source repository and confirm the existing link remains unchanged.
- Return to the owner workspace, revoke the link, and confirm the public URL no longer exposes repository content.
Troubleshooting
- GitHub is not configured: Confirm all three
GITHUB_*values are present in.env, then restart the server. - Callback error or sign-in verification error: Make sure
BASE_URLand the GitHub App callback URL use the same origin, port, and protocol. Start sign-in again from the home page. - No repositories appear: Open the GitHub App installation settings and grant it access to the intended repositories. The app lists only repositories selected for that installation.
- Issues or pull requests do not appear: Grant the GitHub App read-only Issues and Pull requests permissions, approve the updated installation permissions, then create a new snapshot.
- Repository snapshot fails: Confirm the GitHub App has read-only Contents and Metadata repository permissions and that the owner still has access.
- Stored token errors after changing
SESSION_SECRET: Restore the previous secret, or move the local database aside and sign in again. Do not delete a database that contains snapshots you need. - The generated link points to localhost: Set
BASE_URLto the viewer-reachable HTTPS origin before creating the link. - Port conflict: Set
PORTand use the same port inBASE_URL, the callback URL, and the setup URL.