Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
147 changes: 83 additions & 64 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1,64 +1,83 @@
name: Package Release

on:
push:
branches:
- latest-release
- beta

permissions:
contents: write
issues: write
pull-requests: write

jobs:
release-builder:
runs-on: ubuntu-latest
defaults:
run:
working-directory: packages/builder
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # Important for semantic release to work correctly

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "22"
registry-url: "https://registry.npmjs.org"

- name: Setup pnpm
uses: pnpm/action-setup@v2
with:
version: "10.8.1"
run_install: false

- name: Get pnpm store directory
id: pnpm-cache
shell: bash
run: |
echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT

- uses: actions/cache@v3
name: Setup pnpm cache
with:
path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-store-

- name: Install dependencies
run: pnpm install --frozen-lockfile

- name: Build package
run: pnpm build

- name: Release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
run: pnpm semantic-release

# Add more jobs for additional packages as repo grows
name: Package Release

on:
push:
branches:
- latest-release
- beta

workflow_dispatch:

permissions:
contents: write
issues: write
pull-requests: write
id-token: write # Required for npm OIDC trusted publishing

concurrency:
group: release-${{ github.ref }}
cancel-in-progress: true

jobs:
release-builder:
runs-on: ubuntu-latest
defaults:
run:
working-directory: packages/builder
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # Important for semantic release to work correctly

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "22"
registry-url: "https://registry.npmjs.org"

- name: Setup pnpm
uses: pnpm/action-setup@v2
with:
version: "10.8.1"
run_install: false

- name: Get pnpm store directory
id: pnpm-cache
shell: bash
run: |
echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT

- uses: actions/cache@v4
name: Setup pnpm cache
with:
path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-store-

- name: Install dependencies
run: pnpm install --frozen-lockfile
working-directory: .

- name: Build package
run: pnpm build
working-directory: .

- name: Semantic Release
id: semantic
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: pnpm semantic-release

- name: Publish to npm with OIDC
if: steps.semantic.outcome == 'success'
run: |
# Check if package.json version was updated (not 0.0.0-development)
VERSION=$(node -p "require('./package.json').version")
if [ "$VERSION" != "0.0.0-development" ]; then
echo "Publishing version $VERSION to npm with OIDC provenance..."
npm publish --provenance --access public
else
echo "No new version to publish"
fi

1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
node_modules
dist
coverage
sites

*.tsbuildinfo
3 changes: 3 additions & 0 deletions .vscode/pushforge.code-workspace
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
{
"path": "../packages/builder",
},
{
"path": "../sites/test",
},
{
"path": "..",
},
Expand Down
180 changes: 93 additions & 87 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,133 +1,139 @@
# PushForge 🚀

<div align="center">

<img src="images/pushforge_logo.png" alt="PushForge Logo" width="150" />
<img src="images/logo.webp" alt="PushForge Logo" width="120" />

# PushForge

**Modern, Cross-Platform Web Push Notifications**
**Web Push Notifications for the Modern Stack**

[![npm version](https://img.shields.io/npm/v/@pushforge/builder.svg)](https://www.npmjs.com/package/@pushforge/builder)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
[![Node Version](https://img.shields.io/badge/node-%3E%3D16.0.0-brightgreen)](https://nodejs.org/)
[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](CONTRIBUTING.md)
[![TypeScript](https://img.shields.io/badge/TypeScript-first--class-blue.svg)](https://www.typescriptlang.org/)

</div>
Zero dependencies · Works everywhere · TypeScript-first

## What is PushForge?
[Documentation](packages/builder) · [npm](https://www.npmjs.com/package/@pushforge/builder) · [Report Bug](https://github.com/draphy/pushforge/issues)

PushForge is a comprehensive toolkit for implementing Web Push Notifications in modern web applications. It handles the complex parts of push notifications so you can focus on building great user experiences.
**[Try the Live Demo →](https://pushforge.draphy.org)**

**Zero dependencies. Cross-platform. TypeScript-first.**
</div>

### Features
---

- 🔐 Compliant VAPID authentication
- 📦 Streamlined payload encryption
- 🌐 Works everywhere: Node.js, Browsers, Deno, Bun, Cloudflare Workers
- 🧩 Modular architecture for flexible implementation
- 🛠️ Built with TypeScript for robust type safety
## Live Demo

## Packages
See PushForge in action at **[pushforge.draphy.org](https://pushforge.draphy.org)** — a fully working test site powered by PushForge on Cloudflare Workers.

| Package | Description | Path |
| -------------------------------------- | --------------------------------------------------------------------------------- | --------------------------------------- |
| [@pushforge/builder](packages/builder) | Core library for building push notification requests with proper VAPID encryption | [`packages/builder/`](packages/builder) |
- **Enable push notifications** on your device with a single toggle
- **Send a test notification** to all active devices — anyone visiting the page can send and receive
- **See it working across browsers** — Chrome, Firefox, Edge, Safari 16+, and more
- Subscriptions auto-expire after 5 minutes — no permanent data stored

_More packages coming soon!_
The entire backend is a single Cloudflare Worker using `buildPushHTTPRequest()` from `@pushforge/builder` with zero additional dependencies.

## Quick Start
## The Problem

```bash
# Install the core package
npm install @pushforge/builder
Traditional web push libraries like `web-push` rely on Node.js-specific APIs that don't work in modern edge runtimes:

# Generate VAPID keys for push authentication
npx @pushforge/builder generate-vapid-keys
```
❌ Cloudflare Workers - "crypto.createECDH is not a function"
❌ Vercel Edge - "https.request is not available"
❌ Convex - "Top-level await is not supported"
```

Check out the complete documentation in each package's README for detailed usage examples.
## The Solution

## Project Structure
PushForge uses standard Web APIs that work everywhere:

```
pushforge/
├── packages/
│ └── builder/ # Core push notification builder
│ ├── lib/ # Source code
│ ├── examples/ # Usage examples (coming soon...)
│ └── README.md # Package documentation
└── README.md # This file
```
```typescript
import { buildPushHTTPRequest } from "@pushforge/builder";

## Requirements
const { endpoint, headers, body } = await buildPushHTTPRequest({
privateJWK: VAPID_PRIVATE_KEY,
subscription: userSubscription,
message: {
payload: { title: "Hello!", body: "This works everywhere." },
adminContact: "mailto:admin@example.com"
}
});

- **Node.js**: v16.0.0 or higher (for WebCrypto API support)
- **NPM**, **Yarn**, or **pnpm** for package management
await fetch(endpoint, { method: "POST", headers, body });
```

## Development Setup
## Why PushForge?

1. Clone the repository:
| | PushForge | web-push |
|---|:---:|:---:|
| Dependencies | **0** | 5+ |
| Cloudflare Workers | ✅ | [❌](https://github.com/web-push-libs/web-push/issues/718) |
| Vercel Edge | ✅ | ❌ |
| Convex | ✅ | ❌ |
| Deno / Bun | ✅ | Limited |
| TypeScript | Native | @types |

```bash
git clone https://github.com/draphy/pushforge.git
cd pushforge
```
## Quick Start

2. Install dependencies:
```bash
# Install
npm install @pushforge/builder

```bash
pnpm install
```
# Generate VAPID keys
npx @pushforge/builder vapid
```

3. Build packages:
**Frontend** - Subscribe users:

```bash
pnpm build
```
```javascript
const subscription = await registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: VAPID_PUBLIC_KEY
});
// Send subscription.toJSON() to your server
```

4. Available Commands:
**Backend** - Send notifications:

```bash
# Format and lint code
pnpm biome:format # Format code with Biome
pnpm biome:lint # Lint code with Biome
pnpm biome:check # Check code with Biome
pnpm biome:fix # Fix issues automatically with Biome
```typescript
import { buildPushHTTPRequest } from "@pushforge/builder";

# Type checking
pnpm type:check # Run TypeScript type checking
const { endpoint, headers, body } = await buildPushHTTPRequest({
privateJWK: process.env.VAPID_PRIVATE_KEY,
subscription,
message: {
payload: { title: "New Message", body: "You have a notification!" },
adminContact: "mailto:admin@example.com"
}
});

# Commit checks (run before committing)
pnpm commit:check # Run formatting, type checking and build
```
await fetch(endpoint, { method: "POST", headers, body });
```

## Contributing
See the [full documentation](packages/builder) for platform-specific examples (Cloudflare Workers, Vercel Edge, Convex, Deno, Bun).

Contributions are always welcome! We follow a structured workflow for contributions - see our [Contributing Guidelines](CONTRIBUTING.md) for details.
## Packages

Whether you want to:
| Package | Description |
|---------|-------------|
| [@pushforge/builder](packages/builder) | Core library for building push notification requests |

- 🐛 Report a bug
- 💡 Suggest new features
- 🧪 Improve tests
- 📚 Enhance documentation
- 💻 Submit a PR
## Requirements

We appreciate your help making PushForge better for everyone.
- **Node.js 20+** or any runtime with Web Crypto API
- Supported: Cloudflare Workers, Vercel Edge, Convex, Deno, Bun, modern browsers

## Reporting Issues
## Development

Found a bug or have a feature request? Please [open an issue](https://github.com/draphy/pushforge/issues/new) and provide as much detail as possible.
```bash
git clone https://github.com/draphy/pushforge.git
cd pushforge
pnpm install
pnpm build
```

## Sponsorship
## Contributing

If you find PushForge valuable, consider [sponsoring the project](https://github.com/sponsors/draphy). Your sponsorship helps maintain and improve the library.
Contributions welcome! See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.

## License

This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.

---

<div align="center">
<sub>Built with ❤️ by <a href="https://github.com/draphy">David Raphi</a></sub>
</div>
MIT © [David Raphi](https://github.com/draphy)
Loading