Happenstance deploys as a static site to GitHub Pages with automated builds via GitHub Actions. This document covers setup, configuration, and troubleshooting for deployments.
- Go to your repository on GitHub
- Click Settings → Pages (in sidebar)
- Under "Build and deployment":
- Source: Select "GitHub Actions"
- This replaces the legacy "Deploy from branch" method
Note: The repository already includes the necessary workflow file (.github/workflows/pages.yml), so no additional configuration is needed.
Ensure the workflow has the necessary permissions:
- Go to Settings → Actions → General
- Under "Workflow permissions":
- Select "Read and write permissions"
- Check "Allow GitHub Actions to create and approve pull requests"
- Click Save
To fetch real data instead of fixtures:
- Go to Settings → Secrets and variables → Actions
- Click "New repository secret"
- Add secrets (one at a time):
For Google Places + Ticketmaster:
Name: GOOGLE_PLACES_API_KEY
Secret: your_google_api_key_here
Name: TICKETMASTER_API_KEY
Secret: your_ticketmaster_api_key_here
For AI-powered data (alternative):
Name: GROK_API_KEY
Secret: your_grok_api_key_here
Name: OPENAI_API_KEY
Secret: your_openai_api_key_here
For pre-generated AI data (alternative):
Name: AI_RESTAURANTS_DATA
Secret: [{"name": "Restaurant", "cuisine": "Italian", ...}]
Name: AI_EVENTS_DATA
Secret: [{"title": "Event", "category": "music", ...}]
See API_SETUP.md for detailed instructions on obtaining API keys.
Edit config/config_logic.json to specify your data sources and region:
{
"profiles": {
"default": {
"region": "Your City, State",
"branding": {
"title": "Happenstance - Your City",
"tagline": "Plan your weekend with great food and events",
"accent_color": "#3b82f6"
},
"data_sources": {
"restaurants": "fixtures",
"events": "fixtures"
}
}
}
}Data source options:
"fixtures"- Demo data (no API keys needed)"google_places"- Google Places API (requires API key)"ticketmaster"- Ticketmaster API (requires API key)"eventbrite"- Eventbrite API (requires API key)"ai"- AI-powered search (requires Grok or OpenAI key)
Option A: Push to main branch
# Stage only the config file you changed
git add config/config_logic.json
git commit -m "Configure for my city"
git push origin mainOption B: Manual workflow dispatch
- Go to Actions tab
- Click "Pages Deploy" workflow
- Click "Run workflow" → "Run workflow"
- Wait 2-3 minutes for workflow to complete
- Go to Settings → Pages
- You'll see: "Your site is live at https://username.github.io/repository-name/"
- Click the URL to view your site
The site automatically deploys when:
- Push to
mainbranch - Any commit triggers deployment - Daily schedule - Runs at 6 AM UTC (cron:
0 6 * * *) - Manual trigger - Via GitHub Actions UI ("Run workflow" button)
Workflow file: .github/workflows/pages.yml
┌─────────────────────────────────────┐
│ Trigger (push/schedule/manual) │
└─────────────────┬───────────────────┘
▼
┌─────────────────────────────────────┐
│ Checkout repository │
└─────────────────┬───────────────────┘
▼
┌─────────────────────────────────────┐
│ Setup Python 3.11 │
└─────────────────┬───────────────────┘
▼
┌─────────────────────────────────────┐
│ Install dependencies │
│ (pip install -r requirements.txt) │
└─────────────────┬───────────────────┘
▼
┌─────────────────────────────────────┐
│ Run data aggregation │
│ (python -m happenstance.cli │
│ aggregate) │
│ │
│ Environment variables: │
│ - API keys from repository secrets │
│ - PROFILE=default │
└─────────────────┬───────────────────┘
▼
┌─────────────────────────────────────┐
│ Upload docs/ as Pages artifact │
│ (actions/upload-pages-artifact) │
└─────────────────┬───────────────────┘
▼
┌─────────────────────────────────────┐
│ Deploy to GitHub Pages │
│ (actions/deploy-pages) │
└─────────────────┬───────────────────┘
▼
┌─────────────────────────────────────┐
│ Site live at GitHub Pages URL │
└─────────────────────────────────────┘
Deployment time: Typically 2-3 minutes
- A registered domain name
- Access to DNS settings
Create docs/CNAME with your domain:
echo "happenstance.yourdomain.com" > docs/CNAME
git add docs/CNAME
git commit -m "Add custom domain"
git pushNote: The repository already has a CNAME file. Edit it with your domain.
Add a CNAME record in your DNS provider:
For subdomain (e.g., happenstance.yourdomain.com):
Type: CNAME
Name: happenstance
Value: username.github.io
For apex domain (e.g., yourdomain.com):
Type: A
Name: @
Value: 185.199.108.153
Type: A
Name: @
Value: 185.199.109.153
Type: A
Name: @
Value: 185.199.110.153
Type: A
Name: @
Value: 185.199.111.153
DNS providers:
- Cloudflare: DNS → Add record
- Namecheap: Advanced DNS → Add record
- Google Domains: DNS → Custom records
- Go to Settings → Pages
- Under "Custom domain":
- Enter your domain:
happenstance.yourdomain.com - Click Save
- Enter your domain:
- Wait for DNS check (may take up to 24 hours)
- Once verified, check "Enforce HTTPS"
Note: GitHub automatically provisions SSL certificate via Let's Encrypt.
# Check DNS propagation
dig happenstance.yourdomain.com
# Should show:
# happenstance.yourdomain.com. 3600 IN CNAME username.github.io.Visit your custom domain - it should redirect to HTTPS automatically.
Advantages:
- Professional branding
- Memorable URL
- Full control over domain
Considerations:
- DNS propagation takes 1-24 hours
- SSL certificate provisioning takes a few minutes
- Domain registration costs ~$10-20/year
- Requires DNS management knowledge
Free alternatives:
- Use default GitHub Pages URL:
username.github.io/repository-name - Perfectly functional, just longer URL
View deployment status:
- Go to Actions tab
- Click on a workflow run
- Expand steps to see logs
Successful deployment:
✓ Checkout repository
✓ Setup Python
✓ Install dependencies
✓ Generate data using real APIs
✓ Upload artifact
✓ Deploy to GitHub Pages
Failed deployment: Red X on any step - click to see error logs.
After deployment, a separate validation workflow runs:
Workflow: .github/workflows/validate-pages.yml
What it checks:
- All JSON endpoints return HTTP 200
- JSON files parse correctly
- Required fields present in data
- Metadata sentinel present
- UI readiness signal (
data-hs-ready="1")
To view results:
- Go to Actions tab
- Click "Validate Published JSON" workflow
- View latest run
Deployment logs:
- Available in GitHub Actions for 90 days
- Click on workflow run → View logs
- Shows aggregation output, API calls, errors
Build artifacts:
- Uploaded as GitHub Pages artifact
- Automatically deployed
- Not directly downloadable (use
git checkoutof docs/)
Example log output:
Using fixture data for restaurants in Capital Region, NY
Using fixture data for events in Capital Region, NY
Generated 4 restaurants, 4 events, 4 pairings
Writing restaurants.json (4 items)
Writing events.json (4 items)
Writing meta.json
Writing config.json
- Go to Actions tab
- Look for workflow runs with the clock icon (scheduled)
- Check status:
- ✓ Green = successful
- ✗ Red = failed
- ○ Yellow = in progress
- Go to Settings → Pages
- View deployment history
- Check timestamps - should show daily updates
Visit your site and check the footer:
Data from Capital Region, NY • Updated: 2025-12-29 at 06:05 UTC
The timestamp shows when data was last generated.
# Fetch meta.json and check generated_at
curl -s https://username.github.io/repository-name/meta.json | \
python -c "import sys, json; print(json.load(sys.stdin)['generated_at'])"
# Output: 2025-12-29T06:05:23+00:00Run didn't trigger:
- GitHub may skip scheduled runs on inactive repos
- Check Actions tab for disabled workflows
- Manual trigger once to reactivate
Run failed:
- Check workflow logs for errors
- Often API rate limits or quota exceeded
- Fixture fallback should still work
Data didn't update:
- Check
_meta.changedfield in JSON - If
false, data hasn't changed since last run - This is normal - prevents unnecessary updates
Site not updating:
- Clear browser cache (Ctrl+Shift+R)
- Check deployment actually completed
- Verify cache headers allow updates
Symptoms:
Error: python -m happenstance.cli aggregate
ModuleNotFoundError: No module named 'requests'
Solution:
# Check requirements.txt is present and committed
git add requirements.txt
git commit -m "Add requirements.txt"
git pushSymptoms:
Warning: GOOGLE_PLACES_API_KEY environment variable not set
Using fixture data for restaurants
Solution:
- This is not an error - fixture fallback is working
- To use real data, add API keys as repository secrets (see Step 3 above)
Symptoms:
Error: Resource not accessible by integration
Solution:
- Go to Settings → Actions → General
- Under "Workflow permissions", select "Read and write permissions"
- Save and re-run workflow
Symptoms:
Error: Path does not exist: docs
Solution:
# Ensure docs/ directory exists
mkdir -p docs
git add docs/.gitkeep
git commit -m "Add docs directory"
git pushSymptoms: Warning in GitHub Pages settings.
Solution:
- Verify DNS records using
dig yourdomain.com - Wait up to 24 hours for propagation
- Ensure CNAME record points to
yourusername.github.io(notyourusername.github.io/repo)
Symptoms: Browser shows "Not Secure" warning.
Solution:
- Wait a few minutes for certificate provisioning
- Uncheck "Enforce HTTPS", save, then re-check
- Clear browser cache and retry
Symptoms: Events tab empty or shows "No events found"
Solution:
# Check EVENT_WINDOW_DAYS - may be too small
# Add to .github/workflows/pages.yml under env:
EVENT_WINDOW_DAYS: 30
# Or update in configSymptoms: Paired tab shows "No pairings available"
Solution:
- Check both restaurants and events have data
- Review geocoding errors in workflow logs
- Ensure cities in data match region configuration
Symptoms: Old events still showing after scheduled run
Solution:
# Force manual workflow run
# Go to Actions → Pages Deploy → Run workflow
# Check _meta.changed in JSON
curl https://username.github.io/repo/events.json | \
python -m json.tool | grep changedEdit .github/workflows/pages.yml:
on:
push:
branches: ["main"]
workflow_dispatch:
schedule:
- cron: "0 6 * * *" # Change this lineCommon schedules:
0 */6 * * *- Every 6 hours0 6,18 * * *- 6 AM and 6 PM daily0 6 * * 1,4- Mondays and Thursdays at 6 AM0 6 1 * *- First day of each month
Option 1: Branch-based
Create separate workflows for staging:
# .github/workflows/staging.yml
on:
push:
branches: ["develop"]Deploy staging to a different Pages site or subdomain.
Option 2: Environment-based
Use GitHub Environments:
- Settings → Environments → New environment
- Create "production" and "staging"
- Add different secrets to each
- Reference in workflow:
environment: name: production
Add notification step to workflow:
- name: Notify deployment
if: success()
run: |
curl -X POST https://your-webhook-url \
-H 'Content-Type: application/json' \
-d '{"text": "Deployment successful"}'Services:
- Slack webhook
- Discord webhook
- Email via SendGrid
- Custom API endpoint
GitHub Pages automatically uses CDN with these cache headers:
Cache-Control: max-age=600 # 10 minutes
To verify:
curl -I https://username.github.io/repo/restaurants.jsonGitHub Pages automatically enables gzip compression for:
.html.css.js.json
No configuration needed.
Current build time: ~2-3 minutes
Optimization strategies:
- Limit API result counts (fewer restaurants/events = faster)
- Reduce geocoding calls (pre-cache coordinates)
- Skip pairing for very distant events
- Use fixture data for faster builds during development
GitHub doesn't support automatic rollback, but you can:
# Find commit hash of working version
git log --oneline
# Revert to that commit
git revert <commit-hash>
git push origin main- Download artifact from previous workflow run (if available)
- Extract to
docs/ - Commit and push
Keep backups of docs/ directory:
# Before making changes
cp -r docs/ docs-backup-$(date +%Y%m%d)If site is completely broken:
- Check workflow logs for errors
- Verify
docs/index.htmlexists and is valid - Test locally:
python -m happenstance.cli serve - If necessary, restore from git history:
git checkout <last-known-good-commit> -- docs/ git commit -m "Restore working docs" git push
✓ Do:
- Store API keys as repository secrets
- Use separate keys for staging/production
- Rotate keys periodically
- Monitor API usage dashboards
✗ Don't:
- Commit API keys to git
- Share keys in issues or PRs
- Use production keys in forks
- Hardcode keys in workflow files
For public repositories:
- API keys are safe in secrets (not exposed in logs)
- Forkers cannot access your secrets
- Generated data is public (by design)
For private repositories:
- Same security model applies
- Pages site can be private (requires GitHub Pro)
The deployed site is static with no backend:
- No server-side code execution
- No database or user data
- No cookies (except GitHub Pages analytics, optional)
- HTML escaping in frontend prevents XSS
Basic analytics available:
- Insights → Traffic (for public repos)
- Shows page views and unique visitors
- Limited to 14-day history
Add analytics to docs/index.html:
Google Analytics:
<script async src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-XXXXXXXXXX');
</script>Privacy-focused alternatives:
- Plausible Analytics
- Fathom Analytics
- Simple Analytics
Use external monitoring:
- UptimeRobot (free tier available)
- Pingdom
- StatusCake
Monitor endpoints:
- Main page:
https://username.github.io/repo/ - JSON health check:
https://username.github.io/repo/meta.json