Skip to content

Peleke/linwheel

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

LinWheel

Turn Any Content Into a Month of LinkedIn Posts

Next.js TypeScript Claude Flux.1 LinkedIn

90+ posts. 6 angles. AI cover images. Direct LinkedIn publishing. Under 60 seconds.

Get Started Β· Features Β· Architecture Β· Roadmap


The Problem

You just recorded an amazing podcast. Or finished a book chapter. Or came out of a conference with pages of notes. Great insights are trapped in your contentβ€”but getting them onto LinkedIn?

That's 4-6 hours of manual work:

  • Reading through transcripts hunting for quotable moments
  • Rewriting the same insight in different styles
  • Staring at Canva trying to make images
  • Posting once and hoping the algorithm notices

Most creators give up. The insights die in a Google Doc.

The Solution

LinWheel is a multi-agent AI system that extracts insights from any content and transforms them into a complete LinkedIn content engine:

Podcast transcript  β†’  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
Book chapter        β†’  β”‚                                      β”‚
Research paper      β†’  β”‚   90+ LinkedIn posts                 β”‚
Meeting notes       β†’  β”‚   + AI-generated cover images        β”‚
Conference talk     β†’  β”‚   + 5-slide carousels               β”‚
White paper         β†’  β”‚   + Long-form articles               β”‚
Interview           β†’  β”‚                                      β”‚
                       β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Paste your content. Select your angles. Get a month of scroll-stopping content.


✨ Features

πŸš€ Direct LinkedIn Publishing

Zero friction from creation to posted. Connect your LinkedIn account and publish approved posts instantlyβ€”no copy-paste, no switching apps.

  • One-click connect β€” OAuth integration with LinkedIn
  • Instant publishing β€” Approve a post, click Publish, done
  • Image support β€” AI-generated cover images publish with your post
  • Published tracking β€” See which posts are live with direct links
  • Secure tokens β€” AES-256-GCM encryption for your credentials

Coming soon: Scheduled publishing β€” set it and forget it.

🎭 Six Distinct Content Angles

Every insight gets rewritten in 6 different voicesβ€”each optimized for a specific LinkedIn engagement pattern:

Angle Strategy Hook Style
Contrarian Challenge the consensus "Everyone's wrong about AI. Here's why."
Field Note Share firsthand observations "Spent 6 months testing this. Here's what I found."
Demystify Strip glamour from sacred cows "The 'overnight success' story nobody tells you."
Identity Make outliers feel seen "If you've ever felt like a fraud at work..."
Provocateur Stir debate with edge "Hot take: Your KPIs are lying to you."
Synthesizer Connect dots across domains "What jazz improv teaches us about hiring."
Curious Cat Lead with questions "What if everything you know about productivity is wrong?"

5 versions per angle Γ— 6 angles Γ— 3+ insights = 90+ unique posts

πŸ–ΌοΈ AI-Generated Cover Images

Every post includes a custom cover image generated by Flux.1:

  • One-click generation β€” Click "Generate" on any post
  • Smart prompts β€” AI-crafted prompts optimized for engagement
  • Regenerate anytime β€” Not happy? Generate a new version instantly
  • Mobile-ready downloads β€” Download images directly to your phone

πŸ“‘ 5-Slide Carousels

Turn any article into LinkedIn's algorithm-favorite format:

  • Automatic slide breakdown β€” AI structures content for carousel flow
  • Per-slide image generation β€” Each slide gets a unique visual
  • Version history β€” Regenerate individual slides without losing others
  • One-tap download β€” Get the full carousel as individual images

πŸ“ Long-Form Articles

Not just postsβ€”full 500-750 word articles in 4 formats:

Type Best For
Deep Dive Comprehensive exploration of a topic
Contrarian Challenging conventional wisdom at length
How-To Step-by-step guides and tutorials
Case Study Real-world examples and lessons

πŸŽ™οΈ Voice Profiles

Train LinWheel on your writing style:

  • Add samples β€” Paste examples of your best posts
  • Style matching β€” Generated content matches your voice
  • One active profile β€” Switch between different personas

⚑ Progressive Web App

Install LinWheel on any device:

  • iOS Safari β€” Add to Home Screen for native-like experience
  • Android/Chrome β€” Install prompt with one tap
  • Offline support β€” Review content without internet
  • No app store β€” Direct access, no gatekeepers

πŸ†š Why LinWheel?

Manual Workflow LinWheel
Time per episode 4-6 hours < 60 seconds
Posts generated 3-5 90+
Content angles 1 (your default voice) 6 distinct perspectives
Cover images DIY in Canva AI-generated, one click
Carousels Hours of design work Automatic, per-slide images
Publishing Copy-paste to LinkedIn One-click direct publish
Consistency Varies by energy level Same quality every time

πŸ–ΌοΈ Screenshots

Landing Page Generate Interface Results Dashboard
High-energy landing with parallax effects Paste any content, select angles Browse, approve, and export
Post Card Carousel View Image Generation
Each post with AI cover image 5-slide carousel with versions One-click Flux.1 generation

Part II: Technical Documentation

For engineers, contributors, and the curious


πŸ—οΈ Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                         Client (PWA)                             β”‚
β”‚         Next.js 16 Β· React 19 Β· TypeScript Β· Tailwind v4        β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                              β”‚
                              β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                      API Layer (Next.js)                         β”‚
β”‚         LangChain Β· Claude AI Β· Streaming Responses              β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
           β”‚                  β”‚                  β”‚
           β–Ό                  β–Ό                  β–Ό
    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚  Supabase   β”‚    β”‚  Anthropic  β”‚    β”‚    fal.ai   β”‚
    β”‚  Auth +     β”‚    β”‚   Claude    β”‚    β”‚   Flux.1    β”‚
    β”‚  Storage    β”‚    β”‚   3.5/4     β”‚    β”‚   Images    β”‚
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
           β”‚
           β–Ό
    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚           Turso (LibSQL)            β”‚
    β”‚     Edge-optimized SQLite           β”‚
    β”‚     Drizzle ORM Β· Type-safe         β”‚
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Tech Stack

Layer Technology Why
Frontend Next.js 16, React 19, TypeScript App Router, RSC, Turbopack
Styling Tailwind CSS v4 Utility-first, CSS variables
Database Turso (LibSQL) + Drizzle ORM Edge-optimized, type-safe
Auth Supabase Auth Social login, RLS
AI/LLM Claude (Anthropic) via LangChain Best-in-class reasoning
Image Gen Flux.1 via fal.ai Fast, high-quality, cheap
PWA next-pwa Installable, offline support

Multi-Agent Pipeline

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    Content Input (Any Format)                    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                              β”‚
                              β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                   Chunker Agent                                  β”‚
β”‚   Splits content at semantic boundaries (4000 token chunks)      β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                              β”‚
                              β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                  Extractor Agent                                 β”‚
β”‚   Finds non-obvious claims, "I've felt this" moments             β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                              β”‚
                              β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                   Deduper Agent                                  β”‚
β”‚   Filters overlapping insights, maximizes variety                β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                              β”‚
        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
        β”‚                     β”‚                     β”‚
        β–Ό                     β–Ό                     β–Ό
  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
  β”‚ Writer    β”‚         β”‚ Writer    β”‚         β”‚ Writer    β”‚
  β”‚ Contrarianβ”‚         β”‚ Field Noteβ”‚         β”‚ ...Γ—6     β”‚
  β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜         β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜         β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜
        β”‚                     β”‚                     β”‚
        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                              β”‚
                              β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                  Image Intent Agent                              β”‚
β”‚   Generates Flux-optimized prompts for each post                 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

The Writer Supervisor uses RunnableParallel for concurrent generation:

const writerChain = RunnableParallel.from({
  contrarian: contrarianWriter,
  field_note: fieldNoteWriter,
  demystify: demystifyWriter,
  identity: identityWriter,
  provocateur: provocateurWriter,
  synthesizer: synthesizerWriter,
  curious_cat: curiousCatWriter,
});

// All 6 angles generate simultaneously
const results = await writerChain.invoke({ insight, voiceProfile });

πŸš€ Quick Start

Prerequisites

  • Node.js 20+
  • Anthropic API key (Claude)
  • fal.ai API key (Flux.1)
  • Supabase project (auth)
  • Turso database (or local SQLite)

Installation

# Clone the repository
git clone https://github.com/Peleke/linwheel.git
cd linwheel

# Install dependencies
npm install

# Set up environment
cp .env.example .env.local

Environment Configuration

# .env.local

# AI Providers (Required)
ANTHROPIC_API_KEY=your-anthropic-key      # Claude for text generation
FAL_KEY=your-fal-key                       # Flux.1 for image generation

# LinkedIn Integration (Required for publishing)
LINKEDIN_CLIENT_ID=your-linkedin-app-id   # From LinkedIn Developer Portal
LINKEDIN_CLIENT_SECRET=your-secret        # From LinkedIn Developer Portal
TOKEN_ENCRYPTION_KEY=64-char-hex-key      # For secure token storage

# Supabase Auth
NEXT_PUBLIC_SUPABASE_URL=your-project-url
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key
SUPABASE_SERVICE_ROLE_KEY=your-service-key # For admin operations

# Database (Turso)
DATABASE_URL=libsql://your-db.turso.io
DATABASE_AUTH_TOKEN=your-token

# Stripe Billing
STRIPE_SECRET_KEY=sk_live_...              # or sk_test_ for dev
STRIPE_WEBHOOK_SECRET=whsec_...
STRIPE_PRO_MONTHLY_PRICE_ID=price_...
STRIPE_PRO_YEARLY_PRICE_ID=price_...       # Optional

# App URL (for Stripe redirects)
NEXT_PUBLIC_APP_URL=https://linwheel.ai    # Your production domain

Database Setup

# Generate migrations from schema
npm run db:generate

# Apply migrations
npm run db:push

Run Development Server

npm run dev

Open http://localhost:3000


πŸ“ Project Structure

linwheel/
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ app/                      # Next.js App Router
β”‚   β”‚   β”œβ”€β”€ api/                  # API routes
β”‚   β”‚   β”‚   β”œβ”€β”€ generate/         # Content generation pipeline
β”‚   β”‚   β”‚   β”œβ”€β”€ posts/            # Post CRUD + approval
β”‚   β”‚   β”‚   β”œβ”€β”€ articles/         # Article + carousel generation
β”‚   β”‚   β”‚   β”œβ”€β”€ runs/             # Generation run management
β”‚   β”‚   β”‚   β”œβ”€β”€ stripe/           # Billing (checkout, portal, webhook)
β”‚   β”‚   β”‚   └── voice-profiles/   # Voice profile CRUD
β”‚   β”‚   β”œβ”€β”€ generate/             # Input form page
β”‚   β”‚   β”œβ”€β”€ results/              # Results dashboard
β”‚   β”‚   β”œβ”€β”€ pricing/              # Pricing page
β”‚   β”‚   └── settings/             # User settings + subscription
β”‚   β”œβ”€β”€ components/
β”‚   β”‚   β”œβ”€β”€ landing/              # Landing page sections
β”‚   β”‚   β”œβ”€β”€ subscription/         # Subscription status component
β”‚   β”‚   β”œβ”€β”€ post-card.tsx         # Post display with image
β”‚   β”‚   └── article-card.tsx      # Article with carousel
β”‚   β”œβ”€β”€ db/
β”‚   β”‚   └── schema.ts             # Drizzle schema definitions
β”‚   └── lib/
β”‚       β”œβ”€β”€ llm/                  # LLM provider abstraction
β”‚       β”œβ”€β”€ t2i/                  # Text-to-image providers
β”‚       β”œβ”€β”€ stripe/               # Stripe client + helpers
β”‚       β”œβ”€β”€ prompts/              # System prompts for each angle
β”‚       └── usage.ts              # Usage tracking + gating
β”œβ”€β”€ public/
β”‚   └── promo/                    # AI-generated landing page images
β”œβ”€β”€ supabase/
β”‚   └── migrations/               # Supabase migrations
└── drizzle/                      # Drizzle migrations

πŸ§ͺ Commands

# Development
npm run dev              # Start dev server (Turbopack)
npm run build            # Production build
npm run lint             # ESLint

# Database
npm run db:generate      # Generate migrations from schema
npm run db:push          # Push schema to database
npm run db:studio        # Open Drizzle Studio

# Testing
npm run test:e2e         # Playwright E2E tests
npm run test:e2e:ui      # E2E with interactive UI
npm run test:e2e:headed  # E2E in visible browser

πŸ” Database Schema

Core Tables

Table Purpose
generation_runs Pipeline execution records
insights Extracted claims from content
linkedin_posts Generated posts (90+ per run)
articles Long-form content (500-750 words)
image_intents Post cover image prompts + URLs
article_image_intents Article cover images
article_carousel_intents Carousel metadata + pages
carousel_slide_versions Per-slide version history
voice_profiles User writing style samples

Key Relationships

generation_runs
  └── insights (1:many)
        └── linkedin_posts (1:many)
              └── image_intents (1:1)
        └── articles (1:many)
              └── article_image_intents (1:1)
              └── article_carousel_intents (1:1)
                    └── carousel_slide_versions (1:many)

🎨 Design Decisions

Why Claude over GPT-4?

Claude excels at maintaining consistent voice and following nuanced style guidelines. The 200K context window means we can include more samples for voice matching. Also: Claude is just better at writing LinkedIn content that doesn't sound like AI wrote it.

Why Flux.1 over DALL-E?

Speed and cost. Flux.1 via fal.ai generates images in 2-3 seconds at $0.03/image. DALL-E is 10-15 seconds at $0.04-0.08. For a product generating 90+ images per run, this adds up fast.

Why Turso over Supabase Postgres?

Edge latency. Turso's embedded replicas mean database queries run at the edge, cutting 50-100ms off every request. For a content generation app with lots of reads, this makes the UI feel instant.

Why 6 angles?

LinkedIn's algorithm rewards variety. Posting the same insight 6 different ways over 6 weeks looks like "fresh content" to the algorithm, not spam. Each angle targets a different psychological triggerβ€”FOMO (contrarian), social proof (field note), curiosity (demystify), belonging (identity), controversy (provocateur), intelligence (synthesizer).

Why carousels?

LinkedIn's data shows carousel posts get 3x more engagement than single images. The swipe interaction increases time-on-post, which the algorithm loves. Plus, they're harder to create manuallyβ€”so fewer people do themβ€”which means less competition.


πŸ“Š Performance

Metric Target Achieved
Full generation pipeline < 60s ~45s
Single image generation < 5s ~3s
Post approval (optimistic) < 100ms ~50ms
Initial page load < 2s ~1.2s

Cost per Generation Run

Service Cost
Claude (insight extraction) ~$0.05
Claude (90 posts) ~$0.15
Flux.1 (90 images) ~$2.70
Total ~$3/run

At 90 posts per run, that's $0.03 per post with image.


πŸ—ΊοΈ Roadmap

βœ… Shipped

  • Multi-angle post generation (7 angles Γ— 2 versions)
  • AI cover image generation (Flux.1 via FAL.ai)
  • Long-form articles (4 types: Deep Dive, Contrarian, How-To, Case Study)
  • Voice profiles for style matching
  • PWA with install prompt
  • Stripe subscription billing (Free tier + Pro @ $29/mo)
  • Usage gating with upgrade prompts
  • Supabase authentication
  • πŸš€ Direct LinkedIn Publishing β€” Connect account, publish with one click

🎨 Brand Style Profiles

Voice profiles, but for visuals

Your posts already match your voice. Soon your images will match your brand.

  • Upload brand guidelines, color palette, visual references
  • AI learns your aesthetic across all generated images
  • Consistent visual identity without a design team

πŸ”’ Self-Hosted / Private Cloud

Your content never leaves your servers

Swap in Ollama, local Stable Diffusion, or your own fine-tuned models.

  • Full air-gapped deployment option
  • Bring your own LLM (Claude, GPT, Llama, Mistral)
  • Custom T2I pipelines for compliance-heavy industries (healthcare, finance, gov)

πŸ“… Scheduled Publishing

Set it and forget it

βœ… Direct publishing is live! Scheduled auto-posting coming next.

  • βœ… Native LinkedIn API integration SHIPPED
  • Calendar view of scheduled posts
  • Automatic publishing at scheduled times
  • Optimal timing suggestions based on your audience

πŸ‘₯ Team & Agency Mode

One dashboard, infinite brands

Manage multiple clients/brands from a single workspace.

  • Per-client voice profiles + brand styles
  • Team member permissions & roles
  • Client approval workflows
  • White-label option for agencies

πŸ“Š Performance Analytics

Know what's working

Track which angles, topics, and image styles drive engagement.

  • Post performance tracking (impressions, engagement, clicks)
  • Angle effectiveness scoring
  • "More like this" regeneration based on winners

πŸ”Œ API Access

Plug LinWheel into your stack

Programmatic content generation for power users.

  • REST API for generation
  • Webhooks for completion events
  • Zapier/Make integration
  • Podcast RSS β†’ LinkedIn automation

πŸ“„ License

MIT License β€” see LICENSE for details.


Built for creators who'd rather ship ideas than fight with formatting.

One piece of content. A month of LinkedIn gold.

⬆ Back to top

About

Fan-out skeletons for LinkedIn posts.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •  

Languages