Newsletter System Setup Guide
Newsletter System Setup Guide
Overview
This guide will help you set up the private newsletter system for the status.health blog using GitHub private repository + encryption + SendGrid + Vercel.
Prerequisites
- GitHub account with ability to create private repositories
- SendGrid account (free tier is fine for starting)
- Vercel account (free tier works)
- Access to status.health blog repository
Step 1: Create Private GitHub Repository
- Go to GitHub and create a new private repository named
newsletter-subscribers
- Initialize it with a README
- This will store encrypted subscriber emails
Step 2: Set Up SendGrid
- Sign up for SendGrid
- Create an API key:
- Go to Settings → API Keys
- Click “Create API Key”
- Name it “status.health blog newsletter”
- Give it “Full Access” permissions
- Copy the API key (you’ll only see it once!)
- Set up sender authentication:
- Go to Settings → Sender Authentication
- Add domain: status.health
- Follow DNS verification steps
Step 3: Generate Encryption Key
Run this command to generate a secure encryption key:
openssl rand -base64 32
Save this key securely - you’ll need it for the environment variables.
Step 4: Set Up GitHub Secrets
In your blog repository, go to Settings → Secrets and variables → Actions, and add:
NEWSLETTER_GITHUB_TOKEN
: Personal access token with repo permissionsSENDGRID_API_KEY
: Your SendGrid API keyENCRYPTION_KEY
: The key you generated in Step 3PRIVATE_REPO_NAME
:newsletter-subscribers
Step 5: Deploy to Vercel
- Install Vercel CLI:
npm i -g vercel
- In the blog directory, run:
vercel
-
Follow the prompts to link to your Vercel account
- Set environment variables in Vercel:
vercel env add GITHUB_TOKEN vercel env add SENDGRID_API_KEY vercel env add ENCRYPTION_KEY vercel env add PRIVATE_REPO_NAME
Step 6: Configure DNS (if using custom domain)
In Vercel dashboard:
- Go to your project settings
- Add domain: blog.status.health
- Follow DNS configuration instructions
Step 7: Test the System
- Test subscription:
- Go to your blog
- Enter an email in the newsletter form
- Check for:
- Welcome email received
- Email encrypted in private repo
- Success animation on frontend
- Test unsubscribe:
- Click unsubscribe link in welcome email
- Verify subscriber marked as unsubscribed
- Test new post notification:
- Create a test post in
_posts/
- Push to main branch
- Check GitHub Actions log
- Verify notification emails sent
- Create a test post in
Monitoring & Maintenance
Check subscriber count:
// Quick script to check subscribers
const { Octokit } = require('@octokit/rest');
const octokit = new Octokit({ auth: 'YOUR_GITHUB_TOKEN' });
async function getSubscriberCount() {
const { data } = await octokit.repos.getContent({
owner: 'statusdothealth',
repo: 'newsletter-subscribers',
path: 'subscribers.json'
});
const content = Buffer.from(data.content, 'base64').toString();
const subscribers = JSON.parse(content);
const active = Object.values(subscribers).filter(s => s.status === 'active').length;
console.log(`Active subscribers: ${active}`);
}
SendGrid Dashboard:
- Monitor email delivery rates
- Check for bounces/complaints
- Review monthly usage
Privacy Compliance:
- Regularly audit subscriber data
- Ensure unsubscribe links work
- Keep privacy policy updated
- Delete old unsubscribed data after 30 days
Troubleshooting
Emails not sending:
- Check SendGrid API key is valid
- Verify sender authentication
- Check GitHub Action logs
- Ensure environment variables are set
Subscription not working:
- Check browser console for errors
- Verify Vercel deployment is live
- Check API endpoint logs in Vercel
- Ensure CORS headers are correct
Unsubscribe links broken:
- Verify encryption key matches
- Check token generation logic
- Ensure subscriber ID exists
Security Best Practices
- Rotate encryption key every 6 months
- Audit access to private repo regularly
- Monitor for suspicious subscription patterns
- Keep dependencies updated
- Review logs for unauthorized access attempts
Support
For issues or questions:
- Check Vercel logs
- Review GitHub Actions output
- Contact: blog@status.health