{"id":50886569,"url":"https://github.com/notsoocool/worktowords","last_synced_at":"2026-06-15T17:32:21.261Z","repository":{"id":351074495,"uuid":"1209433114","full_name":"notsoocool/worktowords","owner":"notsoocool","description":"✍️ Turn daily work into posts with AI (Clerk auth + Supabase history + settings).","archived":false,"fork":false,"pushed_at":"2026-05-19T19:04:39.000Z","size":1574,"stargazers_count":2,"open_issues_count":13,"forks_count":4,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-19T22:07:35.836Z","etag":null,"topics":["clerk","linkedin","nextjs","openai","react","saas","shadcn-ui","supabase","tailwindcss","typescript"],"latest_commit_sha":null,"homepage":"https://worktowords.in","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/notsoocool.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-04-13T12:27:29.000Z","updated_at":"2026-05-19T18:52:24.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/notsoocool/worktowords","commit_stats":null,"previous_names":["notsoocool/worktowords"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/notsoocool/worktowords","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/notsoocool%2Fworktowords","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/notsoocool%2Fworktowords/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/notsoocool%2Fworktowords/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/notsoocool%2Fworktowords/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/notsoocool","download_url":"https://codeload.github.com/notsoocool/worktowords/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/notsoocool%2Fworktowords/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34374146,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-15T02:00:07.085Z","response_time":63,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["clerk","linkedin","nextjs","openai","react","saas","shadcn-ui","supabase","tailwindcss","typescript"],"created_at":"2026-06-15T17:32:19.424Z","updated_at":"2026-06-15T17:32:21.251Z","avatar_url":"https://github.com/notsoocool.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ✍️ WorktoWords\n\nTurn your daily work into **social-ready content** — LinkedIn posts, Instagram captions, and YouTube scripts — fast, clean, and on-brand.\n\n## ✨ Features\n\n- 🔐 **Auth** with [Clerk](https://clerk.com) (Google sign-in supported)\n- 🧠 **AI generation** via OpenAI — **Help Me Write** and **Write For Me** modes\n- 📱 **Multi-platform output** — LinkedIn, Instagram, and YouTube (select one or more per run)\n- 🎯 **Goals** — `job` · `growth` · `authority` (per post or default in settings)\n- 💳 **Pro upgrade** via Razorpay (₹149 / 30 days, UPI-friendly checkout)\n- 📅 **Pro expiry** — auto-downgrades to Free after 30 days\n- 📊 **Usage limits**\n  - Free: **5** generations/day\n  - Pro: **100** generations/day\n- 🧾 **History** — saved posts, filter by goal, reopen on the dashboard\n- ⚙️ **Settings** — default goal + tone (`casual` · `professional` · `storytelling`)\n- 🎛️ **Regenerate** — per-platform refresh; adjust length, tone, technical level, storytelling\n- 🔔 **Live toasts** during generation\n- 🌓 **Light / dark** theme\n\n## 🧰 Tech Stack\n\n- **Next.js 16** (App Router) + **TypeScript**\n- **Tailwind CSS** + **shadcn/ui**\n- **Clerk** — authentication\n- **Supabase Postgres** — posts, settings, usage, subscriptions\n- **OpenAI** — content generation\n- **Razorpay** — payments\n\n## ✅ Prerequisites\n\n- **Node.js 20+**\n- **pnpm 9+**\n\n## 🚀 Getting Started\n\n```bash\ngit clone https://github.com/notsoocool/worktowords.git\ncd worktowords\npnpm install\n```\n\nCreate `.env.local`:\n\n```bash\n# Clerk\nNEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=\nCLERK_SECRET_KEY=\n\n# OpenAI\nOPENAI_API_KEY=\n\n# Supabase (server routes use the service role key)\nNEXT_PUBLIC_SUPABASE_URL=\nNEXT_PUBLIC_SUPABASE_ANON_KEY=\nSUPABASE_SERVICE_ROLE_KEY=\n\n# Razorpay — use test keys locally\nNEXT_PUBLIC_RAZORPAY_KEY_ID=\nRAZORPAY_KEY_ID=\nRAZORPAY_KEY_SECRET=\n```\n\nOptional:\n\n```bash\n# Bypass daily limits for admin/testing (comma-separated Clerk user IDs)\nROOT_USER_ID=\n# ROOT_USER_IDS=\n\n# Custom Clerk domains (production)\n# NEXT_PUBLIC_CLERK_FRONTEND_API=\n# NEXT_PUBLIC_CLERK_ACCOUNTS_ORIGIN=\n```\n\n### Database\n\nIn the [Supabase](https://supabase.com) SQL editor, run the full schema:\n\n```text\nsupabase/posts.sql\n```\n\nThis creates tables, indexes, RLS policies, and `check_and_increment_usage()` (required for generation limits).\n\n### Run locally\n\n```bash\npnpm dev\n```\n\nOpen [http://localhost:3000](http://localhost:3000).\n\n### Scripts\n\n| Command | Description |\n|---------|-------------|\n| `pnpm dev` | Development server |\n| `pnpm build` | Production build |\n| `pnpm start` | Run production build |\n| `pnpm lint` | ESLint |\n| `pnpm typecheck` | TypeScript (`tsc --noEmit`) |\n\n## 🗄️ Database (Supabase)\n\n| Table | Purpose |\n|-------|---------|\n| `posts` | Generated content (`content`, `hashtags`, `goal`, `type`, `linkedin`, `instagram`, `youtube`) |\n| `user_settings` | Default goal + writing tone |\n| `user_usage` | Daily usage, plan, expiry |\n| `user_subscriptions` | Razorpay order/payment refs, plan status |\n\n**Function:** `check_and_increment_usage(user_id)` — atomic daily limit check + Pro expiry downgrade.\n\n## 🔌 API Routes\n\n| Method | Route | Description |\n|--------|-------|-------------|\n| `GET` | `/api/health` | Liveness check |\n| `POST` | `/api/generate` | Generate + save post(s) |\n| `GET` | `/api/posts` | List history (`?goal=` optional) |\n| `GET` | `/api/posts/[id]` | Single post |\n| `GET` | `/api/settings` | User settings |\n| `PATCH` | `/api/settings` | Update settings |\n| `GET` | `/api/usage` | Remaining generations + plan |\n| `POST` | `/api/razorpay/create-order` | Create Pro order (₹149) |\n| `POST` | `/api/razorpay/verify` | Verify payment + activate Pro |\n\n## 💳 Razorpay (Standard Checkout)\n\nFlow ([Razorpay docs](https://razorpay.com/docs/payments/payment-gateway/web-integration/standard/integration-steps/)):\n\n1. **Server** — `POST /api/razorpay/create-order` creates an order (14900 paise, INR) and stores a pending row in `user_subscriptions`.\n2. **Client** — Opens Checkout with `key`, `order_id`, `amount`, `currency`, `prefill`.\n3. **Success** — Client receives `razorpay_payment_id`, `razorpay_order_id`, `razorpay_signature`.\n4. **Server** — `POST /api/razorpay/verify` validates the signature and upgrades the user to Pro for 30 days.\n\nUse **test** keys in development; **live** keys in production. Enable **automatic capture** for orders in the Razorpay Dashboard.\n\n## 🚢 Deployment\n\nSet the same environment variables on your host (e.g. Vercel). **Required for core features:**\n\n- Clerk keys\n- `OPENAI_API_KEY`\n- `NEXT_PUBLIC_SUPABASE_URL` + `SUPABASE_SERVICE_ROLE_KEY` (usage, posts, payments)\n- Razorpay keys\n\nAfter deploy:\n\n1. Confirm `supabase/posts.sql` has been applied to your production project.\n2. Hit `GET /api/health` to confirm the app is up.\n3. Run a test generation and (optionally) a Razorpay test checkout.\n\n## 🤝 Contributing\n\nWe welcome contributions — especially for [open issues](https://github.com/notsoocool/worktowords/issues).\n\n- Read **[CONTRIBUTING.md](./CONTRIBUTING.md)** for setup, conventions, and PR expectations.\n- Every PR runs **lint**, **typecheck**, and **build** in GitHub Actions.\n- Comment on an issue before starting large changes.\n\n## 📁 Project layout\n\n```text\napp/              Pages and API routes\ncomponents/       UI (dashboard, history, settings, …)\nlib/services/     Business logic (generate, payments, usage, posts)\nlib/ai/           Platform-specific AI prompts (LinkedIn, Instagram, YouTube)\nsupabase/         SQL schema\nproxy.ts          Auth (Clerk) + security headers\n```\n\n## 🧪 Notes\n\n- Secrets live in `.env.local` (gitignored).\n- `/dashboard`, `/history`, and `/settings` require sign-in (Clerk).\n- Server-side Supabase access uses the **service role** key — never expose it to the client.\n\n## 📄 License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnotsoocool%2Fworktowords","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnotsoocool%2Fworktowords","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnotsoocool%2Fworktowords/lists"}