Setuverse is a community gallery for workspace setups. Browse real desk photos, explore every tagged item inside them, save favorites, and share your own setup with the community.
Browsing is open to everyone. Sharing requires an account (Google OAuth).
- Setup gallery — Discover published workspace photos by category
- Tagged items — Click hotspots on a photo to see monitors, keyboards, and other gear
- Create flow — Upload images, place item tags, review, and submit for publishing
- Social actions — Like, save, and rate setups
- Profiles — Public profiles with setups, likes, saves, and custom links
- Admin panel — Moderate setups, manage users, categories, and images
- Image pipeline — Cloudflare R2 storage with Sharp-based optimization
| Layer | Technology |
|---|---|
| Framework | TanStack Start (React 19, SSR) |
| Routing & data | TanStack Router, TanStack Query |
| Auth | Better Auth + Google OAuth |
| Database | PostgreSQL + Prisma |
| Storage | Cloudflare R2 (S3-compatible) |
| UI | Tailwind CSS 4, Radix UI / shadcn-style components |
| Validation | Zod, React Hook Form |
| Runtime / deploy | Nitro (Node server) |
| Package manager | Yarn |
- Node.js
22.14(see.nvmrc) - Yarn
- Docker (recommended for PostgreSQL)
- A Google Cloud OAuth client (for login)
- A Cloudflare R2 bucket (for setup images)
git clone https://github.com/<your-org>/setuverse.git
cd setuverse
yarn installcp .env.example .envFill in the values described in Environment variables. At minimum you need a working DATABASE_URL, BETTER_AUTH_SECRET, Google OAuth credentials, and R2 settings for uploads.
Generate an auth secret:
openssl rand -base64 32docker compose up -dThis starts Postgres 16 using the credentials from your .env.
yarn db:generate
yarn db:migrate
yarn db:seed # optional sample datayarn devThe app starts at http://localhost:3000.
Copy from .env.example. Important keys:
| Variable | Description |
|---|---|
POSTGRES_USER / POSTGRES_PASSWORD / POSTGRES_DB / POSTGRES_PORT |
Local Docker Postgres settings |
DATABASE_URL |
Prisma connection string |
BASE_URL / VITE_BASE_URL |
App origin (e.g. http://localhost:3000) |
BETTER_AUTH_SECRET |
Better Auth signing secret |
GOOGLE_CLIENT_ID / GOOGLE_CLIENT_SECRET |
Google OAuth credentials |
R2_ENDPOINT / R2_ACCOUNT_ID / R2_ACCESS_KEY_ID / R2_SECRET_ACCESS_KEY / R2_BUCKET_NAME / R2_PUBLIC_URL |
Cloudflare R2 configuration |
Never commit .env. Only .env.example belongs in the repository.
src/
features/ # Domain modules (auth, home, create-setup, setup, profile, admin, …)
routes/ # File-based TanStack Router routes
shared/ # Shared UI, libs, and utilities
integrations/ # Cross-cutting integrations (e.g. Query)
generated/ # Prisma client output (gitignored)
prisma/
schema/ # Split Prisma models
migrations/ # SQL migrations
seed.ts # Seed script
Feature code is organized by domain (screen, components, server, service, lib) so UI, server functions, and hooks stay close to the feature they belong to.
| Command | Description |
|---|---|
yarn dev |
Generate Prisma client and start Vite dev server on port 3000 |
yarn build |
Production build |
yarn start |
Run the Nitro production server (.output/server/index.mjs) |
yarn test |
Run Vitest |
yarn lint / yarn format / yarn check |
Lint and format |
yarn db:generate |
Generate Prisma client |
yarn db:migrate |
Create / apply migrations (dev) |
yarn db:deploy |
Apply migrations (production) |
yarn db:push |
Push schema without a migration (prototyping) |
yarn db:seed |
Seed the database |
yarn db:studio |
Open Prisma Studio |
yarn test:r2 |
Smoke-test R2 upload credentials |
Prisma schemas live under prisma/schema/ and map to PostgreSQL.
Core domain models:
- User / Session / Account — Better Auth identity
- Profile / ProfileLink — Public profile data
- Setup — Draft → pending → published (or rejected) workspace posts
- SetupItem — Tagged products on a setup image
- Category — Setup categories
- SetupLike / SetupSave / SetupRate — Engagement
Useful workflow:
yarn db:migrate # change schema + create migration
yarn db:studio # inspect dataAuth is handled by Better Auth with a Prisma adapter and Google as the social provider. Sessions use TanStack Start cookies.
On first sign-in, a related Profile row is created automatically.
Configure the Google OAuth redirect URI to match your BASE_URL (for local development: http://localhost:3000/api/auth/callback/google — confirm against your Better Auth / Google Cloud console settings).
Setup images are uploaded to Cloudflare R2. The create flow optimizes images with Sharp before storage.
Ensure R2_PUBLIC_URL points at a publicly readable URL for your bucket (custom domain or r2.dev URL).
yarn build
yarn startA multi-stage Dockerfile builds and runs the app. Migrations run on container start via docker-entrypoint.sh.
Typical flow:
- Provide production env vars (database, auth, R2,
BASE_URL) - Ensure Postgres is reachable
- Build and run the image
Local Postgres for development remains available via docker compose up -d.
Contributions are welcome.
- Fork the repository and create a feature branch
- Keep changes focused and consistent with the existing feature-based layout
- Run
yarn lintandyarn testbefore opening a PR - Describe the motivation and how to verify the change
If you are fixing a bug, include steps to reproduce. If you are proposing a larger feature, open an issue first so scope can be discussed.
- Additional OAuth providers
- Richer discovery (search, filters, collections)
- Moderation tooling improvements
License to be decided. Until a LICENSE file is added, all rights are reserved by the author(s). If you plan to use or redistribute this project, open an issue to confirm terms.
Built with TanStack, Better Auth, Prisma, and Cloudflare R2.