The organizations resource hit LinkedIn's app-wide daily cap; organizationsLookup
has its own. Falls back to organizations, then ids.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Single-Page lookups hit LinkedIn's daily per-member limit for admins of many Pages,
so the Page list fell back to ids.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The approved app has no OpenID Connect product, so openid/profile/r_organization_admin
would fail. Use r_basicprofile + rw_organization_admin and read the member from /v2/me.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Places API (New): competitor scans find local rivals on Google Maps and the
server reads real ratings/review counts by place id; client's own listing
fills the "You" row; recent reviews for praise/complaint themes; 30-day cache
- Google Trends via DataForSEO: rising/top related searches and % change per
keyword in the client's region; used by trend-scan and to check gap demand
- Instagram Hashtag Search: top/recent posts under a niche hashtag (tool +
Competitors page panel), counts Instagram's 30 tags/week limit
- Server settings → Research: keys plus on/off switches for each source
(hashtag search off until Meta approves Public Content Access)
- Reports mark website-sourced ratings as unverified; skill takes handles
only from a business's own site
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- competitor-scan skill + run type: web search for local rivals and
niche benchmarks, competitor_suggest checks each on Instagram
- Suggestions inbox on Competitors page (Track / Dismiss)
- Report blocks: leaderboard, size-vs-engagement map, format lift,
market's best posts, hashtag gap, Google ratings
- Stats: engagement by format, top hashtags; audit adds leaderboard
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Server settings (Settings page): SMTP, AI, publishing, Meta, platform keys and,
on the control centre only, Stripe/billing. Stored sealed in data/settings.json and
applied over .env in every process; hosted agency workspaces don't see our email,
platform keys or billing.
- Odoo connection per workspace in Connections (login checked before saving).
- provision-tenants.sh marks agency containers with QUORLA_HOSTED_TENANT=true.
- docs/wildcard-subdomains.html: one-time setup for automatic agency subdomains.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
commentThreads.list rejects youtube.readonly ("insufficient authentication
scopes"); it needs youtube.force-ssl, which we don't want to request.
Public comments are now read with YOUTUBE_API_KEY. Also records the
re-submitted Google verification (video v2, new scope justification).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Control centre (QUORLA_CONTROL=true on app.quorlasocial.com): public /signup → Stripe Checkout,
verified Stripe webhook (paid, updated, cancelled, payment failed), Admin → Agencies
(approve without Stripe, suspend, resume, billing portal, resend welcome, remove)
- deploy/provision-tenants.sh (cron): one container per agency with its own .env and data,
nginx map for <agency>.quorlasocial.com, upgrades agencies after a rebuild, archives removed data
- New workspaces: first admin only via the emailed one-time setup link (SETUP_TOKEN)
- Meta system user token can be saved in Settings (encrypted) for workspaces that can't edit .env
- docs/multi-tenant.md: DNS, wildcard cert, nginx, sudoers, cron, Stripe setup; tests for the control centre
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Public page /l/<address>: Instagram name, picture and bio (or custom), link buttons, latest 6 posts
- Every click counted per link per day through /l/<address>/go/<id>; optional UTM tags for Google Analytics
- Client page → Link in bio: address, links (reorder with buttons), colours, clicks in the last 30 days
- Snapshots now keep the Instagram profile picture
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Client page → Brand kit: hashtag sets, approved phrases/CTAs, words to avoid, voice notes
- New post: one-click insert of hashtag sets and phrases, live checks while typing
- Checks: agency named in a client post (refused when saving; the agency's own account is exempt),
avoid list, generic AI-sounding phrases, too many hashtags or emoji, platform length limits
- Brand warnings also appear on drafts; MCP tools brand_kit and caption_check for the AI
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Inbox tabs: Instagram & Facebook / Google reviews / YouTube comments
- Google reviews: average rating, needs-reply filter, reply or edit reply (public on Google), only on the client's location
- YouTube comments: latest on the channel, open the comment to reply on YouTube (reply needs a broader scope)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Assigning a plan item notifies the person (bell + email); team names offered when assigning
- Optional Odoo task from a calendar card (project + assignee, deadline = post date, brief in the task)
- Library upload can pick its calendar item: inherits date and Odoo task, card moves to 'in production'
- Approving the upload moves the card to 'ready'; changes requested notify the uploader
- Calendar shows the uploaded work in place of its plan card (no duplicates)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- In-app list with unread count; per-person email and 8:00 summary settings
- Team is told when a client approves or asks for changes, a post fails or only partly publishes,
or a TikTok post is waiting in the TikTok app; new drafts appear in the bell and the summary
- Clients get one email (batched over 5 minutes) when posts are sent to them, in the agency's name
- SMTP settings in .env; nodemailer pinned; express advisories fixed (npm audit: 0)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Admin creates/replaces/turns off the link and sets the reviewer on the client page (Client approval tab)
- Drafts get 'Send to client'; the client's answer (approved / changes + note + name) shows on the draft
- Editing a reviewed draft asks the client again; the admin's approval is still required to publish
- Client page is mobile-first, no login, noindex, media served only for posts in review
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Add/remove competitor handles (public Business/Creator accounts); refreshed nightly, one snapshot a day
- Compare with the client: followers, 30-day change, trend, posts/week, typical post (median), engagement rate, format mix
- Engagement-rate chart and each competitor's top recent posts
- MCP tools competitors and competitor_add (audits can add the AI's suggestions)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Plan items (idea → brief → production → ready) with brief, caption, platforms, assignee, pillar
- Calendar merges plan items, library items with a target date and queued/published posts
- Month and week views, drag a card to another day (or change the date in the card), add from any day
- MCP tools content_plan, plan_add, plan_update; weekly-plan skill now fills the calendar
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Feed merges Instagram/Facebook snapshot posts (with insights) and everything Quorla published
- Filters (client, platform, 7/30/90 days), sort by interactions/reach/views, via-Quorla badge
- YouTube view/like/comment counts fetched nightly and on demand (1 quota unit per 50 videos)
- Snapshots now keep post thumbnails (IG media/thumbnail url, FB full_picture)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Direct Post from an unaudited app only works for private accounts. Inbox upload lets a
person finish and post from the TikTok app.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Publishing: admins can retry a failed or partly published post; parts that already posted are skipped
- API errors now include the platform's error code, with plain fixes for common TikTok ones
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Quorla logo, navy/coral colours and page titles in the app (PDF reports keep agency branding)
- Connections: Move button reassigns an account to another client without reconnecting
- Fix double @ on YouTube handles
- HANDOFF.md with current status and next steps
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- quota.js: per-platform limits (YouTube 10,000 units/day Pacific per project,
Instagram 100 / Threads 250 / TikTok 15 posts per 24 h per account, ...),
usage log, .env overrides (QUOTA_<PLATFORM>)
- Publishing checks the budget first and records usage; when a platform is
out of quota (or answers quota exceeded / 429) the post stays approved and
the queue retries after the reset, without re-posting finished platforms
- Drafts that exceed a day's limit get a warning
- Connections page shows used/limit and when it frees up
- Tests for windows (incl. DST), shared vs per-account limits and the
wait-and-retry queue flow; docs for quotas and the Google app setup
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Public /privacy and /terms pages (Quorla, operated by Metatroncube
Software Solutions) for platform app listings; includes Google API
Limited Use statement and TikTok data use
- TikTok post panel follows the Content Posting API guidelines: shows the
creator's name/avatar, audience options from creator info with no
default, comment/Duet/Stitch off by default and locked when the creator
disabled them, max video length, commercial content disclosure (Your
brand / Branded content, branded content can't be private), Music Usage
Confirmation / Branded Content Policy consent
- Placeholder app icon (branding/quorla-icon-1024.png)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Connections page: admins set up each platform's developer app (keys stored
encrypted), connect a client's account via OAuth, choose company Page /
business location, check or disconnect
- Adapters per platform with sign-in, identity, targets and publishing;
token refresh with "reconnect needed" when a sign-in expires
- Publishing and Content library: "Post to" lists the client's connected
platforms with their own fields and optional per-platform caption
- Queue validates drafts per platform and publishes through the adapters;
Facebook/Instagram unchanged
- Signed, expiring media links (/m/...) for platforms that fetch media by URL
- Agent: list_connections tool; schedule tools accept all platforms + options
- Offline test suite with simulated platform APIs (15 tests)
- docs/platforms.md: setup, approvals per platform, what is and isn't tested
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Connector lists Instagram accounts assigned to the system user without a
Page; numbers, inbox, mentions and publishing work for them
- Clients link by Page or Instagram account ("Link an account"); Facebook
features explain the client has no Page instead of failing
- Drafts for Instagram-only clients drop Facebook automatically
- Images for Instagram-only clients are hosted via the agency's own Page
(META_MEDIA_PAGE_ID, unpublished); never falls back to a client's Page
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Dashboard (content library, publishing queue with approvals, inbox, team
management, AI runs), Meta connector, branded PDF reports, agent skills,
and Docker packaging (Dockerfile, docker-compose with Caddy HTTPS,
backup and path-relocation scripts).
Client data, live data and secrets are excluded via .gitignore.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>