An AI-powered LinkedIn distribution engine. Turn articles, launches, and hackathon recaps into on-brand LinkedIn posts, approve them, publish to a personal profile or company page, and pull performance back into a dashboard.

Stack: Next.js 16 (App Router) · Convex (data + functions + scheduler) · shadcn/ui + Tailwind v4 · OpenRouter Agent SDK · LinkedIn OAuth 2.0 + Posts API.

Dashboard — impressions, engagement, performance chart, recent posts, and activity.

Post performance — per-post metrics synced from the LinkedIn API.

Posts & schedule — manage drafts, approvals, scheduled, and published content.

New article / project / hackathon

AI generates a LinkedIn post (OpenRouter)

Your approval

LinkedIn API (personal or company page)

Published + performance synced back

- Content sources — store articles, projects, hackathons, and resources.

- AI composer — generate drafts from a source with your brand voice.

- Approval queue — review and edit before anything goes live.

- Scheduling — schedule posts; a Convex cron publishes them.

- Publishing — personal (w_member_social) and company page (w_organization_social) posts.

- Analytics — best-effort impressions/engagement synced from LinkedIn.

- Activity feed — audit trail of everything that happened.

npm install

npx convex dev # provisions/uses your dev deployment, writes .env.localLeave npx convex dev running in a terminal while developing.

Server-side secrets are stored on the Convex deployment (not in .env.local):

npx convex env set LINKEDIN_CLIENT_ID <your-client-id>

npx convex env set LINKEDIN_CLIENT_SECRET <your-client-secret>

npx convex env set OPENROUTER_API_KEY <your-openrouter-key>

npx convex env set APP_URL http://localhost:3000Optional overrides:

npx convex env set LINKEDIN_SCOPES "openid profile email w_member_social w_organization_social r_organization_social"

npx convex env set LINKEDIN_VERSION 202609

npx convex env set LINKEDIN_REDIRECT_URI https://<deployment>.convex.site/linkedin/callback

npx convex env set OPENROUTER_MODEL openai/gpt-4o-miniIn your LinkedIn developer app, add this Authorized redirect URL (Auth tab):

https://<your-deployment>.convex.site/linkedin/callback

Request the products you need (Sign In with LinkedIn using OpenID Connect, Share on LinkedIn, and Marketing Developer Platform for company pages/analytics).

npm run devOpen http://localhost:3000, go to LinkedIn → Connect, then create your first post in the Composer.

Populate the dashboard with realistic data for screenshots or demos. Everything

is tagged demo: true and never touches your real account or posts.

npx convex run seed:seedAll # reset + seed 2,400 posts

npx convex run seed:seedAll '{"total":5000}' # seed 5,000 posts

npx convex run seed:clearDemoData # remove all demo data- npm run dev— Next.js dev server

- npm run build— production build

- npm run lint— ESLint

- npm run typecheck— TypeScript

- npx convex dev --once— push backend changes once

- convex/schema.ts— tables: accounts, sources, posts, activities, settings.

- convex/http.ts— LinkedIn OAuth- /linkedin/connectand- /linkedin/callback.

- convex/linkedin.ts— publish, metrics sync, org refresh, version probing.

- convex/ai.ts— OpenRouter generation (- "use node").

- convex/crons.ts— publish scheduled posts (1 min) and sync metrics (6 h).

- convex/seed.ts— demo data seeding.

- app/dashboard/*— dashboard, composer, sources, approvals, posts, analytics, LinkedIn, settings.

- Impressions are only exposed for company page posts. Personal posts show

likes/comments unless the restricted r_member_socialscope is approved.

- Historical personal posts can't be imported without r_member_social; every post published through this app is stored in Convex with its metrics.

- LinkedIn API versions expire monthly. LINKEDIN_VERSIONdefaults to202609.