3 of your GitHub stars, resurfaced in your inbox every week.
Most developers star GitHub repos and never look at them again. re:starred resurfaces those forgotten stars as a weekly email digest — 3 of your starred repos per week, cycling through your entire list before repeating. No repo is shown twice until you've seen them all.
- Connect GitHub — sign in with GitHub OAuth, we index your starred repos
- Weekly digest — every week, our algorithm picks 3 repos you starred and forgot about
- Re-engage — read the summary, check recent activity, decide if it stays or gets archived
I built re:starred to help developers rediscover the GitHub repos they once thought were worth remembering. It's free forever, open source, and has no ads. Every digest costs a fraction of a penny to send, but it adds up. If you've found a gem in your inbox, consider buying me a coffee to keep the emails flowing.
- Runtime: Bun
- Database: PostgreSQL via
Bun.SQL(no ORM) - Auth: GitHub OAuth with secure session management
- Email: Transactional email via Resend
- Templating: Server-rendered JSX (not React — no client-side hydration)
- Styling: Hand-written CSS with custom properties, no Tailwind
- Fonts: Space Grotesk, Inter, JetBrains Mono (Google Fonts)
- Hosting: Railway
You'll need Bun and a local PostgreSQL instance running.
bun install
cp .env.example .env # fill in your credentials
bun run devVisit http://localhost:3000 — migrations run automatically on startup.
| Variable | Required | Description |
|---|---|---|
DATABASE_URL |
Yes | PostgreSQL connection string |
CRYPTO_PEPPER |
Yes | Secret key for session tokens — run bun run generate:pepper |
APP_URL |
Yes | Public URL (e.g. https://restarred.dev) |
GITHUB_CLIENT_ID |
Yes | GitHub OAuth app client ID |
GITHUB_CLIENT_SECRET |
Yes | GitHub OAuth app client secret |
GITHUB_CALLBACK_URL |
Yes | OAuth callback URL (e.g. http://localhost:3000/auth/callback) |
EMAIL_PROVIDER_API_KEY |
Yes | Resend API key for sending digests |
EMAIL_FROM_ADDRESS |
Yes | Sender address for digest emails |
ENCRYPTION_KEY |
Yes | Key for encrypting GitHub tokens at rest |
PORT |
No | Server port — defaults to 3000 |
bun run dev # Start dev server with hot reload
bun run test # Run full test suite (238 tests)
bun run check # Lint + typecheck (zero warnings enforced)
bun run migrate:status # Show migration state
bun run migrate:create # Create a new migration file- Biome linting with
--max-warnings 0— noanytypes, noconsolestatements - TypeScript strict mode
- Husky pre-commit hooks run lint and typecheck before every commit
- Structured logging via
log.info()/log.warn()/log.error()— noconsole.*
Tests run against a real PostgreSQL database (configured via .env.test). No mocking the DB layer.
bun run test # all tests
bun run test:file src/server/services/... # single filesrc/
├── client/ # Browser-side code
│ ├── main.ts # Entry point — routes to page init functions
│ ├── style.css # Global styles + CSS imports
│ ├── components/ # Shared component CSS
│ └── pages/ # Page-specific JS + CSS (co-located)
│
├── server/
│ ├── main.ts # Server entry point
│ ├── routes/ # URL → controller mapping
│ ├── controllers/ # Request handlers (app/, api/, auth/)
│ ├── templates/ # Full-page JSX templates
│ ├── components/ # Reusable server JSX components
│ ├── services/ # Business logic & data access
│ ├── middleware/ # Auth, CSRF, rate limiting
│ ├── utils/ # Response helpers, crypto
│ └── database/ # Migrations + CLI
│
└── types/ # Global TypeScript declarations
Single Bun process — no containers, no serverless adapters. Anywhere you can run bun run start, it works.
A railway.json is included with build and start commands pre-configured.
- Push to GitHub
- Create a new Railway project and connect your repo
- Add a PostgreSQL plugin — this auto-sets
DATABASE_URL - Set the remaining environment variables
- Deploy — migrations run automatically on startup
MIT