Sharply is a photography gear database and cataloging application. It combines authoritative gear specs, editorial reviews, and contributor tools so the community can keep data accurate while discovering new equipment.
- Framework: Next.js 15 (App Router) with React 19
- Language: TypeScript
- UI: Tailwind CSS 4, shadcn/ui
- Database: PostgreSQL with Drizzle ORM
- Auth: BetterAuth with Passkeys, OTP, and Discord & Google providers
- AI & Integrations: OpenAI API, Payload CMS for editorial content
- Tooling: ESLint, Prettier, TypeScript, Drizzle Kit
- Node.js 20 (LTS) and npm 10
- PostgreSQL 15+ (local or containerized)
- pnpm or yarn are not officially supported; use npm
- Docker or Podman (optional) if you want the provided database script
- An
.envfile configured from.env.example
Clone the repository and install dependencies:
git clone https://github.com/Flohhhhh/sharply.git
cd sharply
npm installCopy the template environment file and fill in required secrets:
cp .env.example .envSharply validates configuration through src/env.js. For onboarding you only need to set the values that power the features you plan to exercise:
Core minimum (the app will crash without these)
AUTH_SECRET– used by BetterAuth for session encryption (src/server/auth/index.ts)DATABASE_URL– establishes the Drizzle/Postgres connection (src/server/db/index.ts)NEXT_PUBLIC_BASE_URL– required when building canonical URLs and Discord bot links (src/server/gear/browse/service.ts)PAYLOAD_SECRET– required user-generated secret string for Payload CMS (src/payload.config.ts)
Sign-in providers (pick which providers you want and populate them)
It's highly advised you set up at least one of these, otherwise you can't test or use most features of the app because auth will be impossible. Discord is typically the fastest and easiest.
- Discord OAuth:
AUTH_DISCORD_ID,AUTH_DISCORD_SECRET - Google OAuth:
AUTH_GOOGLE_ID,AUTH_GOOGLE_SECRET - Email magic links:
RESEND_API_KEY,RESEND_EMAIL_FROM
Feature-specific values (optional until you need the feature)
CRON_SECRET– only required when hitting the secured cron routes such as/api/admin/popularity/rollupDISCORD_ROLLUP_WEBHOOK_URL– used to post rollup status messages to Discord; rollups still run without itOPENAI_API_KEY– enables AI review summaries;src/server/reviews/summary/service.tssafely no-ops if it is missingUPLOADTHING_TOKEN– used exclusively by the Payload CMS instance (src/payload.config.ts); the main Next.js app does not import it
Use the template comments as guidance; keep secrets out of version control.
You can run Postgres however you prefer. Two common options:
-
Local installation: create a database and ensure the URL in
.envpoints to it. -
Docker/Podman: run the helper script:
./start-database.sh
The script reads
DATABASE_URLfrom.env, creates a matching container, and warns if ports are in use.
After Postgres is running:
First-time setup (for new contributors setting up a fresh database):
npm run db:push # sync schema directly from src/server/db/schema.ts (one-time initial setup)
npm run db:seed -- --confirm-seed # (optional) populate sample data
npx drizzle-kit studio # (optional) view the database in Drizzle studio (or use your own viewer)After pulling changes (when migrations have been generated and merged to main):
npm run db:migrate # apply pending migrations to your LOCAL databaseDuring development (when working on schema changes):
npm run db:push # sync your local database with schema.ts changes (for testing)Note:
- Use
db:pushto test schema changes locally during development- Do NOT generate migration files (
db:generate) - maintainers will generate a consolidated migration when merging dev to main/staging- After migrations are merged, use
db:migrateto sync your local database- Never run migrations against production/staging databases
npm run db:seedrequires you to append-- --confirm-seed(for examplenpm run db:seed -- --confirm-seed). This keeps the safeguard in place so the script only runs when you explicitly acknowledge it and target a dev database. It will not overwrite existing gear unless you also pass--allow-gear-overwrite.
The seed script (scripts/seed.ts) is non-destructive by default and populates:
- Brands, mounts, sensor formats, genres, AF area modes
- Nikon Z6 III (fully hydrated: specs, mounts, AF areas, genres, editorial, reviews, review summaries)
- Canon EOS R6 Mark III
- Nikon Zf/Zr
- Nikon AF-S DX NIKKOR 35mm f/1.8G
- Nikon AF-S NIKKOR 50mm f/1.8G
Flags:
--confirm-seed(required): safety gate to prevent accidental production writes--allow-gear-overwrite: allow updating existing gear rows; without this, existing gear is left untouched--skip-taxonomy: skip brands/mounts/formats/genres/AF area modes--skip-editorial: skip editorial content (use-case ratings, staff verdicts)--skip-reviews: skip reviews and AI summaries
Examples:
npm run db:seed -- --confirm-seed
npm run db:seed -- --confirm-seed --skip-reviews
npm run db:seed -- --confirm-seed --allow-gear-overwritenpm run devThis starts Next.js on http://localhost:3000.
npm run lint– ESLint (required after significant changes)npm run typecheck– TypeScript with--noEmitnpm run check– Combined lint + typecheck
src/app– Next.js App Router routes, layouts, and pagessrc/components– Shared UI components (shadcn/ui lives insrc/components/ui)src/server– Server-only codedb– Drizzle client and schema definitionsgear,admin,auth, etc. – Service layers followingdata → service → actions
src/lib– Utilities, constants, mapping logicdocs– Architecture and feature documentation (keep docs updated when code changes)drizzle– Generated SQL migrationsscripts– Node scripts for seeding and maintenance
- Fork or create a feature branch.
- Keep schema changes in
src/server/db/schema.ts; do not edit migrations manually. - Database workflow:
- Make schema changes in
src/server/db/schema.ts - Test locally: Use
npm run db:pushto sync your local database with schema changes - Do NOT run
db:generateor commit migration files - maintainers will generate a consolidated migration when merging dev to main/staging - Commit only the schema changes (
schema.ts) - After migrations are merged to main, pull and run
npm run db:migrateto sync your local database
- Make schema changes in
- First-time setup: New contributors use
npm run db:pushonce for initial database setup - Update relevant docs in
/docsalongside code changes. - Run
npm run lintandnpm run typecheckornpm run buildand fix any errors in touched files. - Open a pull request with context on the changes and testing performed.
- Review documentation in
/docsfor deeper architecture details. - For questions, open an issue or reach out to the maintainers listed in
AGENTS.md.
Note: This project does not include production database contents. Any live/production data (editorial, user content, or other proprietary datasets) is not included or licensed as part of this repository.