367 lines
19 KiB
Markdown
367 lines
19 KiB
Markdown
# 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.*
|