# The Daily Pour — Marketing Automation Deployment

**Owner:** Annie (Marketing Lead)
**Infra:** Sam (GitLab CI + Kestra)
**Target deploy date:** Sunday, August 17, 2026
**GitLab repo:** https://gitlab.com/samueljamesinc/daily-pour-marketing (LIVE)
**Code-server:** https://code.snsnetlabs.com (LXC 304, Fedora 44, pve3)

---

## What This Is

Automated daily social media promotion for The Daily Pour, powered by Kestra workflows.
Annie manages the content calendar and approvals; the system handles content generation,
hashtag selection, platform-specific formatting, and publishing — zero daily effort once
configured.

---

## Architecture

```
┌──────────────┐     ┌───────────────┐     ┌──────────────┐     ┌─────────────┐     ┌────────────┐
│ Pre-Flight   │ ──▶ │ Content Gen   │ ──▶ │ Hashtag      │ ──▶ │ Platform    │ ──▶ │ Publish    │
│ Checks       │     │ (ChatGPT /    │     │ Engine       │     │ Formatter   │     │ (Buffer    │
│              │     │  Ollama)      │     │              │     │             │     │  API)      │
└──────────────┘     └───────────────┘     └──────────────┘     └─────────────┘     └────────────┘
       │                     │                     │                     │                   │
       ▼                     ▼                     ▼                     ▼                   ▼
  APIs alive?          Weather +             Tier 1-4 +            Per-platform        One API →
  Drive access?        day theme →           RiteKit trending +    character limits,   FB + IG +
  Platforms up?        brand voice →         rotation logic →      image specs,        TikTok +
  Content exists?      caption draft         anti-shadowban        hashtag counts      LinkedIn +
                                                                                       Google Biz
```

### Data Flow (detailed)

```
                    ┌─────────────────────────────────────────────────────┐
                    │              GitLab.com (Source of Truth)            │
                    │  daily-pour-marketing repo                          │
                    │  ├── workflows/ (Kestra YAML)                       │
                    │  ├── config/ (brand voice, hashtags, locations)     │
                    │  └── CI Variables (secrets, tokens)                 │
                    └───────────────────────┬─────────────────────────────┘
                                            │ git sync (every 15 min)
                                            ▼
┌──────────────┐              ┌─────────────────────────────┐
│ Google Drive │◀────read────▶│      Kestra (Execution)     │
│ (60GB)       │              │      192.168.122.71         │
│ ├── photos/  │              │                             │
│ ├── videos/  │              │  Cron triggers:             │
│ └── logos/   │              │  • 5:30 AM — preflight      │
└──────────────┘              │  • 6:00 AM — daily post     │
                              │  • Sun 8PM — weekly gen     │
                              └──────────────┬──────────────┘
                                             │
                              ┌──────────────┼──────────────┐
                              ▼              ▼              ▼
                    ┌──────────────┐ ┌─────────────┐ ┌──────────────┐
                    │ OpenWeather  │ │ ChatGPT /   │ │ RiteKit      │
                    │ API          │ │ Ollama      │ │ (trending    │
                    │ (weather)    │ │ (captions)  │ │  hashtags)   │
                    └──────────────┘ └─────────────┘ └──────────────┘
                                             │
                                             ▼
                              ┌─────────────────────────────┐
                              │     Buffer API              │
                              │     (single publishing      │
                              │      layer for all 5        │
                              │      platforms)             │
                              └──────────────┬──────────────┘
                                             │
                    ┌────────┬───────┬───────┼───────┬────────┐
                    ▼        ▼       ▼       ▼       ▼        │
                Facebook  Instagram TikTok LinkedIn  Google    │
                                                    Business  │
                                                              │
                              ┌────────────────────────────────┘
                              ▼
                    ┌─────────────────────────────┐
                    │ Kestra plugin-meta (backup) │
                    │ Direct FB + IG posting      │
                    │ (if Buffer doesn't cover    │
                    │  a specific need)           │
                    └─────────────────────────────┘
```

---

## Publishing Layer: Buffer API

**Why Buffer instead of 5 separate platform APIs:**
- One integration → posts to all 5 platforms
- Handles format differences (image sizes, character limits, hashtag placement)
- Built-in scheduling, analytics, engagement inbox
- Free tier: 3 channels, 10 posts/channel/month
- Paid: ~$6/channel/month ($30/mo for all 5 — cheaper than dev time on 5 APIs)
- Has an MCP server (AI agents can post directly)
- REST API: `https://api.bufferapp.com/1/updates/create.json`

**Fallback:** Kestra `plugin-meta` for direct Facebook + Instagram posting if Buffer
doesn't cover a specific need (carousels, reels with specific metadata, etc.)

**Setup:**
1. Sign up at buffer.com
2. Connect all 5 social accounts
3. Generate API token
4. Add `BUFFER_ACCESS_TOKEN` to GitLab CI Variables + Kestra namespace secrets

---

## Hashtag Engine

### Strategy: 4-Tier System with Rotation

| Tier | What | Example | Rotation |
|------|------|---------|----------|
| 1 — Brand | Always present | #TheDailyPour #DailyPourCoffee | Never changes |
| 2 — Category | Broad reach | #CoffeeAddict #SpecialtyCoffee #LocalCoffee | 3 sets, cycle every 3 days |
| 3 — Day Theme | Matches daily rotation | #MenuMonday #BehindTheScenes #FridayFeels | Changes daily |
| 4 — Dynamic | Fresh per post | Weather-based, trending, time-of-day | Every post (RiteKit + weather API) |

### Platform Limits (enforced by the formatter)

| Platform | Optimal Count | Format |
|----------|---------------|--------|
| Instagram | 20-25 | In caption or first comment (separated by dots) |
| TikTok | 5-8 | In caption only (algorithm punishes excess) |
| Facebook | 3-5 | In caption, early |
| LinkedIn | 3-5 | Final line, professional tone only |
| Google Business | 2-3 | In description, minimal |

### Anti-Shadowban Rules
- Never repeat the same Tier 2 set within 7 days on the same platform
- Rotate Tier 2 pools: A → B → C → A (3-day cycle)
- Tier 4 (trending) is always unique — pulled fresh per post
- Track hashtag history in Kestra (7-day lookback before selecting)

### Trending Hashtag Sources
- **RiteKit API** (https://ritekit.com) — give it post text, returns optimized hashtags
  based on real-time popularity. 100 free calls/month.
- **Apify TikTok Scraper** — pulls TikTok Creative Center trending hashtags daily
- **OpenWeatherMap** — weather-reactive hashtags (#SummerVibes, #CozyMorning, etc.)
- **Day-of-week cultural moments** — #MondayMotivation, #FridayFeels, #SundayFunday

### Config Files

```
config/
├── hashtag-rotation.yml    ← Tier 2 pools (A/B/C), Tier 3 by day, rotation state
├── hashtag-limits.yml      ← Per-platform max counts + format rules
└── hashtag-banned.yml      ← Hashtags known to be suppressed/banned (check monthly)

content/templates/
└── hashtags.md             ← Master reference (all tiers defined, human-readable)
```

---

## Pre-Requisites Checklist (Updated)

### Infrastructure (Sam) — ✅ = Done

- [x] **GitLab.com repo** — https://gitlab.com/samueljamesinc/daily-pour-marketing
- [x] **Kestra** running and healthy — 192.168.122.71:8080
- [x] **Code-server** — LXC 304, Fedora 44, code.snsnetlabs.com
- [x] **GitLab SSH** from code-server working
- [x] **OpenWeatherMap API** — key active, tested
- [x] **OpenAI API** — key active, tested
- [x] **Google Drive OAuth** — refresh token working, tested upload/list/download
- [x] **Pre-flight checks flow** — tested, all passing
- [x] **Weather caption flow** — tested, generating captions
- [ ] **Buffer account** — sign up, connect platforms, get API token
- [ ] **RiteKit account** — sign up, get API key (free tier)
- [ ] **Kestra ↔ GitLab sync flow** — auto-pull workflows from repo
- [ ] **Publish GCP OAuth app** (Testing → Production) — prevent 7-day token expiry

### Platform Accounts (Sam or Annie)

- [ ] **Google Business Profile** created for The Daily Pour
- [ ] **Facebook Business Page** created
- [ ] **Instagram Business Account** connected to Facebook page
- [ ] **TikTok Business Account** created
- [ ] **LinkedIn Company Page** created (SnS Hospitality Group or The Daily Pour)

### Content Library (Annie — ongoing, seed before launch)

- [ ] **Logos** — PNG (dark/light/icon), SVG source
- [ ] **Product photos** — at least 10 menu item shots
- [ ] **Trailer photos** — exterior, window, signage (even mockups/renders to start)
- [ ] **Video clips** (optional for launch) — espresso pulls, morning prep, b-roll
- [x] **Brand voice doc** — committed to repo
- [x] **Hashtag sets** — committed to repo (expand with Tier 2/3/4 config)
- [x] **Rules doc** — committed to repo
- [x] **Platform config** — committed to repo

---

## Kestra Workflows (Updated)

| # | Workflow | Trigger | What it does | Status |
|---|---------|---------|--------------|--------|
| 0 | `preflight_checks` | Before every deployment | Validates APIs, platforms, Drive, content exist | ✅ LIVE |
| 1 | `weather_caption_test` | Manual / Cron | Weather + ChatGPT → generates caption | ✅ LIVE |
| 2 | `daily_post_rotation` | Cron 6:00 AM daily | Preflight → content gen → hashtags → format → publish via Buffer | TODO |
| 3 | `weekly_content_gen` | Cron Sunday 8 PM | LLM generates 7 draft captions + hashtag sets for the week | TODO |
| 4 | `location_announce` | Manual or webhook | New location signed → announcement series across all platforms | TODO |
| 5 | `hiring_post` | Webhook from Plane | Hiring task created → generates + posts hiring content | TODO |
| 6 | `review_responder` | Cron daily 9 AM | Pulls Google reviews → drafts responses → Annie approves | TODO |
| 7 | `engagement_repost` | Cron 2x/week | Scans for UGC/mentions → queues for repost with credit | TODO |
| 8 | `hashtag_performance` | Cron Monday 9 AM | Pulls engagement data, correlates with hashtags, recommends rotations | TODO |

---

## Content Rotation (daily theme)

| Day | Type | Platforms | Tier 3 Hashtags |
|-----|------|-----------|-----------------|
| Mon | Menu highlight | All | #MenuMonday #CoffeeMagic #MondayMotivation |
| Tue | Behind the scenes | IG, TikTok, FB | #BehindTheScenes #MorningShift #BaristaDiary |
| Wed | Testimonial / review | FB, Google, LinkedIn | #CustomerLove #TestimonialTuesday #FiveStars |
| Thu | Educational / fun fact | All | #CoffeeEd #DidYouKnow #ThursdayThoughts |
| Fri | Weekend teaser + location | All | #FridayFeels #WeekendPlans #CoffeeNearMe |
| Sat | Live energy / "we're open" | IG Stories, TikTok, FB | #WeAreOpen #SaturdayVibes #LiveEnergy |
| Sun | Community / gratitude | FB, LinkedIn, IG | #CommunityLove #SundayBrunch #Grateful |

---

## GitLab Repo Structure (Updated)

```
daily-pour-marketing/                        ← https://gitlab.com/samueljamesinc/daily-pour-marketing
├── .gitlab-ci.yml                           ← Validates YAML + syncs to Kestra
├── README.md
├── content/
│   ├── logos/
│   ├── photos/{products,trailer,team,customers}/
│   ├── videos/{reels,tiktok,stories}/
│   └── templates/
│       ├── captions/                        ← Per-day caption templates
│       ├── hashtags.md                      ← Master hashtag reference
│       └── canva/                           ← Brand templates
├── config/
│   ├── brand-voice.md                       ← Annie's tone guide
│   ├── colors.md                            ← Brand palette
│   ├── rules.md                             ← What to never post
│   ├── platforms.yml                        ← Platform config (no secrets)
│   ├── locations.yml                        ← Active locations + hours
│   ├── hashtag-rotation.yml                 ← NEW: Tier 2 pools, rotation state
│   ├── hashtag-limits.yml                   ← NEW: Per-platform counts + format
│   └── hashtag-banned.yml                   ← NEW: Suppressed/banned hashtags
├── workflows/
│   ├── preflight-checks.yml                 ← ✅ LIVE
│   ├── daily-post-rotation.yml              ← TODO (full pipeline)
│   ├── weather-reactive.yml
│   ├── weekly-content-gen.yml
│   ├── location-announce.yml
│   ├── hiring-post.yml
│   ├── review-responder.yml
│   ├── engagement-repost.yml
│   └── hashtag-performance.yml              ← NEW: Weekly analytics
└── scripts/
    ├── hashtag-selector.py                  ← NEW: Tier selection + rotation logic
    ├── hashtag-validator.py                 ← NEW: Validates sets before posting
    └── platform-formatter.py               ← NEW: Formats caption + hashtags per platform
```

---

## Secrets (GitLab CI Variables + Kestra Namespace Files)

| Variable | Location | Status |
|----------|----------|--------|
| `KESTRA_API_USER` | GitLab CI | ✅ Set |
| `KESTRA_API_PASSWORD` | GitLab CI | ✅ Set |
| `KESTRA_URL` | GitLab CI | ✅ Set |
| `OPENAI_API_KEY` | GitLab CI + Kestra | ✅ Set |
| `OPENWEATHER_API_KEY` | GitLab CI + Kestra | ✅ Set |
| `GOOGLE_DRIVE_REFRESH_TOKEN` | Kestra namespace | ✅ Set (publish GCP app to prevent 7-day expiry) |
| `GOOGLE_DRIVE_CLIENT_ID` | Kestra namespace | ✅ Set |
| `GOOGLE_DRIVE_CLIENT_SECRET` | Kestra namespace | ✅ Set |
| `BUFFER_ACCESS_TOKEN` | GitLab CI + Kestra | ⬜ TODO (after Buffer signup) |
| `RITEKIT_API_KEY` | GitLab CI + Kestra | ⬜ TODO (after RiteKit signup) |
| `META_ACCESS_TOKEN` | GitLab CI + Kestra | ⬜ TODO (after FB/IG app approval) |
| `TIKTOK_ACCESS_TOKEN` | GitLab CI + Kestra | ⬜ TODO (after TikTok developer app) |
| `LINKEDIN_ACCESS_TOKEN` | GitLab CI + Kestra | ⬜ TODO (after LinkedIn API access) |
| `GOOGLE_BUSINESS_TOKEN` | GitLab CI + Kestra | ⬜ TODO (after GBP API setup) |

---

## Tech Stack

| Layer | Tool | Cost | Role |
|-------|------|------|------|
| Orchestration | Kestra (self-hosted) | Free | Cron schedules, task coordination, retry logic |
| Source control | GitLab.com | Free | Workflow YAML, config, content templates |
| Dev environment | code-server (LXC 304) | Free | Browser IDE for editing flows + scripts |
| Content storage | Google Drive (60GB) | Free | Photos, videos, logos — large binary media |
| Content generation | ChatGPT (OpenAI API) | Pay-per-use (~$0.01/caption) | Caption drafting, hashtag brainstorming |
| Local LLM (backup) | Ollama (192.168.122.20) | Free | Fallback caption gen, no API cost |
| Weather data | OpenWeatherMap | Free (1000 calls/day) | Weather-reactive content |
| Trending hashtags | RiteKit | Free (100 calls/mo) | Real-time hashtag optimization |
| TikTok trends | Apify scraper | Pay-per-run (pennies) | TikTok Creative Center trending data |
| Publishing | Buffer API | Free–$30/mo | Single API → all 5 platforms |
| Publishing (backup) | Kestra plugin-meta | Free | Direct FB + IG posting |
| Project management | Plane CE | Free (self-hosted) | Annie's task board, hiring triggers |

---

## Deployment Steps (Updated)

### Phase 1: Foundation (Done)
1. ~~Create GitLab repo~~ ✅
2. ~~Push scaffold~~ ✅
3. ~~Add CI variables (Kestra, OpenAI, OpenWeather)~~ ✅
4. ~~Build + test preflight checks~~ ✅
5. ~~Build + test weather caption flow~~ ✅

### Phase 2: Publishing Pipeline (This Week)
6. Sign up for Buffer → connect platforms → add API token
7. Sign up for RiteKit → get API key
8. Build `hashtag-rotation.yml` config
9. Build `hashtag-selector.py` script (Tier 1-4 + rotation logic)
10. Build `platform-formatter.py` (per-platform caption + hashtag assembly)
11. Build full `daily-post-rotation` workflow (preflight → gen → hashtags → format → Buffer)
12. Test end-to-end: one real post on one platform

### Phase 3: Content & Handoff (Before Launch)
13. Seed content library (10+ photos, 7 caption templates)
14. Annie reviews brand voice + hashtag sets
15. Enable cron schedules
16. Set up Kestra ↔ GitLab sync (auto-pull from repo every 15 min)
17. Publish GCP OAuth app (prevent token expiry)

### Phase 4: Analytics & Optimization (After Launch)
18. Build `hashtag-performance` weekly analytics workflow
19. Set up A/B testing framework (same content, different hashtag sets)
20. Connect Buffer analytics → Kestra for automated optimization
21. Add Apify TikTok trending scraper to daily pipeline

---

## Decision Framework Score

| Gate | Score | Reason |
|------|-------|--------|
| Time | 5 | Zero daily posting effort once live — fully automated |
| Net Worth | 4 | Consistent presence builds brand → more customers at trailer |
| Freedom | 5 | Marketing runs without Sam; scales across all trailers |
| **Total** | **14** | Execute |

---

## Repos to Evaluate (from research)

| Repo | What | Action |
|------|------|--------|
| [charlie947/social-media-skills](https://github.com/charlie947/social-media-skills) | Claude skills behind 350K-follower creator | Fork `post-writer` + `post-scorer` for caption logic |
| [rampstackco/claude-skills](https://github.com/rampstackco/claude-skills) | 65 Claude skills including SEO/content | Adapt keyword research → hashtag research |

---

*Created 2026-08-13. Updated 2026-08-14 with Buffer publishing layer, hashtag engine,
and research findings.*
