← All apps
📣

sherpa-marketing

Simultaneous Posts to Social Networks for businesses

README

# Sherpa Marketing

Multi-tenant social media publishing platform. Connect social accounts and publish content to Facebook, Instagram, and LinkedIn (TikTok coming soon) — publish now or schedule for later.

## Stack

- **Next.js 15** (App Router, TypeScript, server mode)
- **Tailwind CSS** for styling
- **Prisma + PostgreSQL** for data
- **Redis + BullMQ** for job queue (scheduled & immediate publishing)
- **NextAuth** for authentication (Google OAuth + email magic link)
- **Zod** for validation
- Provider tokens encrypted at rest with AES-256-GCM

## Quick Start (Local Development)

### Prerequisites

- Node.js 18+
- PostgreSQL running locally
- Redis running locally

### Setup

```bash
# Install dependencies
npm install

# Copy env file and fill in values
cp .env.example .env

# Generate Prisma client
npx prisma generate

# Run migrations
npx prisma migrate dev

# Seed database (creates "The Tax Shelter" org + owner user)
npm run seed

# Start dev server
npm run dev

# In a separate terminal, start the worker
npm run worker:dev
```

Visit http://localhost:3000

## NPM Scripts

| Script | Description |
|--------|-------------|
| `dev` | Start Next.js dev server |
| `build` | Build for production |
| `start` | Start production server |
| `worker` | Start BullMQ publish worker |
| `worker:dev` | Start worker with file watching |
| `migrate` | Run Prisma migrations (deploy) |
| `migrate:dev` | Run Prisma migrations (dev) |
| `seed` | Seed database |
| `generate` | Generate Prisma client |

## Deploy to Render

### Option A: Blueprint (recommended)

1. Push this repo to GitHub
2. In Render dashboard, click **New > Blueprint**
3. Connect your repo and select the `render.yaml`
4. Render will create: Web Service, Background Worker, Postgres, Redis
5. **Set these env vars manually** in Render dashboard:
   - `NEXTAUTH_URL` = `https://sherpa-marketing.onrender.com` (your Render URL)
   - `APP_ENCRYPTION_KEY` = generate with: `node -e "console.log(require('crypto').randomByt

…(truncated for upload size)

STATUS

---
type: project-status
project: sherpa-marketing
last_updated: 2026-06-09
---

# STATUS — sherpa-marketing

*The freshest file. Answers "where am I on this project?" Updated at the end of every substantive session.*

---

## Current state

Early MVP, recently picked back up after a ~10-day post-tax-season pause. CC is doing a robustness pass on the existing code (auth, encryption, error handling) ahead of onboarding the first real customer. App is deployed on Render and functional for Facebook, Instagram, and personal-profile LinkedIn posting. Two prospective users now driving the roadmap: Steph (waiting customer) and The Tax Shelter (Ken's own firm, used as the guiding light for prioritization).

## In progress

- [ ] **TikTok (Phase 1D) design** — mid-brainstorm 2026-06-09: Approach A chosen (single phase, Direct Post, video+photos, sandbox-first); design section 1 of 3 (connect/OAuth/tokens) approved; sections 2 (audit-mandated composer UX) and 3 (publish pipeline) still to present, then spec → plan. Ken's parallel task: create TikTok developer app + sandbox. Details in session memory.
- [ ] **Phase 1A publishing verification (steps 2–8)** — still outstanding (text/image/video/scheduled posts + worker log scan). Decoupled from 1A.1 on 2026-06-04 (publishing logic unchanged); will be verified organically when Stephanie/OFC connect accounts on the deployed app. No longer gates anything.
- [ ] CC's robustness pass (ongoing scope)
- [ ] Awaiting Steph's confirmation on scope email sent 2026-05-07 (LinkedIn personal vs Company Page; TikTok timeline acceptance; anything else missing)

## Next up

1. **Google Business Profile integration (Phase 1C)** — posts + review reading + review replies. Highest single value-add for a local CPA firm. Build with multi-location support from day one.
3. **LinkedIn Company Page support** — different OAuth scope and posting endpoint than the existing personal-profile flow.
4. **Worker hardening (Phase 1B)** — graceful shutdown, smarte

…(truncated for upload size)

DECISIONS

---
type: project-decisions
project: sherpa-marketing
last_updated: 2026-04-27
---

# DECISIONS — sherpa-marketing

*Architectural and scope choices. Append-only log. Each entry is a decision that shouldn't be re-litigated without new information. If you find yourself reopening a decision, either add a new entry that overrides the old (and say why) or leave both so the history is visible.*

---

## How to use this file

Each decision gets a dated entry with: what was decided, why, what was considered instead, and what would change our mind. Never delete entries — if a decision is reversed, add a new one that supersedes it.

---

## 2026-06-09 — Production-first development & testing workflow

**Decision:** Production (Render, `sherpa-marketing.onrender.com`) is the working and testing environment. Code lives on `master`; pushing `master` auto-deploys to prod; new features are exercised/connected on prod, not localhost.

**Context:** A full session of localhost work was dominated by env-parity friction — local `.env` vs Render redirect URIs, a stale local Google client secret, and four separate `redirect_uri_mismatch` incidents — none of which reflected real bugs. Ken dislikes working on localhost and notes there is no sensitive/at-risk data in this app yet.

**Alternatives considered:** Keep a local dev + cloud prod split (standard practice) — rejected for now because the dual-environment OAuth/redirect-URI bookkeeping cost more than it bought at this MVP stage.

**Reasoning:** Single environment removes the redirect-URI/secret duplication that caused every config incident this session. Acceptable specifically because there is no real customer data at risk yet.

**Would reconsider if:** Real customer/PII data lands in the shared DB, or a second developer joins — at which point a staging/prod split and feature branches become worth the overhead again. (Still branch for significant work and merge to deploy; this is about where we *test*, not abandoning branches.)

---

…(truncated for upload size)

MEMORY

---
type: project-memory
project: sherpa-marketing
last_updated: 2026-04-27
---

# MEMORY — sherpa-marketing

*Standing facts, preferences, and accumulated context. Long-lived — not "what I did yesterday" (that's STATUS.md). Update when you learn something worth keeping.*

---

## Purpose and scope

<Why this app exists, who uses it, what problem it solves. 2-3 sentences max.>

## Domain knowledge

<Rules of the domain that Claude should know before making changes. For tax apps: the specific IRS rules this module implements, state conformity notes, edge cases. For non-tax apps: business rules, workflows, naming conventions specific to this app's world.>

## User preferences discovered

<Things Ken has said he prefers, or patterns that work / don't work. Example: "Ken prefers server-rendered HTML over SPAs for internal tools." "Don't auto-format tax return numbers with commas on input, only on display.">

## Integrations and external systems

<APIs, webhooks, third-party services this app talks to. Auth patterns, rate limits, quirks.>

## Gotchas and lessons learned

<The things that have bitten us. Non-obvious behavior, debugging dead-ends, environment quirks. Write these when they happen so the next session doesn't repeat the mistake.>

## Data model highlights

<Key tables/models and what's non-obvious about them. Don't duplicate the schema — reference it. Focus on the things you'd warn someone about.>

CLAUDE.md

# Sherpa Marketing - CLAUDE.md

## Project Overview
**Name:** Sherpa Marketing (Social Media Publishing Platform)
**Port:** 3000 (Next.js default)
**Stack:** Next.js 15, React 19, TypeScript, PostgreSQL, Prisma, BullMQ, Redis, Tailwind CSS 4
**GitHub:** https://github.com/klill6506/sherpa-marketing
**Production URL:** Deployed on Render.com
**Status:** In Development (Early MVP)

## What This App Does
A multi-tenant social media publishing platform for scheduling and publishing posts across Facebook, Instagram, LinkedIn, and TikTok. Built for The Tax Shelter to manage firm marketing.

- **Social Account Connection** -- OAuth integration with Meta (Facebook Pages + Instagram Business) and LinkedIn personal profiles
- **Post Composer** -- Write posts with shared captions, hashtags, media uploads (images/video up to 100MB), and per-platform overrides
- **Publish Modes** -- Publish Now, Schedule for later (with timezone), or Save as Draft
- **Background Worker** -- BullMQ processes publish jobs with retry logic (3 attempts, exponential backoff)
- **Dashboard** -- Aggregate stats (total/scheduled/published/failed) and recent post history
- **Multi-Tenant** -- Organizations as the tenant boundary; all data scoped to `orgId`
- **Token Encryption** -- Social account tokens encrypted at rest with AES-256-GCM

## Current State / What I Was Working On
<!-- UPDATE THIS SECTION BEFORE CLOSING CLAUDE CODE -->
**Last session:** [Date]
**Working on:** [Brief description]

### What's Working:
- Google OAuth + email magic link authentication (NextAuth)
- Organization creation and membership
- Meta OAuth (Facebook Pages + Instagram Business) -- fully implemented
- LinkedIn OAuth -- fully implemented
- Post composer with media upload and per-platform toggles
- Publish Now and Schedule modes via BullMQ
- Background publish worker with retry logic
- Dashboard with stats and recent posts
- Post detail page with per-platform attempt history
- Connection management (validate, reconnect, dis

…(truncated for upload size)

Diary mentions

No recent diary mentions.

Render

  • Service: sherpa-marketing
  • Status: live
  • Last deploy: 2026-06-09T21:07:44.340138Z