@growthub/cli 0.3.53 → 0.3.54
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/worker-kits/growthub-postiz-social-v1/.env.example +18 -0
- package/assets/worker-kits/growthub-postiz-social-v1/QUICKSTART.md +136 -0
- package/assets/worker-kits/growthub-postiz-social-v1/brands/NEW-CLIENT.md +67 -0
- package/assets/worker-kits/growthub-postiz-social-v1/brands/_template/brand-kit.md +120 -0
- package/assets/worker-kits/growthub-postiz-social-v1/brands/growthub/brand-kit.md +117 -0
- package/assets/worker-kits/growthub-postiz-social-v1/bundles/growthub-postiz-social-v1.json +52 -0
- package/assets/worker-kits/growthub-postiz-social-v1/docs/ai-caption-layer.md +118 -0
- package/assets/worker-kits/growthub-postiz-social-v1/docs/bullmq-queue-layer.md +157 -0
- package/assets/worker-kits/growthub-postiz-social-v1/docs/platform-coverage.md +97 -0
- package/assets/worker-kits/growthub-postiz-social-v1/docs/postiz-fork-integration.md +143 -0
- package/assets/worker-kits/growthub-postiz-social-v1/examples/analytics-brief-sample.md +125 -0
- package/assets/worker-kits/growthub-postiz-social-v1/examples/client-proposal-sample.md +127 -0
- package/assets/worker-kits/growthub-postiz-social-v1/examples/content-calendar-sample.md +75 -0
- package/assets/worker-kits/growthub-postiz-social-v1/examples/social-campaign-sample.md +104 -0
- package/assets/worker-kits/growthub-postiz-social-v1/growthub-meta/README.md +128 -0
- package/assets/worker-kits/growthub-postiz-social-v1/growthub-meta/kit-standard.md +113 -0
- package/assets/worker-kits/growthub-postiz-social-v1/kit.json +104 -0
- package/assets/worker-kits/growthub-postiz-social-v1/output/README.md +56 -0
- package/assets/worker-kits/growthub-postiz-social-v1/output-standards.md +127 -0
- package/assets/worker-kits/growthub-postiz-social-v1/runtime-assumptions.md +159 -0
- package/assets/worker-kits/growthub-postiz-social-v1/setup/check-deps.sh +117 -0
- package/assets/worker-kits/growthub-postiz-social-v1/setup/clone-fork.sh +83 -0
- package/assets/worker-kits/growthub-postiz-social-v1/setup/verify-env.mjs +99 -0
- package/assets/worker-kits/growthub-postiz-social-v1/skills.md +277 -0
- package/assets/worker-kits/growthub-postiz-social-v1/templates/analytics-brief.md +123 -0
- package/assets/worker-kits/growthub-postiz-social-v1/templates/caption-copy-deck.md +127 -0
- package/assets/worker-kits/growthub-postiz-social-v1/templates/client-proposal.md +139 -0
- package/assets/worker-kits/growthub-postiz-social-v1/templates/content-calendar.md +65 -0
- package/assets/worker-kits/growthub-postiz-social-v1/templates/platform-publishing-plan.md +112 -0
- package/assets/worker-kits/growthub-postiz-social-v1/templates/scheduling-manifest.md +83 -0
- package/assets/worker-kits/growthub-postiz-social-v1/templates/social-campaign-brief.md +111 -0
- package/assets/worker-kits/growthub-postiz-social-v1/validation-checklist.md +79 -0
- package/assets/worker-kits/growthub-postiz-social-v1/workers/postiz-social-operator/CLAUDE.md +287 -0
- package/package.json +1 -1
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# Output Standards
|
|
2
|
+
|
|
3
|
+
**All Postiz Social Media Operator outputs must meet these standards before being delivered to a client.**
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Output Directory Structure
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
output/
|
|
11
|
+
<client-slug>/
|
|
12
|
+
<project-slug>/
|
|
13
|
+
SocialCampaignBrief_v<N>_<YYYYMMDD>.md
|
|
14
|
+
ContentCalendar_v<N>_<YYYYMMDD>.md
|
|
15
|
+
PlatformPublishingPlan_v<N>_<YYYYMMDD>.md
|
|
16
|
+
CaptionCopyDeck_v<N>_<YYYYMMDD>.md
|
|
17
|
+
SchedulingManifest_v<N>_<YYYYMMDD>.md (if scheduling requested)
|
|
18
|
+
AnalyticsBrief_v<N>_<YYYYMMDD>.md (if analytics data available)
|
|
19
|
+
ClientProposal_v<N>_<YYYYMMDD>.md (if requested)
|
|
20
|
+
scheduling-manifest.json (always when scheduling — powers Postiz API)
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## File Naming Convention
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
<ClientSlug>_<OutputType>_v<N>_<YYYYMMDD>.md
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
| Part | Rules | Example |
|
|
32
|
+
|---|---|---|
|
|
33
|
+
| ClientSlug | TitleCase, no spaces, no special chars | `UrbanCycle` |
|
|
34
|
+
| OutputType | CamelCase from the list below | `ContentCalendar` |
|
|
35
|
+
| Version | `v` + integer, starting at 1 | `v1` |
|
|
36
|
+
| Date | `YYYYMMDD` format | `20260415` |
|
|
37
|
+
|
|
38
|
+
**Output type names:**
|
|
39
|
+
|
|
40
|
+
| Artifact | OutputType string |
|
|
41
|
+
|---|---|
|
|
42
|
+
| Social Campaign Brief | `SocialCampaignBrief` |
|
|
43
|
+
| Content Calendar | `ContentCalendar` |
|
|
44
|
+
| Platform Publishing Plan | `PlatformPublishingPlan` |
|
|
45
|
+
| Caption Copy Deck | `CaptionCopyDeck` |
|
|
46
|
+
| Scheduling Manifest | `SchedulingManifest` |
|
|
47
|
+
| Analytics Brief | `AnalyticsBrief` |
|
|
48
|
+
| Client Proposal | `ClientProposal` |
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Required Sections Per Artifact
|
|
53
|
+
|
|
54
|
+
Each artifact must include all sections from its template. Incomplete sections must be marked `<!-- data-gap: reason -->` — never left blank without explanation.
|
|
55
|
+
|
|
56
|
+
| Artifact | Minimum Required Sections |
|
|
57
|
+
|---|---|
|
|
58
|
+
| SocialCampaignBrief | Project Overview, Campaign Objective, Target Platforms, Audience Profile, KPI Targets, Content Theme Pillars, Brand Voice |
|
|
59
|
+
| ContentCalendar | Calendar Header (client, period, platforms), Calendar Table (all rows with all columns), Posting Cadence Summary |
|
|
60
|
+
| PlatformPublishingPlan | Per-platform rows (all selected platforms), Format spec, Frequency, Best posting times, Content mix ratio |
|
|
61
|
+
| CaptionCopyDeck | Per-post entries (A/B/C variants each), Hashtag sets, Character counts, Media asset notes |
|
|
62
|
+
| SchedulingManifest | Manifest header, All post entries (postId, platform, scheduledAt, content, mediaAssets, status) |
|
|
63
|
+
| AnalyticsBrief | Period summary, Per-platform metrics table, Top 3 posts, Bottom 3 posts, Recommendations |
|
|
64
|
+
| ClientProposal | Campaign Overview, Platform Mix rationale, Content Strategy, Deliverables scope, Pricing (3 tiers), ROI Projection |
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## Quality Bar
|
|
69
|
+
|
|
70
|
+
### Platform-Accurate
|
|
71
|
+
|
|
72
|
+
- All platform IDs must match the official list in `docs/platform-coverage.md`
|
|
73
|
+
- Character limits must be respected for every caption variant
|
|
74
|
+
- Post types must be valid for the target platform (e.g., no carousels on TikTok)
|
|
75
|
+
|
|
76
|
+
### Caption Quality
|
|
77
|
+
|
|
78
|
+
- Every caption must have an explicit CTA — "Learn more" is acceptable; blank is not
|
|
79
|
+
- All 3 variants (A/B/C) must be meaningfully different — not minor word swaps
|
|
80
|
+
- Hashtags must be relevant to the content — no generic filler (#love, #instagood) unless platform context demands it
|
|
81
|
+
|
|
82
|
+
### Scheduling Manifest
|
|
83
|
+
|
|
84
|
+
- `scheduledAt` timestamps must be ISO 8601 format with timezone offset
|
|
85
|
+
- `postId` must follow the naming convention: `<client-slug>-<YYYYMMDD>-<platform>-<sequence>`
|
|
86
|
+
- All posts in the manifest must have a corresponding entry in the ContentCalendar
|
|
87
|
+
- `workspaceId` must be present when Postiz API is targeted (even if placeholder in agent-only mode)
|
|
88
|
+
|
|
89
|
+
### No Filler
|
|
90
|
+
|
|
91
|
+
- Every sentence must either present data, explain a constraint, or specify an action
|
|
92
|
+
- Remove phrases like "Great content is key" — replace with the actual content specification
|
|
93
|
+
- Recommendations must be specific: name the exact platform, posting time, content format, and expected impact
|
|
94
|
+
|
|
95
|
+
### Actionable
|
|
96
|
+
|
|
97
|
+
- Every post entry in the ContentCalendar must have a ready-to-use caption variant
|
|
98
|
+
- Every platform in the PlatformPublishingPlan must have a posting time recommendation
|
|
99
|
+
- Every finding in the AnalyticsBrief must have a corresponding action item
|
|
100
|
+
|
|
101
|
+
### Consistent
|
|
102
|
+
|
|
103
|
+
- Platform names in all artifacts must use the same slug format from `docs/platform-coverage.md`
|
|
104
|
+
- Dates must be consistent across all artifacts
|
|
105
|
+
- Client name must match the brand kit exactly
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## Versioning Rules
|
|
110
|
+
|
|
111
|
+
| Scenario | Action |
|
|
112
|
+
|---|---|
|
|
113
|
+
| First campaign for a client | All files at v1 |
|
|
114
|
+
| Campaign revised post-approval | Increment all files to v2 |
|
|
115
|
+
| Partial update (one artifact revised) | Increment only the revised artifact's version |
|
|
116
|
+
| New campaign, same client | Start new project-slug, all files at v1 |
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## scheduling-manifest.json
|
|
121
|
+
|
|
122
|
+
This file must always be written to the output directory when scheduling is requested. It is the machine-readable record required for:
|
|
123
|
+
- Postiz API bulk scheduling (`POST /api/v1/posts/bulk`)
|
|
124
|
+
- Manual review before submitting to Postiz
|
|
125
|
+
- Campaign audit trail
|
|
126
|
+
|
|
127
|
+
See `templates/scheduling-manifest.md` for the complete format with all required fields.
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
# Runtime Assumptions
|
|
2
|
+
|
|
3
|
+
**Frozen at kit creation: 2026-04-15. Update this file when upstream Postiz fork behavior changes.**
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Execution Mode Overview
|
|
8
|
+
|
|
9
|
+
| Mode | Requirements | Fork Used? | Postiz API? | Scheduling? | Caption AI? |
|
|
10
|
+
|---|---|---|---|---|---|
|
|
11
|
+
| `local-fork` | Node 18+, Docker, Postiz running | Yes | Yes | Yes | Yes |
|
|
12
|
+
| `agent-only` | Nothing (Claude Code only) | No | No | Dry-run JSON only | Yes |
|
|
13
|
+
| `hybrid` | ANTHROPIC_API_KEY + Postiz running | Yes | Yes | Yes | Yes |
|
|
14
|
+
|
|
15
|
+
### Choosing a Mode
|
|
16
|
+
|
|
17
|
+
- **Use `local-fork`** when you need real Postiz API scheduling, multi-workspace support, or live BullMQ queue management.
|
|
18
|
+
- **Use `agent-only`** when Postiz is not installed or when you only need campaign planning, content calendars, and caption drafts.
|
|
19
|
+
- **Use `hybrid`** when you want enhanced AI caption generation via Anthropic API alongside live Postiz scheduling.
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Postiz Upstream Assumptions
|
|
24
|
+
|
|
25
|
+
These are the assumptions frozen at kit creation time about the Postiz fork at https://github.com/gitroomhq/postiz-app.
|
|
26
|
+
|
|
27
|
+
### Service Topology
|
|
28
|
+
|
|
29
|
+
| Service | Container | Default Port | Purpose |
|
|
30
|
+
|---|---|---|---|
|
|
31
|
+
| Postiz App | `postiz` | 3000 | NestJS API + Next.js frontend |
|
|
32
|
+
| PostgreSQL | `postiz-postgres` | 5432 | Primary data store |
|
|
33
|
+
| Redis | `postiz-redis` | 6379 | BullMQ job queue, session cache |
|
|
34
|
+
|
|
35
|
+
All services are defined in `docker-compose.yml` at the fork root.
|
|
36
|
+
|
|
37
|
+
### Node.js Environment
|
|
38
|
+
|
|
39
|
+
| Requirement | Value | Notes |
|
|
40
|
+
|---|---|---|
|
|
41
|
+
| Node version | 18+ | Tested on 18 and 20 LTS |
|
|
42
|
+
| Package manager | pnpm | `pnpm install` from repo root |
|
|
43
|
+
| Monorepo structure | Turborepo | `apps/` and `libraries/` |
|
|
44
|
+
| Backend framework | NestJS | `apps/backend/` |
|
|
45
|
+
| Frontend framework | Next.js 14 | `apps/frontend/` |
|
|
46
|
+
|
|
47
|
+
### 28+ Platform Integrations (at time of freeze)
|
|
48
|
+
|
|
49
|
+
The following platform integrations ship with the Postiz codebase under `libraries/nestjs-libraries/src/integrations/`:
|
|
50
|
+
|
|
51
|
+
| Platform | Integration ID | Auth Method |
|
|
52
|
+
|---|---|---|
|
|
53
|
+
| Instagram | `instagram` | Meta OAuth |
|
|
54
|
+
| LinkedIn | `linkedin` | LinkedIn OAuth |
|
|
55
|
+
| TikTok | `tiktok` | TikTok OAuth |
|
|
56
|
+
| X/Twitter | `twitter` | Twitter OAuth 2.0 |
|
|
57
|
+
| YouTube | `youtube` | Google OAuth |
|
|
58
|
+
| Pinterest | `pinterest` | Pinterest OAuth |
|
|
59
|
+
| Reddit | `reddit` | Reddit OAuth |
|
|
60
|
+
| Facebook | `facebook` | Meta OAuth |
|
|
61
|
+
| Bluesky | `bluesky` | AT Protocol credentials |
|
|
62
|
+
| Mastodon | `mastodon` | Mastodon OAuth (instance-specific) |
|
|
63
|
+
| Slack | `slack` | Slack OAuth |
|
|
64
|
+
| Telegram | `telegram` | Telegram Bot API token |
|
|
65
|
+
| Discord | `discord` | Discord Bot token |
|
|
66
|
+
| Threads | `threads` | Meta OAuth |
|
|
67
|
+
| Dribbble | `dribbble` | Dribbble OAuth |
|
|
68
|
+
| Tumblr | `tumblr` | Tumblr OAuth |
|
|
69
|
+
| Medium | `medium` | Medium OAuth |
|
|
70
|
+
| DevTo | `devto` | DEV API key |
|
|
71
|
+
| Hashnode | `hashnode` | Hashnode API key |
|
|
72
|
+
| Lemmy | `lemmy` | Lemmy credentials |
|
|
73
|
+
| Nostr | `nostr` | Nostr keypair |
|
|
74
|
+
|
|
75
|
+
*Additional platforms may be available in newer Postiz releases. Check `libraries/nestjs-libraries/src/integrations/` in the fork for the current list.*
|
|
76
|
+
|
|
77
|
+
### BullMQ Queue Architecture
|
|
78
|
+
|
|
79
|
+
- Queue name: `post` (primary publishing queue)
|
|
80
|
+
- Job type: `publish-post`
|
|
81
|
+
- Delay scheduling: supported via BullMQ `delay` option (milliseconds from now)
|
|
82
|
+
- Retry logic: 3 attempts, exponential backoff (configurable in Postiz admin)
|
|
83
|
+
- Dead letter queue: failed jobs visible in Postiz admin at `/admin/queues`
|
|
84
|
+
|
|
85
|
+
### AI Caption Generation
|
|
86
|
+
|
|
87
|
+
Postiz ships with optional AI caption generation. At time of freeze:
|
|
88
|
+
- OpenAI GPT-4o: enabled when `OPENAI_API_KEY` is set in Postiz `.env`
|
|
89
|
+
- Anthropic Claude: enabled when `ANTHROPIC_API_KEY` is set
|
|
90
|
+
- AI captions are generated via `POST /api/v1/posts/ai/generate`
|
|
91
|
+
- This kit uses the agent's own Anthropic API key (via `ANTHROPIC_API_KEY` in this kit's `.env`) for caption drafts — independent of the Postiz instance's AI config
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## Execution Surface Flows
|
|
96
|
+
|
|
97
|
+
### Local-Fork Mode
|
|
98
|
+
|
|
99
|
+
```
|
|
100
|
+
User request → Environment gate (Step 0)
|
|
101
|
+
↓
|
|
102
|
+
Read skills.md + brand kit (Step 1)
|
|
103
|
+
↓
|
|
104
|
+
Read runtime docs (Step 2)
|
|
105
|
+
↓
|
|
106
|
+
Inspect Postiz fork: docker ps, API healthcheck, platform list (Step 3)
|
|
107
|
+
↓
|
|
108
|
+
4-question gate (Step 4)
|
|
109
|
+
↓
|
|
110
|
+
Select /postiz command (Step 5)
|
|
111
|
+
↓
|
|
112
|
+
Phase 1: Campaign strategy + platform selection (Step 6)
|
|
113
|
+
↓
|
|
114
|
+
Phase 2: Content calendar + caption copy deck (Step 7)
|
|
115
|
+
↓
|
|
116
|
+
Phase 3: Scheduling manifest → POST /api/v1/posts/bulk (Step 8)
|
|
117
|
+
↓
|
|
118
|
+
Artifact package: 5–7 Markdown files + scheduling-manifest.json (Step 9)
|
|
119
|
+
↓
|
|
120
|
+
Log deliverable → brand kit DELIVERABLES LOG (Step 10)
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Agent-Only Mode
|
|
124
|
+
|
|
125
|
+
```
|
|
126
|
+
User request → Environment gate (Step 0 — confirm agent-only)
|
|
127
|
+
↓
|
|
128
|
+
Read skills.md + brand kit (Step 1)
|
|
129
|
+
↓
|
|
130
|
+
Read runtime docs (Step 2)
|
|
131
|
+
↓
|
|
132
|
+
Skip fork inspection (Step 3 — N/A)
|
|
133
|
+
↓
|
|
134
|
+
4-question gate (Step 4)
|
|
135
|
+
↓
|
|
136
|
+
Select /postiz command (Step 5)
|
|
137
|
+
↓
|
|
138
|
+
Phase 1: Campaign strategy + platform selection (Step 6)
|
|
139
|
+
↓
|
|
140
|
+
Phase 2: Content calendar + caption copy deck (Step 7)
|
|
141
|
+
↓
|
|
142
|
+
Phase 3: Dry-run scheduling manifest (JSON — for manual submission) (Step 8)
|
|
143
|
+
↓
|
|
144
|
+
Artifact package: 5–7 Markdown files + scheduling-manifest.json (Step 9)
|
|
145
|
+
↓
|
|
146
|
+
Log deliverable → brand kit DELIVERABLES LOG (Step 10)
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
## Output Assumption
|
|
152
|
+
|
|
153
|
+
All outputs are Markdown files written to:
|
|
154
|
+
|
|
155
|
+
```
|
|
156
|
+
output/<client-slug>/<project-slug>/
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
The scheduling manifest is a JSON file (`scheduling-manifest.json`) written alongside the Markdown artifacts. It is the machine-readable record for Postiz API submission.
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# check-deps.sh — Verify system dependencies for the Postiz Social Media Studio
|
|
3
|
+
# Usage: bash setup/check-deps.sh
|
|
4
|
+
set -e
|
|
5
|
+
|
|
6
|
+
GREEN="\033[0;32m"
|
|
7
|
+
RED="\033[0;31m"
|
|
8
|
+
YELLOW="\033[0;33m"
|
|
9
|
+
RESET="\033[0m"
|
|
10
|
+
|
|
11
|
+
PASS=0
|
|
12
|
+
FAIL=0
|
|
13
|
+
WARN=0
|
|
14
|
+
|
|
15
|
+
ok() {
|
|
16
|
+
echo -e " ${GREEN}✓${RESET} $1"
|
|
17
|
+
PASS=$((PASS + 1))
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
fail() {
|
|
21
|
+
echo -e " ${RED}✗${RESET} $1"
|
|
22
|
+
FAIL=$((FAIL + 1))
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
warn() {
|
|
26
|
+
echo -e " ${YELLOW}⚠${RESET} $1"
|
|
27
|
+
WARN=$((WARN + 1))
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
echo "=== Growthub Postiz Social Media Studio — Dependency Check ==="
|
|
31
|
+
echo ""
|
|
32
|
+
|
|
33
|
+
# --- Node.js ---
|
|
34
|
+
if command -v node &>/dev/null; then
|
|
35
|
+
NODE_VER=$(node --version | sed 's/v//')
|
|
36
|
+
NODE_MAJOR=$(echo "$NODE_VER" | cut -d. -f1)
|
|
37
|
+
if [ "$NODE_MAJOR" -ge 18 ]; then
|
|
38
|
+
ok "node v${NODE_VER} (18+ required)"
|
|
39
|
+
else
|
|
40
|
+
fail "node v${NODE_VER} — version 18+ required. Install from https://nodejs.org"
|
|
41
|
+
fi
|
|
42
|
+
else
|
|
43
|
+
fail "node — not found. Install from https://nodejs.org"
|
|
44
|
+
fi
|
|
45
|
+
|
|
46
|
+
# --- npm ---
|
|
47
|
+
if command -v npm &>/dev/null; then
|
|
48
|
+
ok "npm $(npm --version)"
|
|
49
|
+
else
|
|
50
|
+
warn "npm — not found. Usually installed with Node.js."
|
|
51
|
+
fi
|
|
52
|
+
|
|
53
|
+
# --- pnpm (used by Postiz monorepo) ---
|
|
54
|
+
if command -v pnpm &>/dev/null; then
|
|
55
|
+
ok "pnpm $(pnpm --version)"
|
|
56
|
+
else
|
|
57
|
+
warn "pnpm — not found. Required if building Postiz from source. Install: npm install -g pnpm"
|
|
58
|
+
fi
|
|
59
|
+
|
|
60
|
+
# --- Docker ---
|
|
61
|
+
if command -v docker &>/dev/null; then
|
|
62
|
+
DOCKER_VER=$(docker --version | awk '{print $3}' | sed 's/,//')
|
|
63
|
+
ok "docker $DOCKER_VER"
|
|
64
|
+
# Check Docker daemon is running
|
|
65
|
+
if docker info &>/dev/null 2>&1; then
|
|
66
|
+
ok "docker daemon is running"
|
|
67
|
+
else
|
|
68
|
+
fail "docker daemon is not running. Start Docker Desktop or: sudo systemctl start docker"
|
|
69
|
+
fi
|
|
70
|
+
else
|
|
71
|
+
fail "docker — not found. Install from https://docker.com"
|
|
72
|
+
fi
|
|
73
|
+
|
|
74
|
+
# --- Docker Compose ---
|
|
75
|
+
if docker compose version &>/dev/null 2>&1; then
|
|
76
|
+
COMPOSE_VER=$(docker compose version --short 2>/dev/null || echo "unknown")
|
|
77
|
+
ok "docker compose $COMPOSE_VER"
|
|
78
|
+
elif command -v docker-compose &>/dev/null; then
|
|
79
|
+
warn "docker-compose (standalone) found. Prefer Docker Compose V2 plugin (docker compose)."
|
|
80
|
+
else
|
|
81
|
+
fail "docker compose — not found. Install Docker Desktop or the Docker Compose plugin."
|
|
82
|
+
fi
|
|
83
|
+
|
|
84
|
+
# --- Git ---
|
|
85
|
+
if command -v git &>/dev/null; then
|
|
86
|
+
ok "git $(git --version | awk '{print $3}')"
|
|
87
|
+
else
|
|
88
|
+
fail "git — not found. Install from https://git-scm.com/downloads"
|
|
89
|
+
fi
|
|
90
|
+
|
|
91
|
+
# --- curl ---
|
|
92
|
+
if command -v curl &>/dev/null; then
|
|
93
|
+
ok "curl $(curl --version | head -1 | awk '{print $2}')"
|
|
94
|
+
else
|
|
95
|
+
warn "curl — not found. Used for API healthchecks."
|
|
96
|
+
fi
|
|
97
|
+
|
|
98
|
+
# --- Summary ---
|
|
99
|
+
echo ""
|
|
100
|
+
echo "=== Summary ==="
|
|
101
|
+
echo " Passed: $PASS"
|
|
102
|
+
if [ "$WARN" -gt 0 ]; then
|
|
103
|
+
echo -e " ${YELLOW}Warnings: $WARN${RESET}"
|
|
104
|
+
fi
|
|
105
|
+
if [ "$FAIL" -gt 0 ]; then
|
|
106
|
+
echo -e " ${RED}Failed: $FAIL${RESET}"
|
|
107
|
+
echo ""
|
|
108
|
+
echo "Install missing dependencies and re-run this script."
|
|
109
|
+
exit 1
|
|
110
|
+
else
|
|
111
|
+
echo ""
|
|
112
|
+
if [ "$WARN" -gt 0 ]; then
|
|
113
|
+
echo -e "${YELLOW}Dependencies OK with warnings. Local-fork mode may need attention.${RESET}"
|
|
114
|
+
else
|
|
115
|
+
echo -e "${GREEN}All dependencies satisfied.${RESET}"
|
|
116
|
+
fi
|
|
117
|
+
fi
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# clone-fork.sh — Clone Postiz and start the local workspace via Docker Compose
|
|
3
|
+
# Usage: bash setup/clone-fork.sh
|
|
4
|
+
set -e
|
|
5
|
+
|
|
6
|
+
FORK_DIR="${POSTIZ_FORK_PATH:-$HOME/postiz-app}"
|
|
7
|
+
REPO_URL="https://github.com/gitroomhq/postiz-app"
|
|
8
|
+
|
|
9
|
+
echo "=== Growthub Postiz Social Media Studio — Fork Setup ==="
|
|
10
|
+
echo ""
|
|
11
|
+
|
|
12
|
+
if [ -d "$FORK_DIR" ]; then
|
|
13
|
+
echo "Fork already exists at $FORK_DIR — skipping clone."
|
|
14
|
+
echo "To re-clone, remove the directory first: rm -rf $FORK_DIR"
|
|
15
|
+
else
|
|
16
|
+
echo "Cloning Postiz → $FORK_DIR"
|
|
17
|
+
git clone "$REPO_URL" "$FORK_DIR"
|
|
18
|
+
echo "Clone complete."
|
|
19
|
+
fi
|
|
20
|
+
|
|
21
|
+
echo ""
|
|
22
|
+
echo "Checking for .env configuration..."
|
|
23
|
+
if [ ! -f "$FORK_DIR/.env" ]; then
|
|
24
|
+
if [ -f "$FORK_DIR/.env.example" ]; then
|
|
25
|
+
cp "$FORK_DIR/.env.example" "$FORK_DIR/.env"
|
|
26
|
+
echo "Copied .env.example to .env — edit $FORK_DIR/.env with your credentials before starting services."
|
|
27
|
+
echo ""
|
|
28
|
+
echo " Minimum required values in $FORK_DIR/.env:"
|
|
29
|
+
echo " DATABASE_URL=..."
|
|
30
|
+
echo " REDIS_URL=..."
|
|
31
|
+
echo " JWT_SECRET=..."
|
|
32
|
+
echo " NEXTAUTH_SECRET=..."
|
|
33
|
+
echo ""
|
|
34
|
+
echo " Then re-run this script to start the services."
|
|
35
|
+
exit 0
|
|
36
|
+
else
|
|
37
|
+
echo "WARNING: No .env.example found in the Postiz repo. Create $FORK_DIR/.env manually."
|
|
38
|
+
echo "See https://docs.postiz.com/configuration/environment-variables for required variables."
|
|
39
|
+
exit 1
|
|
40
|
+
fi
|
|
41
|
+
fi
|
|
42
|
+
|
|
43
|
+
echo ""
|
|
44
|
+
echo "Starting Postiz services via Docker Compose..."
|
|
45
|
+
cd "$FORK_DIR"
|
|
46
|
+
docker compose up -d
|
|
47
|
+
|
|
48
|
+
echo ""
|
|
49
|
+
echo "Waiting for Postiz API to become healthy..."
|
|
50
|
+
MAX_WAIT=60
|
|
51
|
+
WAITED=0
|
|
52
|
+
while [ "$WAITED" -lt "$MAX_WAIT" ]; do
|
|
53
|
+
if curl -s http://localhost:3000/api/healthcheck > /dev/null 2>&1; then
|
|
54
|
+
echo "Postiz API is healthy."
|
|
55
|
+
break
|
|
56
|
+
fi
|
|
57
|
+
sleep 2
|
|
58
|
+
WAITED=$((WAITED + 2))
|
|
59
|
+
echo " Waiting... (${WAITED}s elapsed)"
|
|
60
|
+
done
|
|
61
|
+
|
|
62
|
+
if [ "$WAITED" -ge "$MAX_WAIT" ]; then
|
|
63
|
+
echo ""
|
|
64
|
+
echo "WARNING: Postiz API did not become healthy within ${MAX_WAIT}s."
|
|
65
|
+
echo "Check docker logs: docker compose logs -f postiz"
|
|
66
|
+
echo "The services may still be starting — try again in 30 seconds."
|
|
67
|
+
exit 1
|
|
68
|
+
fi
|
|
69
|
+
|
|
70
|
+
echo ""
|
|
71
|
+
echo "=== Postiz workspace is ready ==="
|
|
72
|
+
echo ""
|
|
73
|
+
echo " Admin UI: http://localhost:3000"
|
|
74
|
+
echo " API: http://localhost:3000/api"
|
|
75
|
+
echo ""
|
|
76
|
+
echo "Next steps:"
|
|
77
|
+
echo " 1. Open http://localhost:3000 and complete the initial setup wizard"
|
|
78
|
+
echo " 2. Connect your social media accounts in Settings > Integrations"
|
|
79
|
+
echo " 3. Copy your Workspace ID from Settings > Workspace"
|
|
80
|
+
echo " 4. Set POSTIZ_WORKSPACE_ID in this kit's .env file"
|
|
81
|
+
echo " 5. Run: node setup/verify-env.mjs"
|
|
82
|
+
echo ""
|
|
83
|
+
echo "To stop Postiz: docker compose stop (from $FORK_DIR)"
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// verify-env.mjs — Verify Postiz fork and kit environment configuration
|
|
3
|
+
// Usage: node setup/verify-env.mjs
|
|
4
|
+
|
|
5
|
+
import { existsSync } from "node:fs";
|
|
6
|
+
import { join } from "node:path";
|
|
7
|
+
import { homedir } from "node:os";
|
|
8
|
+
|
|
9
|
+
const RED = "\x1b[31m";
|
|
10
|
+
const GREEN = "\x1b[32m";
|
|
11
|
+
const YELLOW = "\x1b[33m";
|
|
12
|
+
const RESET = "\x1b[0m";
|
|
13
|
+
|
|
14
|
+
let allPassed = true;
|
|
15
|
+
const results = [];
|
|
16
|
+
|
|
17
|
+
function check(label, passed, detail = "") {
|
|
18
|
+
const icon = passed ? `${GREEN}✓${RESET}` : `${RED}✗${RESET}`;
|
|
19
|
+
results.push({ label, passed, detail, icon });
|
|
20
|
+
if (!passed) allPassed = false;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function warn(label, detail = "") {
|
|
24
|
+
results.push({ label, passed: null, detail, icon: `${YELLOW}⚠${RESET}` });
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
console.log("Growthub Postiz Social Media Studio — Environment Verification");
|
|
28
|
+
console.log("=".repeat(60));
|
|
29
|
+
console.log("");
|
|
30
|
+
|
|
31
|
+
// --- Check 1: Postiz fork path ---
|
|
32
|
+
const forkPath = process.env.POSTIZ_FORK_PATH ?? join(homedir(), "postiz-app");
|
|
33
|
+
const forkExists = existsSync(forkPath);
|
|
34
|
+
check("Postiz fork directory exists", forkExists, forkExists ? forkPath : `Not found at ${forkPath}`);
|
|
35
|
+
|
|
36
|
+
if (forkExists) {
|
|
37
|
+
const dockerCompose = existsSync(join(forkPath, "docker-compose.yml"));
|
|
38
|
+
check("docker-compose.yml present in fork", dockerCompose);
|
|
39
|
+
|
|
40
|
+
const envFile = existsSync(join(forkPath, ".env"));
|
|
41
|
+
check("Postiz .env file present", envFile, envFile ? "" : `Run: cp ${forkPath}/.env.example ${forkPath}/.env`);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// --- Check 2: Postiz API reachability ---
|
|
45
|
+
const postizApiUrl = process.env.POSTIZ_API_URL ?? "http://localhost:3000";
|
|
46
|
+
let apiHealthy = false;
|
|
47
|
+
try {
|
|
48
|
+
const controller = new AbortController();
|
|
49
|
+
const timeout = setTimeout(() => controller.abort(), 3000);
|
|
50
|
+
const res = await fetch(`${postizApiUrl}/api/healthcheck`, { signal: controller.signal });
|
|
51
|
+
clearTimeout(timeout);
|
|
52
|
+
apiHealthy = res.ok;
|
|
53
|
+
} catch {
|
|
54
|
+
apiHealthy = false;
|
|
55
|
+
}
|
|
56
|
+
check("Postiz API is reachable", apiHealthy, apiHealthy ? postizApiUrl : `Not reachable at ${postizApiUrl} — run: bash setup/clone-fork.sh`);
|
|
57
|
+
|
|
58
|
+
// --- Check 3: Workspace ID ---
|
|
59
|
+
const workspaceId = process.env.POSTIZ_WORKSPACE_ID;
|
|
60
|
+
if (workspaceId && workspaceId !== "your_workspace_uuid_here") {
|
|
61
|
+
check("POSTIZ_WORKSPACE_ID is set", true, workspaceId.slice(0, 8) + "...");
|
|
62
|
+
} else {
|
|
63
|
+
warn("POSTIZ_WORKSPACE_ID not set", "Required for scheduling manifest submission — find it in Postiz Settings > Workspace");
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// --- Check 4: Anthropic API key ---
|
|
67
|
+
const anthropicKey = process.env.ANTHROPIC_API_KEY;
|
|
68
|
+
if (!anthropicKey || anthropicKey === "your_anthropic_key_here") {
|
|
69
|
+
warn("ANTHROPIC_API_KEY not set", "Optional — required for AI-enhanced caption generation in agent-only and hybrid modes");
|
|
70
|
+
} else if (anthropicKey.startsWith("sk-ant-")) {
|
|
71
|
+
check("ANTHROPIC_API_KEY format is valid", true);
|
|
72
|
+
} else {
|
|
73
|
+
check("ANTHROPIC_API_KEY format is valid", false, "Key does not start with sk-ant- — check your Anthropic console");
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// --- Print results ---
|
|
77
|
+
console.log("Results:");
|
|
78
|
+
for (const { icon, label, detail } of results) {
|
|
79
|
+
const detailStr = detail ? ` → ${detail}` : "";
|
|
80
|
+
console.log(` ${icon} ${label}${detailStr}`);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
console.log("");
|
|
84
|
+
|
|
85
|
+
if (allPassed) {
|
|
86
|
+
console.log(`${GREEN}All checks passed. Ready for local-fork or hybrid mode.${RESET}`);
|
|
87
|
+
} else {
|
|
88
|
+
const warnings = results.filter((r) => r.passed === null);
|
|
89
|
+
const failures = results.filter((r) => r.passed === false);
|
|
90
|
+
if (failures.length > 0) {
|
|
91
|
+
console.log(`${RED}${failures.length} check(s) failed. See details above.${RESET}`);
|
|
92
|
+
if (!apiHealthy) {
|
|
93
|
+
console.log(`\n To start Postiz: bash setup/clone-fork.sh`);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
if (warnings.length > 0 && failures.length === 0) {
|
|
97
|
+
console.log(`${YELLOW}Checks passed with warnings. Agent-only mode is available.${RESET}`);
|
|
98
|
+
}
|
|
99
|
+
}
|