Every time I start a new project, the first week disappears into the same setup loop: wire up auth, connect a database, scaffold a mobile app, get CI passing, add an AI layer. It’s work that has nothing to do with the actual idea I’m trying to build. So after going through that loop one too many times while building Nerdious, I extracted the infrastructure into a reusable template — ShipKit.
Why I Created It
The honest answer is frustration. I had just finished migrating a Next.js project from Supabase to Neon, wired up Better Auth with Google OAuth and email resets via Resend, set up a Mastra agent with streaming chat, and gotten a 51-test CI pipeline green on GitHub Actions. That’s a lot of decisions made and a lot of bugs debugged. The thought of doing it again from scratch on the next project was not appealing.
I also wanted a template that reflected how I actually work in 2026: a web app and a mobile app sharing auth and API logic, TypeScript throughout, AI-first from the start. Most starters I found were either web-only, had outdated dependencies, or skipped the AI integration entirely. ShipKit is my answer to that gap.
The other motivation was the mobile side. Keeping a React Native (Expo) app and a Next.js app in sync — same auth session, same API client, same types — is not trivial. Getting that working cleanly in a monorepo took real effort. Once it was working, it made sense to preserve it.
What You Get
The core structure is a pnpm monorepo managed by Turborepo:
apps/
web/ # Next.js 15, App Router, Turbopack
mobile/ # Expo SDK 54 / React Native 0.76
packages/
ui/ # Shared component library
api-client/ # Typed fetch client shared between web and mobile
Auth is handled by Better Auth — email/password sign-up, Google OAuth, and password reset emails via Resend. Resend is optional: if you don’t add an API key, reset links fall back to a console log so dev still works. Google OAuth is also optional and only activates if GOOGLE_CLIENT_ID is set.
Database is Neon PostgreSQL, using the pg package with a singleton connection pool. The pool strips sslmode and channel_binding from the connection string before passing it to Neon’s pooler, which avoids the SSL mode warnings that otherwise fill your dev logs. Drizzle ORM sits on top for schema definition and migrations.
AI is wired up through Mastra with AI SDK handling the streaming chat protocol. The model factory supports Groq, OpenAI, Anthropic, and Google — you set AI_PROVIDER and AI_MODEL in your env and the factory routes to the right provider. Groq’s llama-3.3-70b-versatile is the default because it’s fast and free-tier friendly.
Styling is Tailwind CSS v4 on web and NativeWind v4 on mobile, so you can use the same utility classes across both platforms.
The CI pipeline runs lint, type-check, Vitest unit tests, a production build, and 51 Playwright E2E tests against Chromium, Firefox, and Mobile Chrome — all on GitHub Actions.
How to Use It
The repo is a GitHub Template, so you can create a new project from it directly on GitHub without forking:
- Click Use this template on the ShipKit repo
- Clone your new repo and run
pnpm install - Copy
.env.exampleto.env.localand fill in the required values — at minimumDATABASE_URL,BETTER_AUTH_SECRET, and one AI provider key
# Run just the web app
pnpm dev:web
# Run just the mobile app
pnpm dev:mobile
# Run everything
pnpm dev
The one thing to get right before doing anything else is the DATABASE_URL. Better Auth runs db.push on startup to create its tables (user, session, account, verification) in your Neon database. If the connection string is wrong or missing, auth will fail silently and users won’t be persisted. Neon’s connection string should use the pooler endpoint (ep-xxx-pooler.region.aws.neon.tech) rather than the direct endpoint.
For mobile, the Expo app shares the same Better Auth session via @better-auth/expo, which handles token storage in expo-secure-store. You don’t need a separate auth system for mobile — same users, same sessions.
Everything else in the template is meant to be replaced or extended. The landing page, the AI agent instructions, the Drizzle schema — these are starting points, not opinions you’re locked into.
The repo is at github.com/chitamoor/shipkit. If you use it and run into something that doesn’t work, open an issue.
