Tubmind is a Next.js 16 app for privately capturing ideas, organizing them inside an idea tub workspace, refining them into structured records, publishing selected ideas to a public listings surface, and moderating users, ideas, and comments through an admin workspace.
The current beta includes:
- Google sign-in with Supabase Auth
- Automatic profile creation and sync on first login
- Private idea creation and editing
- Private idea tub planning with task and calendar flows
- Public listings and public idea pages
- Logged-in commenting
- Admin moderation for ideas, users, and comments
The schema also contains future-facing tables such as reports, reactions, views, and progress entries, but those are not fully productized yet.
- Next.js 16 App Router
- React 19
- Supabase Auth
- Postgres
- Drizzle ORM and Drizzle Kit
- Tailwind CSS 4
- Node.js 20+
- pnpm 9+
- A Supabase project
- A Postgres connection string for that Supabase database
- A Google OAuth app configured inside Supabase Auth
Create a local .env file from .env.example and set:
DATABASE_URL: Postgres connection string used by Drizzle and server-side queriesNEXT_PUBLIC_SUPABASE_URL: Supabase project URLNEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY: Supabase anon or publishable key used by browser and SSR auth clientsSUPABASE_SERVICE_ROLE_KEY: Supabase service role key used for privileged server operations
Notes:
DATABASE_URLmust point at the same database backing your Supabase project.SUPABASE_SERVICE_ROLE_KEYis server-only. Never expose it in the browser.
- Install dependencies:
pnpm install-
Create
.envfrom the example file and fill in the four required values. -
Configure Supabase Auth.
- In Supabase, enable the
Googleprovider under Authentication. - Set the site URL for local development to
http://localhost:3000. - Add this redirect URL:
http://localhost:3000/auth/callback
- Push the schema to the database:
pnpm db:push- Start the app:
pnpm dev- Open:
http://localhost:3000
- The login button starts Supabase Google OAuth.
- Supabase redirects back to
/auth/callback. - The callback exchanges the auth code for a session and syncs the user into the local
profilestable. - The app expects
auth.usersto exist, so this project should run against a Supabase-managed Postgres database, not a generic standalone Postgres instance without Supabase Auth tables.
Schema source:
src/db/schema.ts
Useful commands:
pnpm db:generate
pnpm db:push
pnpm db:studioRecommended beta workflow:
- Use
pnpm db:pushwhile the schema is still changing quickly. - Review schema updates carefully before pushing to shared environments.
- Use
pnpm db:studiowhen you need to inspect or manually verify records.
There is no seed script for admins yet. The normal flow is:
- Start the app.
- Sign in once with the Google account that should become admin.
- Confirm a row was created in
profiles. - Promote that user manually in the database.
Example SQL:
update profiles
set role = 'admin'
where email = 'you@example.com';You can run that in:
- Supabase SQL Editor
- Drizzle Studio
- Any SQL client connected to the same database
After promotion, sign out and sign back in if the current session does not immediately reflect the new role.
Admin pages live at:
/admin/admin/ideas/admin/users/admin/comments
Current admin capabilities:
- Make ideas public or private
- Request revision on ideas
- Archive or delete ideas
- Mark users active, under review, blocked, or unblocked
- Promote or demote admins
- Hide, restore, or delete comments
Important operational notes:
- Blocking a user currently protects page access, but API hardening should still be reviewed before public launch.
- Public visibility is the current gate for listings and public idea pages.
- Moderation actions create entries in
moderation_logs.
Tubmind can be deployed anywhere that supports Next.js 16 and Node.js. Vercel is the easiest path, but not required.
- A production Supabase project
- Production values for all four environment variables
- Google auth enabled in the production Supabase project
- Production redirect URL added in Supabase:
https://your-domain.com/auth/callback
- Production site URL set correctly in Supabase Auth
- Provision the target environment.
- Add the required environment variables.
- Push the schema to the production database:
pnpm db:push- Build the app:
pnpm build- Start the app:
pnpm startpnpm lintpassespnpm buildpasses in a clean environment- Supabase Google auth works locally and in production
/auth/callbackis registered in Supabase for every environment- First admin account is promoted in
profiles - Admin can access
/admin - A signed-in user can create an idea
- A signed-in user can open
/dashboard/projects/[id]and manage tasks - A private idea can be edited from
/dashboard - A public idea appears in
/listings - A public idea page opens at
/ideas/[slug] - Comment creation works for logged-in users
- Environment secrets are set only on the server where appropriate
Check the profiles.role value for that user. The app only grants admin access when the role is exactly admin.
Check:
- Supabase site URL
- Supabase redirect URLs
- The
nextquery string passed into/auth/callback
Check:
DATABASE_URLpoints to the correct database- The schema has been pushed with
pnpm db:push - You are using a Supabase database with the
auth.usersschema available
Stop any running dev server or other process using the app directory, then retry the build in a clean terminal session.
- App routes:
src/app - Database schema:
src/db/schema.ts - Database client:
src/db/index.ts - Auth helpers:
src/lib/auth.ts - Supabase helpers:
src/lib/server.ts,src/lib/client.ts,src/lib/middleware.ts - Admin UI:
src/features/admin - Idea UI:
src/features/ideas - Idea tub UI:
src/features/tub