
I am a huge fan of dogfooding. If I build developer tooling, I want to use it in my own day-to-day workflows.
Deployments are one of the biggest ways I use ActivitySmith: push to main, GitHub Actions runs in the background, and I get step-by-step progress updates on my iPhone lock screen using iOS Live Activities.
My deployments are automated with GitHub Actions and are fairly simple, but they still have multiple steps and usually take at least a minute. In larger projects and teams, deployment runs often take much longer.
Before ActivitySmith, that meant opening GitHub, finding the repo, going to Actions, opening the current run, and watching it progress until it finished so I knew when I could try it out.
That workflow was annoying. With ActivitySmith, the progress streams directly to my iPhone lock screen in real time, and I know exactly when a release is finished and ready to try.

For every production deployment, ActivitySmith:
This is not limited to one backend service. I use the same pattern across various backend services, frontend apps, landing pages, and other projects.
Here is the workflow I use in production:
name: Deploy API to Production
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v4
with:
node-version:node-version:node-version: 24
cache: npm
- name: Start live activity
id: start_activity
uses: ActivitySmithHQ/[email protected]
with:
action: start_live_activity
api-key: ${{ secrets.ACTIVITYSMITH_API_KEY }}
payload: |
content_state:
title: "API Deployment"
subtitle: "ci: install & build"
number_of_steps: 4
current_step: 1
type: "segmented_progress"
color: "yellow"
- name: Build
run: |
npm ci
npm run build
- name: Update live activity
uses: ActivitySmithHQ/[email protected]
with:
action: update_live_activity
api-key: ${{ secrets.ACTIVITYSMITH_API_KEY }}
live-activity-id: ${{ steps.start_activity.outputs.live_activity_id }}
payload: |
content_state:
title: "ActivitySmith API Deployment"
subtitle: "prepare release & upload"
current_step: 2
- name: Set release id
run: |
echo "RELEASE_ID=$(date +%Y%m%d%H%M%S)" >> $GITHUB_ENV
- name: Prepare release dir on remote server
run: |
ssh -o StrictHostKeyChecking=no [email protected] "RELEASE_ID=${RELEASE_ID} bash -s" << 'EOF'
set -euo pipefail
BASE="/srv/apps/activitysmith-api"
NEW="$BASE/releases/$RELEASE_ID"
mkdir -p "$BASE/releases"
rm -rf "$NEW"
mkdir -p "$NEW"
EOF
- name: Upload built artifacts to remote server
run: |
# rsync release artifacts to the new server release directory
- name: Update live activity
uses: ActivitySmithHQ/[email protected]
with:
action: update_live_activity
api-key: ${{ secrets.ACTIVITYSMITH_API_KEY }}
live-activity-id: ${{ steps.start_activity.outputs.live_activity_id }}
payload: |
content_state:
title: "ActivitySmith API Deployment"
subtitle: "prod install & reload"
current_step: 3
- name: Install prod deps, switch release, and reload
run: |
# Remote deployment script:
# - Install production dependencies in the new release directory
# - Atomically switch current symlink to the new release
# - Gracefully reload PM2 cluster behind nginx
# - Prune old releases while keeping rollback-safe history
- name: End live activity
uses: ActivitySmithHQ/[email protected]
with:
action: end_live_activity
api-key: ${{ secrets.ACTIVITYSMITH_API_KEY }}
live-activity-id: ${{ steps.start_activity.outputs.live_activity_id }}
payload: |
content_state:
title: "ActivitySmith API Deployment"
subtitle: "done"
current_step: 4
You can also use ActivitySmith to send push notifications to your iOS devices.
- name: Send deployment complete push notification
uses: ActivitySmithHQ/[email protected]
with:
action: send_push_notification
api-key: ${{ secrets.ACTIVITYSMITH_API_KEY }}
payload: |
title: "Build Failed 🚨"
message: "CI pipeline failed on main branch"ActivitySmith is API infrastructure. Users expect near-constant availability.
Before I implemented zero-downtime deployments, the Live Activity lifecycle would break during release restarts because the API went down mid-deploy, so updates could not be delivered.
Deployments now run behind nginx with PM2 in cluster mode using zero-downtime reloads (worker A, then worker B), so traffic stays up and Live Activity updates continue reliably.
This pattern now powers every deployment workflow I care about, not just ActivitySmith core services. Once wired in, every release gives real-time confidence without babysitting logs.
And outside GitHub Actions, the same approach works from scripts, cron jobs, workers, agents and more. Basically any backend. Zapier and n8n integrations are complete and currently pending marketplace approval.