# {B/qKC} - CollectionBuilder-CSV

**A decentralized archive of Black queer Kansas City history**

{B/qKC} is a community archive operating on the principles of accessible storytelling, repair of our historical record, and intergenerational power building—all within the frame and study of midwestern Black queer history. Founded by Nasir Anthony Montalvo in 2024, this project challenges institutional archival practices and creates permanent, accessible records of Black queer midwestern histories.

Visit the live archive at **[https://bqkc.1800nasi.net](https://bqkc.1800nasi.net)**

Learn more on our [About page](https://bqkc.1800nasi.net/about/) or view [public programs](https://1800nasi.net/category/bqkc/).

---

## Technical Overview

This site is built with [CollectionBuilder-CSV](https://collectionbuilder.github.io/), a robust and flexible template for creating digital collection and exhibit websites using Jekyll and metadata CSV files. The resulting static site is self-hosted on a YunoHost server with automated deployment.

**Our Stack:**
- 🌐 **Static Site Generator:** Jekyll (CollectionBuilder-CSV template)
- 🗂️ **Content Management:** Git + Gitea (self-hosted)
- 🏠 **Hosting:** YunoHost on Raspberry Pi 4
- 🔗 **Decentralized Storage:** IPFS for archival materials
- ⚡ **Deployment:** Automated via cron + bash scripts

---

## Development Workflow

### Quick Start for Editing

1. **Edit locally** in Visual Studio Code
2. **Commit changes** using VS Code's Source Control pane
3. **Push to Gitea** (`git push gitea main`)
4. **Site auto-deploys** within 1 minute! ✨

### Three Ways to Deploy

#### 1. Auto-Deploy (Primary Method) ✨

**What it does:** Automatically deploys when you push to Gitea

**How it works:**
- A cron job runs every minute checking for new commits
- When changes are detected, it pulls and rebuilds the site
- Deployment status is logged with commit details and success/fail indicators
- Takes ~10-30 seconds to build and deploy

**Usage:**
```bash
# On your local machine:
git add .
git commit -m "Update collection metadata"
git push gitea main

# Wait ~1 minute, check logs to confirm deployment
```

#### 2. Manual SSH Deploy 🔧

**What it does:** Instantly deploy without waiting for cron

**When to use:** Need immediate update, testing, or troubleshooting

**Usage:**
```bash
# SSH into server:
ssh 1800nasi@floridas-finest.noho.st

# Switch to app user:
sudo yunohost app shell my_webapp

# Run deployment:
cd /var/www/my_webapp
./deploy.sh

# Exit:
exit
```

#### 3. SFTP File Management 📁

**What it does:** Direct file access via SFTP client (FileZilla, etc.)

**When to use:** Quick fixes, emergency edits, file inspection

**Connection details:**
- Host: `bqkc.1800nasi.net`
- Username: `my_webapp`
- Port: `22`
- Path: `/var/www/my_webapp/`

**⚠️ Important:** Changes made via SFTP to tracked files will be overwritten on next git push. Always treat git as your source of truth. Only use SFTP for untracked files or emergency situations.

---

## How Auto-Deployment Works

### The Technical Details

**Bash Scripts:**
- `auto-pull.sh` - Checks for new commits from Gitea every minute
- `deploy.sh` - Builds the Jekyll site and syncs to live directory

**Cron Job:**
- Runs `auto-pull.sh` every minute
- Extremely lightweight (uses virtually no resources)
- Logs all activity to `/var/www/my_webapp/deploy.log`

**The Flow:**
1. You push code to Gitea from your Mac
2. Cron runs `auto-pull.sh` every minute
3. Script checks: "Is local code different from Gitea?"
4. If yes: pulls new code and runs `deploy.sh`
5. `deploy.sh` runs `/usr/local/bin/bundle exec rake deploy` (builds site)
6. Built site is synced to `/var/www/my_webapp/www/` (live directory)
7. Deployment status logged with ✅ or ❌ indicator
8. Site is live!

**Why this approach?**
- No PHP required (keeps site purely static)
- No webhooks or complex CI/CD
- Self-contained using only Linux built-in tools
- Perfect for Raspberry Pi hosting
- Aligns with decentralized, minimal-dependency philosophy

---

## Monitoring & Logs

### Check Deployment Logs

**View recent deployments:**
```bash
sudo tail -50 /var/www/my_webapp/deploy.log
```

**See all auto-deploy triggers:**
```bash
sudo grep "New changes detected" /var/www/my_webapp/deploy.log
```

**Watch deployment in real-time:**
```bash
sudo tail -f /var/www/my_webapp/deploy.log
```

**Check if cron is running:**
```bash
sudo systemctl status cron
```

**View cron execution history:**
```bash
sudo grep "auto-pull" /var/log/syslog | tail -10
```

### Backup Logs

Deployment logs are automatically rotated and backed up:
- Current log: `/var/www/my_webapp/deploy.log`
- Backups: `/var/www/my_webapp/backups/logs/`
- Retention: Last 30 days
- Archives older than 30 days are automatically deleted

---

## Troubleshooting Guide

### Site Didn't Update After Push

**Step 1: Verify changes are on Gitea**
- Check the Gitea web interface: `https://gitea.floridas-finest.noho.st/1800nasi/bqkc`
- Confirm your commit appears in the commit history

**Step 2: Check deployment log**
```bash
sudo grep "New changes detected" /var/www/my_webapp/deploy.log | tail -5
```

**Step 3: Verify cron is running**
```bash
sudo systemctl status cron
```

**Step 4: Manually trigger deployment**
```bash
sudo yunohost app shell my_webapp
cd /var/www/my_webapp
./auto-pull.sh
```

**Step 5: Check for errors**
```bash
sudo tail -100 /var/www/my_webapp/deploy.log
```

---

### Deployment Errors

**Check error details:**
```bash
sudo tail -100 /var/www/my_webapp/deploy.log
```

**Common issues and fixes:**

**Ruby/Bundle errors:**
```bash
sudo yunohost app shell my_webapp
cd /var/www/my_webapp/repo/bqkc
bundle install
exit
```

**Git errors (uncommitted local changes):**
```bash
sudo yunohost app shell my_webapp
cd /var/www/my_webapp/repo/bqkc
git status
git reset --hard HEAD  # Discard local changes
git pull origin main
exit
```

**Permission errors:**
```bash
sudo chown -R my_webapp:my_webapp /var/www/my_webapp
sudo chmod -R 755 /var/www/my_webapp
```

---

### SFTP Access Issues

**Verify user has correct permissions:**
```bash
groups my_webapp
# Should show: my_webapp ssh.app sftp.app
```

**If ssh.app is missing:**
```bash
sudo usermod -aG ssh.app my_webapp
sudo systemctl restart ssh
```

**Check SSH service:**
```bash
sudo systemctl status ssh
```

**View SSH logs for errors:**
```bash
sudo journalctl -u ssh -n 50 | grep my_webapp
```

---

### Emergency Rollback

If a deployment breaks the site, rollback to a previous version:

**Step 1: Find the commit to rollback to**
```bash
sudo yunohost app shell my_webapp
cd /var/www/my_webapp/repo/bqkc
git log --oneline -10  # Shows last 10 commits
```

**Step 2: Rollback to specific commit**
```bash
git reset --hard COMMIT_HASH
# Example: git reset --hard a1b2c3d
```

**Step 3: Deploy the rolled-back version**
```bash
cd /var/www/my_webapp
./deploy.sh
exit
```

**Step 4: Update Gitea (force push)**
```bash
# On your local Mac:
git fetch gitea
git reset --hard COMMIT_HASH
git push gitea main --force
```

---

### Site Completely Broken

**Nuclear option - restore from backup:**

```bash
# List available backups:
ls -lh /var/www/my_webapp/backups/site/

# Restore from backup (replace DATE with actual backup date):
sudo yunohost app shell my_webapp
cd /var/www/my_webapp
tar -xzf backups/site/site-backup-YYYY-MM-DD.tar.gz -C www/
exit
```

---

## File & Directory Structure

```
/var/www/my_webapp/
├── repo/bqkc/          # Git repository (source code)
│   ├── _config.yml     # Site configuration
│   ├── _data/          # Collection metadata CSV
│   ├── pages/          # Site pages
│   └── _site/          # Built site (generated by Jekyll)
├── www/                # Live website (served to public)
├── backups/            # Automated backups
│   ├── logs/           # Deployment log archives
│   └── site/           # Daily site backups
├── deploy.sh           # Main deployment script
├── auto-pull.sh        # Auto-deployment checker
└── deploy.log          # Deployment activity log
```

---

## Maintenance Tasks

### Update Ruby Dependencies

```bash
sudo yunohost app shell my_webapp
cd /var/www/my_webapp/repo/bqkc
bundle update
git add Gemfile.lock
git commit -m "Update Ruby dependencies"
git push origin main
exit
```

### Clear Old Backups Manually

Backups are auto-cleaned, but to manually clear:

```bash
# Remove backups older than 30 days:
sudo find /var/www/my_webapp/backups/ -type f -mtime +30 -delete
```

### Check Disk Space

```bash
df -h /var/www/my_webapp
```

### View System Resource Usage

```bash
htop  # Interactive process viewer (press 'q' to quit)
```

---

## CollectionBuilder Resources

For detailed information about working with CollectionBuilder:

- [CollectionBuilder Docs](https://collectionbuilder.github.io/cb-docs/) - Complete documentation
- [Metadata Guide](https://collectionbuilder.github.io/cb-docs/docs/metadata/csv_metadata/) - How to format your collection metadata
- [Configuration Guide](https://collectionbuilder.github.io/cb-docs/docs/config/) - Customizing your site
- [Theme Customization](https://collectionbuilder.github.io/cb-docs/docs/theme/) - Design and styling
- [Discussion Forum](https://github.com/CollectionBuilder/collectionbuilder.github.io/discussions) - Ask questions

### Quick CollectionBuilder Tips

**Update collection metadata:**
1. Edit `_data/metadata.csv`
2. Commit and push changes
3. Site auto-rebuilds with new metadata

**Change site configuration:**
1. Edit `_config.yml`
2. Commit and push changes
3. Site auto-rebuilds

**Add custom pages:**
1. Create `.md` files in `pages/` directory
2. Add front matter (title, layout, etc.)
3. Commit and push

---

## About CollectionBuilder

CollectionBuilder is a project of University of Idaho Library's [Digital Initiatives](https://www.lib.uidaho.edu/digital/) and the [Center for Digital Inquiry and Learning](https://cdil.lib.uidaho.edu) (CDIL) following the [Lib-Static](https://lib-static.github.io/) methodology.

**Powered by:**
- [Jekyll](https://jekyllrb.com/) - Static site generator
- [Bootstrap](https://getbootstrap.com/) - CSS framework
- [DataTables](https://datatables.net/) - Interactive tables
- [Leaflet.js](http://leafletjs.com/) - Interactive maps
- [Lunr.js](https://lunrjs.com/) - Client-side search

---

## Support {B/qKC}

This archive is made possible through community support and the dedication of Black queer elders sharing their stories.

**Support the archive:**
- [Donate](https://bqkc.1800nasi.net/donate/)
- [Subscribe to Newsletter](https://1800nasi.substack.com)
- Share the archive with your networks

**Contact:**
- Email: [Contact form](https://bqkc.1800nasi.net/contact/)
- Archive inquiries: collectionbuilder.team@gmail.com (technical)

---

## License

{B/qKC} content and documentation is © 2024 Nasir Anthony Montalvo. All rights reserved for archive materials and collections.

CollectionBuilder code is licensed [MIT](https://github.com/CollectionBuilder/collectionbuilder-csv/blob/master/LICENSE).

This license does not include:
- Digital collection objects and images (individually licensed, see "rights" field in metadata)
- External dependencies in `assets/lib` directory (covered by individual licenses)

---

## Technical Support

**For {B/qKC}-specific deployment issues:**
- Check this README's troubleshooting section first
- Review deployment logs: `sudo tail -100 /var/www/my_webapp/deploy.log`
- Contact: Nasir Anthony Montalvo

**For CollectionBuilder questions:**
- [CollectionBuilder Discussion Forum](https://github.com/CollectionBuilder/collectionbuilder.github.io/discussions)
- Email: collectionbuilder.team@gmail.com

---

*Last updated: January 28, 2026*

**"Plainly put, the far right is erasing Blackness from the fabrics of America, so historical collection can no longer be a passive process; it must be applied radically."**

— Nasir Anthony Montalvo