Turn your shipped work into LinkedIn posts.
▶ Live demo — loudship.vercel.app
Loudship reads what you built on GitHub (merged PRs, releases, new projects, recent commits) and drafts LinkedIn posts in your voice. It's for developers who'd rather ship than self-promote: introverts, non-native English speakers, anyone who knows they should post but freezes on the empty box.
What it does:
- Connect GitHub to pull your real work: merged PRs, releases, projects, and commits.
- Connect LinkedIn (optional) so posts sound more like you. It only reads your profile. Loudship never posts for you.
- Bring your own AI key (Anthropic or OpenAI). The key stays in your browser and goes straight to the provider. Loudship's server never sees it.
- Tune each post: tone, length, three variations per run, plus humble, emoji, and hashtag toggles.
- Pick a creator style to write in the spirit of a well-known LinkedIn voice. This emulates the writing style only. Loudship is not affiliated with or endorsed by any named creator, and the avatars are generated illustrations.
# 1. Install dependencies.
# This drive is exFAT, which can't create symlinks, so skip bin-links.
npm install --no-bin-links
# 2. (optional) Set up the connectors. See "OAuth setup" below.
cp .env.example .env.local # then fill in the client IDs and secrets
# 3. Run it.
npm run dev
# http://localhost:3000Then open the app, click Settings, pick your AI provider, paste your API key, and connect GitHub.
The app boots fine without any .env.local. The connector buttons stay disabled and the UI says they aren't configured, which is handy if you just want to look around. You still need your own AI key (in Settings) to generate posts.
Both connectors are optional. Set up whichever you want. The callback URLs below assume http://localhost:3000.
- Open GitHub Settings, then Developer settings, then OAuth Apps, then New OAuth App (https://github.com/settings/developers).
- Set:
- Homepage URL:
http://localhost:3000 - Authorization callback URL:
http://localhost:3000/api/auth/github/callback
- Homepage URL:
- Copy the Client ID and generate a Client secret into
.env.local:Requested scopes:GITHUB_CLIENT_ID=... GITHUB_CLIENT_SECRET=...read:user repo.
- Open LinkedIn Developers and create an app (https://www.linkedin.com/developers/apps).
- Add the "Sign In with LinkedIn using OpenID Connect" product.
- Under Auth, add the redirect URL:
http://localhost:3000/api/auth/linkedin/callback. - Copy the Client ID and Primary Client Secret into
.env.local:Requested scopes:LINKEDIN_CLIENT_ID=... LINKEDIN_CLIENT_SECRET=...openid profile email. This is read-only. There's no posting permission.
After editing .env.local, restart npm run dev.
You register the OAuth apps once; your users just click Connect. To deploy:
- Push the repo and import it on Vercel.
- Set the OAuth env vars in the Vercel project (Settings, then Environment Variables):
GITHUB_CLIENT_ID,GITHUB_CLIENT_SECRET,LINKEDIN_CLIENT_ID,LINKEDIN_CLIENT_SECRET. The AI key is not set here; each user enters their own in the app. - Add the production callback URLs to the GitHub and LinkedIn apps:
https://<your-domain>/api/auth/github/callbackhttps://<your-domain>/api/auth/linkedin/callback
The public origin is resolved automatically: on Vercel it uses the production domain, so OAuth works on your-app.vercel.app with no extra config. Set APP_URL=https://<your-domain> if you use a custom domain, or GITHUB_REDIRECT_URI / LINKEDIN_REDIRECT_URI to pin a provider's callback exactly.
Your AI API key is entered in Settings, kept in localStorage, and sent straight from your browser to Anthropic or OpenAI (dangerouslyAllowBrowser). It's never transmitted to or logged by the Loudship server.
GitHub and LinkedIn access tokens are stored in httpOnly cookies on your own machine. The local API routes use them to read your activity. A short-lived state cookie guards against CSRF.
There's no database. This is a single-user local app. The auth layer is structured so you could later swap it for Auth.js plus a database to make it multi-user without touching the UI, but that isn't part of this build.
LinkedIn access is read-only. Loudship drafts; you copy and post. It never publishes anything for you.
This drive is exFAT, which doesn't support symlinks, so the scripts call the Next.js binary directly instead of relying on node_modules/.bin:
| Command | What it does |
|---|---|
npm run dev |
Start the dev server on :3000 |
npm run build |
Production build |
npm run start |
Serve the production build |
npm run lint |
Run ESLint |
If you reinstall dependencies, use npm install --no-bin-links.
Next.js 16 (App Router), React 19, TypeScript, Tailwind CSS v4, the @anthropic-ai/sdk and openai SDKs (browser-side), and hand-rolled GitHub and LinkedIn OAuth. The component look follows the shadcn/Tailwind ("21st.dev") style on a dark "beacon" palette.
src/
app/
page.tsx the workspace (feed, composer, settings)
layout.tsx, globals.css shell and design system
api/
connections/ GET current connection status
github/activity/ GET the normalized "shipped work" feed
auth/{github,linkedin}/ OAuth start, callback, and disconnect
components/ Header, WorkFeed, Generator, DraftCard, and so on
lib/ types, store (localStorage), llm, prompt, oauth, github
