The practical guide for end users (brand owners, marketers) and the
founder/operator. This doc mirrors the product's structure — open the
product and follow along. For editing the public pages (marketing/website
team), read WEBSITE_HANDOFF.md instead.
https://productiveit.in/products/brandgrowth-osBrandGrowth OS <noreply@brandtroveglobal.com> → click the link → log in.One organization (org) per brand/team. Everything you create — profiles, scans, campaigns — lives inside your workspace and is never visible to other workspaces. Plan limits (seats, scans/month, matches/month) come from your org's plan.
AI.md).audit_logs: payment
attempts, order links/outcomes, seat and pending-invite changes, live plan
price/limit edits, and partner rate-card ranges are recorded by database
triggers, including direct SQL changes. See BILLING.md and DATABASE.md for
the operator audit query and scope.--regenerate-insight (force a rewrite) and --dry-run (read the cache, write nothing) — DEPLOY.md §4.2.digest@ convention (team): the Monday cron mails every workspace member whose toggle is on, at their account email. To receive your digest in a specific inbox without putting your main address in the product, use a delivery alias: digest@brandtroveglobal.com (operator-managed in the mail admin, forwards to your real mailbox) — register or invite that alias as the workspace member and the digest lands wherever the alias points. Keep it to one hop (alias → real mailbox); never chain aliases through auto-forwarders — bulk machine mail landing in a personal Gmail is exactly what triggered Gmail's 2026-09-18 rate-limit on this domain (see the appendix in MAIL_MIGRATION_PLAN.md). Machine reports (DMARC aggregates) must use the dedicated dmarc-reports@… sinks, never a person's mailbox.[WARN] (stale) line per quiet workspace and its streak length, measured with the same helpers the notice uses — so a workspace going quiet is caught without waiting for the customer to say so. It is a warning, not a failure: nothing in the pipeline broke, so it must not page like a broken run.weekly_digest_runs ledger — a week with an existing ledger row is skipped, even if it was generated early and empty. To re-send a week: delete that ledger row, then run the script (see §9). The script also refuses a live run for a week that has not completed (its ending Monday 00:00 UTC is still in the future) — a premature run can no longer write the empty ledger row that would make Monday skip the week; preview mid-week with --dry-run.noreply@brandtroveglobal.com; replies/contact go to info@productiveit.in.Team page: invite members by email (role: owner/admin/member/viewer — capability matrix enforced server-side). Invites arrive by email; accept from the link. Seats are plan-limited. Removing a member revokes access immediately.
info@productiveit.in, we send account details, payment activates the plan (usually same day) with a receipt. See BILLING.md for the checkout status and operator go-live procedure. Annual (2 months free) on request.plans/plan_limits on the VPS (see the header comment in app/src/app/(marketing)/pricing/page.tsx) — goes live without a deploy, and is recorded (billing.plan_priced / billing.plan_limit_changed), so a hand-edited price leaves a trace like any other money change.| Task | How |
|---|---|
| Deploy an update | push to master, then on the VPS: cd /opt/brandgrowth-os && scripts/deploy.sh --skip-migrate (the script finds Node ≥ 22 itself and restarts the systemd unit safely) |
| Approve or reject an upgrade request | /admin → Plan change requests → Approve & apply / Reject. Approving applies the plan (orgs.plan_key moves in the same transaction that records decided_by), so the request queue is the whole loop — no SQL. A double-click answers 409 ALREADY_DECIDED, and a request naming a retired plan is refused rather than granted |
| Check health | curl -s https://productiveit.in/products/brandgrowth-os/api/v1/healthz |
| See who's on | VPS: journalctl -u brandgrowth-os -n 50 |
| Re-run weekly digest manually | VPS: node scripts/weekly-digest.mjs --dry-run (preview), then without --dry-run. Idempotent per workspace+week: if a week was generated early/empty, delete its weekly_digest_runs row first, then re-run |
| Re-send one week after a renderer/content fix | VPS: node scripts/weekly-digest.mjs --resend --org "<workspace name or UUID>" --week-start YYYY-MM-DD, then scripts/mail.sh. --resend is the narrow path: it requires --org, refuses an ambiguous name, and never touches the ledger — it exists precisely to push a corrected email for a week that was already generated (DEPLOY.md §4.2). The AI paragraph is reused from the cache while the measurement is unchanged; add --regenerate-insight to rewrite it |
| Watch for churn | the hourly plan-change notice emails every orgs.plan_key change (written by a trigger, so an operator's SQL is caught like a Razorpay capture). A downgrade carries its churn context: why (the request note when an operator approved one, otherwise the audit source), how old the workspace is, and when it was last used — a line marked ← REASON NOT RECORDED is the one to chase. Preview one without sending: node scripts/plan-change-notify.mjs --dry-run |
| Drain the email queue | automatic every 5 min; manual: node scripts/mail.mjs |
| Backups | automatic daily 03:15 + WAL continuous; offsite copy lands on the founder Mac daily; restore drills in DISASTER_RECOVERY.md |
| Monday health at a glance | the Monday ops dashboard email (08:30 UTC) merges the digest pipeline, AI free tiers, and backup freshness into one verdict — ALL CLEAR or N fail, M warn in the subject; sections name what broke and the documented fix |
| Inspect one section only | VPS: node scripts/digest-healthcheck.mjs --dry-run (digest), node scripts/ai-health-report.mjs --dry-run (AI), node scripts/ops-dashboard.mjs --dry-run (all three) — the dashboard prints the exact merged email without sending |
| AI providers down? | logs show [ai-gateway] all providers failed; features degrade, nothing breaks. Details in AI.md |
productiveit.in mail still lives at Zoho; the digest to a @productiveit.in address bounces until the planned mail migration (send to Gmail or a @brandtroveglobal.com alias meanwhile).