GoFarm Developer Documentation — Build, Configure & Ship
The complete reference for the GoFarm agricultural e-commerce platform. This guide walks you through everything from cloning the repo to deploying on Vercel — installation, service configuration, architecture, schemas, APIs, payments, analytics, and the coding standards every contributor follows.
01Introduction
GoFarm is a production-ready agricultural e-commerce platform that connects farmers and consumers directly. It ships with a full storefront, an admin dashboard, vendor onboarding, an employee portal, multi-currency support, Stripe + SSLCommerz checkout, and a Sanity-powered CMS.
The codebase is built around three principles: a single source of truth per concern (Firebase Auth for identity, Sanity for domain data, GA4 for analytics), server-by-default React components, and strictly enforced coding standards via Biome, lefthook, and Conventional Commits.
Who this guide is for
- New contributors setting up a local environment for the first time.
- Maintainers looking for a complete reference to the routes, APIs, and schemas.
- DevOps engineers deploying GoFarm to Vercel or another host.
- Store operators configuring services (Sanity, Stripe, email) before going live.
02Tech Stack
GoFarm uses a modern, battle-tested set of libraries. Every package is on a current major version with security patches applied.
| Layer | Technology | Version | Purpose |
|---|---|---|---|
| Framework | next | 16.2.x | App Router, React Server Components, Turbopack |
| UI | react / react-dom | 19.2.x | Server Components, Actions, Suspense |
| Language | typescript | 6.0.x | Strict mode + noImplicitOverride |
| Styling | tailwindcss | 4.2.x | Utility-first CSS with theme tokens |
| Components | Radix UI + shadcn/ui | 1.x | Accessible primitives |
| Animation | motion | 12.38.x | Page and component transitions |
| CMS | sanity / next-sanity | 5.21.x | Headless content + embedded Studio |
| Auth | firebase / firebase-admin | 12 / 13 | Email + OAuth, 14-day session cookies, custom claims |
| Payments | stripe + SSLCommerz | 22.x | Card, wallet, BDT, COD |
nodemailer | 8.x | Gmail OAuth2 transactional email | |
| State | zustand | 5.x | Auth, cart, wishlist, compare, share |
| Forms | react-hook-form + zod | 7.x / 4.x | Schema-first input validation |
| Tooling | Biome v2, lefthook, commitlint | — | Format, lint, hooks, commit policy |
03Core Features
Out of the box, GoFarm includes everything an agricultural marketplace needs. The full feature set is available to anyone using or purchasing the project — there are no locked tiers.
Storefront
- Multi-image product catalog
- Category, brand, and collection pages
- Product variants (size, color, weight)
- Real-time inventory tracking
- Search, filters, and faceted browse
- Status badges (New, Hot, Featured)
Cart & Checkout
- Persistent cart synced across sessions
- Wishlist + compare list
- Discount codes and coupons
- Stripe, SSLCommerz, Cash-on-Delivery
- Apple Pay / Google Pay ready
- Order confirmation emails
User Accounts
- Firebase email + Google OAuth
- Profile, addresses, preferences
- Order history & tracking
- Digital wallet + transactions
- Loyalty & reward points
- Reviews and ratings
Admin Dashboard
- Product, order, and user management
- Vendor approval workflow
- Analytics & sales dashboards
- Email campaigns / newsletter
- Review moderation
- Coupon & subscription management
Vendor Portal
- Vendor application + approval
- Vendor product management
- Sales analytics
- Wallet withdrawals
- Commission tracking
Operations
- Employee portal for fulfilment
- Order workflow: Pending → Delivered
- Newsletter & subscribers
- Contact form + ticketing
- Store-settings dashboard
04Prerequisites
Before you clone the repo, make sure your machine has the following installed.
| Tool | Minimum | Install |
|---|---|---|
| Node.js | 18.0+ (LTS 20 recommended) | nodejs.org |
| pnpm | 9.0+ | npm i -g pnpm |
| Git | 2.30+ | git-scm.com |
| Stripe CLI (optional) | latest | brew install stripe/stripe-cli/stripe |
Required accounts
You will need free-tier accounts for the following SaaS services. All can be created in under 10 minutes.
- Sanity CMS — sanity.io (catalog, pages, blog)
- Firebase — console.firebase.google.com (auth + analytics)
- Stripe — stripe.com (card payments)
- Google Cloud — console.cloud.google.com (Gmail OAuth2 for outbound email)
- SSLCommerz (optional, BD payments) — sslcommerz.com
05Quick Start
These five steps take you from a blank machine to a running local dev server. Detailed configuration is covered in §7.
Clone the repository
git clone https://github.com/noorjsdivs/gofarm.git
cd gofarmInstall dependencies with pnpm
The prepare script automatically installs lefthook git hooks during install.
pnpm installCopy the environment template
cp .env.example .env.localOpen .env.local and fill in your service credentials. Full reference in §6.
Start the dev server
pnpm dev # webpack (default)
pnpm dev:turbo # turbopack (faster HMR)Open the app
- Storefront:
http://localhost:3000 - Sanity Studio:
http://localhost:3000/studio - Admin panel:
http://localhost:3000/admin - These docs:
http://localhost:3000/docs
pnpm install again. The allowlist lives under pnpm.onlyBuiltDependencies in package.json.06Environment Variables
Every variable the app reads is grouped by concern. Server-only variables have no NEXT_PUBLIC_ prefix and never ship to the browser.
Base & admin
NEXT_PUBLIC_BASE_URL=http://localhost:3000
ADMIN_EMAILS=you@example.com,team@example.comSanity CMS
NEXT_PUBLIC_SANITY_PROJECT_ID=xxxxxxxx
NEXT_PUBLIC_SANITY_DATASET=production
SANITY_API_TOKEN=sk_write_token_here
SANITY_API_READ_TOKEN=sk_read_token_hereFirebase client (public)
NEXT_PUBLIC_FIREBASE_API_KEY=AIzaSy...
NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=your-project.firebaseapp.com
NEXT_PUBLIC_FIREBASE_PROJECT_ID=your-project-id
NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET=your-project.firebasestorage.app
NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID=123456789
NEXT_PUBLIC_FIREBASE_APP_ID=1:123:web:abc
NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID=G-XXXXXXXXXXFirebase Admin (server only)
FIREBASE_PROJECT_ID=your-project-id
FIREBASE_CLIENT_EMAIL=firebase-adminsdk-...@your-project.iam.gserviceaccount.com
FIREBASE_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n"Stripe
STRIPE_SECRET_KEY=sk_test_...
STRIPE_WEBHOOK_SECRET=whsec_...
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_...SSLCommerz (optional, BD)
SSLCOMMERZ_STORE_ID=...
SSLCOMMERZ_STORE_PASSWORD=...
SSLCOMMERZ_IS_LIVE=falseEmail (Gmail OAuth2)
GOOGLE_CLIENT_ID=123456789-xxx.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=GOCSPX-xxx
GOOGLE_REFRESH_TOKEN=1/04...
SENDER_EMAIL_ADDRESS=noreply@yourdomain.comAnalytics (GA4 Measurement Protocol)
GA4_MEASUREMENT_ID=G-XXXXXXXXXX
GA4_API_SECRET=abc123....gitignore excludes .env* files. If a secret leaks, rotate it immediately and use git filter-repo to scrub history before pushing.07Service Setup
Detailed walkthrough for each external service GoFarm depends on. Complete these before running pnpm dev.
7.1 Sanity CMS
- Sign in at sanity.io/manage and create a new project.
- Note the Project ID and use
productionas the dataset name. - Under API → Tokens, generate two tokens: Editor (write) and Viewer (read).
- Add the CORS origin
http://localhost:3000(and later your production domain) with credentials enabled. - Paste IDs and tokens into
.env.local(see §6). - Visit
/studioto start authoring categories, brands, and products.
7.2 Firebase Authentication & Analytics
- Create a project at Firebase Console.
- In Authentication → Sign-in methods, enable Email/Password and Google.
- In Project settings → General, register a Web app and copy the SDK config into the
NEXT_PUBLIC_FIREBASE_*variables. - Under Service accounts → Generate new private key, download the JSON and extract
project_id,client_email, andprivate_keyinto the server-onlyFIREBASE_*variables. - Enable Analytics and link the GA4 property — required for the GA4 Measurement Protocol.
7.3 Stripe
- Get test API keys from Developers → API Keys.
- Local development webhook:
Copy thestripe login stripe listen --forward-to localhost:3000/api/webhookwhsec_secret intoSTRIPE_WEBHOOK_SECRET. - For production, register an endpoint at
https://yourdomain.com/api/webhookand subscribe to:checkout.session.completedpayment_intent.succeededcharge.refunded
7.4 Gmail OAuth2 for email
- At Google Cloud Console enable the Gmail API for your project.
- Create an OAuth client ID (Web application).
- Authorize redirect URI
https://developers.google.com/oauthplayground. - Use the OAuth Playground with your own credentials to obtain a refresh token for the scope
https://mail.google.com/. - Paste the credentials into
GOOGLE_*env vars.
7.5 GA4 Measurement Protocol
- In GA4 console open Admin → Data Streams → Web.
- Click Measurement Protocol API secrets → Create and copy the secret to
GA4_API_SECRET. - The same property's Measurement ID becomes
GA4_MEASUREMENT_ID. - Mark
purchase,sign_up, andbegin_checkoutas conversion events for Monetisation reports.
08Running the App
Available scripts
| Script | Command | Purpose |
|---|---|---|
dev | pnpm dev | Webpack-based dev server on :3000 |
dev:turbo | pnpm dev:turbo | Turbopack dev server (faster HMR) |
build | pnpm build | Production build (Next.js) |
start | pnpm start | Run the built app |
format | pnpm format | Biome format everything |
lint | pnpm lint | Biome check (read-only) |
lint:fix | pnpm lint:fix | Biome check with safe auto-fixes |
typecheck | pnpm typecheck | tsc --noEmit |
ci | pnpm ci | typecheck + lint + build (CI parity) |
typegen | pnpm typegen | Regenerate sanity.types.ts |
Local URLs
http://localhost:3000— Storefronthttp://localhost:3000/studio— Sanity Studiohttp://localhost:3000/admin— Admin Dashboardhttp://localhost:3000/employee— Employee Portalhttp://localhost:3000/vendor— Vendor Portalhttp://localhost:3000/docs— This documentation
09Project Structure
GoFarm uses the Next.js App Router with route groups for isolation. Server actions live in actions/, shared helpers in lib/, schemas in sanity/.
gofarm/
├── app/ # Next.js App Router
│ ├── (client)/ # Public storefront route group
│ │ ├── (public)/ # About, FAQ, contact, etc.
│ │ ├── (user)/ # Cart, checkout, dashboard
│ │ ├── blog/ brands/ category/ collection/
│ │ ├── compare/ deal/ product/ products/ shop/
│ │ ├── orders/ vendor-info/ vendor-registration/
│ │ ├── home-2/ home-3/ home-4/
│ │ └── page.tsx # Homepage
│ │
│ ├── (admin)/admin/ # Admin dashboard
│ ├── (auth)/ # Sign-in / Sign-up
│ ├── (employee)/employee/ # Fulfilment portal
│ │
│ ├── api/ # API routes
│ │ ├── auth/ checkout/ payment/ webhook/
│ │ ├── admin/ user/ vendor/ employee/
│ │ ├── orders/ coupons/ categories/
│ │ ├── menus/ newsletter/ contact/
│ │ ├── analytics/ addresses/ store-settings/
│ │ └── ...
│ │
│ ├── studio/ # Embedded Sanity Studio
│ ├── docs/ # This documentation page
│ ├── layout.tsx # Root layout (Jost, providers)
│ ├── globals.css
│ ├── robots.ts
│ └── sitemap.ts
│
├── actions/ # "use server" actions
├── components/ # Shared UI components
│ ├── ui/ # shadcn primitives
│ ├── admin/ vendor/ employee/
│ ├── cart/ checkout/ product/
│ └── AuthInitializer.tsx AnalyticsProvider.tsx
│
├── hooks/ # Client-side hooks
├── lib/ # Framework-agnostic helpers
│ ├── firebase/admin.ts
│ ├── auth/server.ts
│ ├── analytics/server.ts
│ └── logger.ts
│
├── sanity/ # CMS configuration
│ ├── schemaTypes/ # 25+ content schemas
│ ├── queries/ # Centralised GROQ
│ └── helpers/ lib/ env.ts
│
├── stores/ # Zustand state
├── store.ts # Legacy cart store
├── types/ config/ constants/
├── public/ # Static assets (logo.svg, etc.)
├── scripts/ # CLI scripts
├── biome.json # Format + lint config
├── lefthook.yml # Git hooks
├── commitlint.config.mjs
├── next.config.ts
├── sanity.config.ts
└── tsconfig.json10Routing
The App Router uses parenthesised route groups to isolate layouts without changing URLs. Each group has its own layout.tsx and error.tsx.
| Route group | Purpose | Audience | Auth |
|---|---|---|---|
(client)/(public) | Marketing, FAQ, contact, terms | Anonymous | None |
(client) | Shop, products, blog, brands | Visitors | None |
(client)/(user) | Cart, checkout, dashboard, wishlist | Signed-in customers | requireUser() |
(auth) | Sign in, sign up, forgot password | Anyone | None |
(admin) | Product / order / user management | Admins only | requireRole("admin") |
(employee) | Fulfilment, deliveries, warehouse | Employees | requireRole("employee") |
Edge middleware
proxy.ts runs at the Edge for every request. It checks the __session cookie and redirects unauthenticated users away from /admin, /employee, /cart, /checkout, and /user. Role checks happen in the Node-runtime layout because firebase-admin is not available at the Edge.
11Authentication
Identity is owned entirely by Firebase Authentication. Sanity stores only the things Firebase does not — addresses, wallet, wishlist — keyed by the Firebase UID.
Session lifecycle
Browser /api/auth/session Firebase Admin
│ │ │
│ signInWithEmail / Google │ │
│ ─────────────────────────────▶ │ │
│ idToken (1h TTL) │ verifyIdToken │
│ │ ───────────────────────▶ │
│ │ createSessionCookie(14d) │
│ ◀─────────────────────────────── │
│ Set-Cookie: __session; │ │
│ HttpOnly; Secure; SameSite=Lax │ │
│ │ ensureSanityUser(uid) │
│ │ ◀─── idempotent ──────── │Key files
lib/firebase/admin.ts— single Admin SDK init.lib/auth/server.ts— canonical server auth helpers:requireUser(),requireRole(),currentUserIsAdmin().app/api/auth/session/route.ts— POST creates session cookie, DELETE revokes refresh tokens.stores/authStore.ts— Zustand store mirroring Firebase auth state to React.components/AuthInitializer.tsx— subscribes toonIdTokenChangedand pushes ID tokens to/api/auth/session.
Server-side usage
// app/(client)/(user)/user/page.tsx
import { requireUser } from "@/lib/auth/server";
export default async function UserDashboard() {
const user = await requireUser();
return <Dashboard user={user} />;
}12Authorization & Roles
Roles live in Firebase custom claims so they are present in the JWT and require no database round-trip on every request.
| Role | Claim | Grants |
|---|---|---|
| Admin | { admin: true } | Full /admin access, role grants, store settings, analytics |
| Employee | { employee: true } | /employee portal, order fulfilment, deliveries |
| Vendor | { vendor: true } | /vendor dashboard, manage own products / payouts |
| Customer | (no claim) | Default — shop, checkout, user dashboard |
Granting a role
# Preview (no changes)
pnpm tsx scripts/sync-claims.ts
# Commit
pnpm tsx scripts/sync-claims.ts --applyrevokeRefreshTokens(uid)is called so the new claim is reflected on the user's next request.13Sanity CMS
Sanity is the system of record for catalog, marketing pages, blog, and per-user domain data (orders, addresses, wallet). Schemas live in sanity/schemaTypes/.
| Schema | Purpose | Key fields |
|---|---|---|
product | Catalog item | title, slug, price, images, variants, category |
productVariant | SKU-level variant | size, color, weight, stock |
category | Nested categories | title, slug, parent, image |
brand | Brand / farmer profile | name, logo, story |
order | Customer order | firebaseUid, products[], status, totalPrice |
user | Profile + wallet | firebaseUid, addresses, wishlist, wallet |
review | Product review | product, rating, body, approved |
coupon | Discount codes | code, type, value, expiry, usage |
subscription | Newsletter subscriber | email, source, optedInAt |
vendorApplication | Vendor onboarding | firebaseUid, businessName, status |
walletWithdrawal | Payout request | firebaseUid, amount, status, bankInfo |
storeSettings | Global store config | currency, tax, shipping, branding |
menu / banner | Site nav & hero | title, items[], link |
blog / blogCategory | Content marketing | title, slug, body (PortableText) |
Queries
GROQ queries are never inlined in components. They live in sanity/queries/*.ts as typed functions.
// sanity/queries/userQueries.ts
export const ordersByUser = `
*[_type == "order" && firebaseUid == $uid]
| order(orderDate desc) {
_id, status, totalPrice, currency,
products[]{ quantity, product->{title, slug, image} }
}
`;Whenever a schema changes, run pnpm typegen to rebuild sanity.types.ts.
14API Reference
All routes live under app/api/**. Most mutations now prefer Server Actions in actions/; the API routes remain for webhooks and AJAX endpoints used by the dashboards.
| Endpoint | Method | Auth | Purpose |
|---|---|---|---|
/api/auth/session | POST / DELETE | Public / cookie | Create or destroy session cookie |
/api/auth/check-admin | GET | Session | Returns { isAdmin } |
/api/auth/role | GET | Session | Returns active role(s) from claims |
/api/auth/sync-user | POST | Session | Sync Firebase user into Sanity |
/api/checkout/stripe | POST | Session | Create Stripe Checkout session |
/api/webhook | POST | Stripe sig | Process payment success, emit GA4 purchase |
/api/user/profile | GET / PATCH | Session | Read or update profile |
/api/user/cart | GET / POST / DELETE | Session | Persistent cart |
/api/user/orders | GET | Session | List user orders |
/api/user/wishlist | GET / POST / DELETE | Session | Manage wishlist |
/api/user/addresses | all | Session | Shipping addresses CRUD |
/api/admin/orders | GET / PATCH | Admin claim | List & manage orders |
/api/admin/products | all | Admin claim | CRUD products |
/api/admin/users | GET / PATCH | Admin claim | List + manage users |
/api/admin/vendor-requests | GET / POST | Admin claim | Approve / reject vendors |
/api/admin/analytics | GET | Admin claim | Aggregate KPIs |
/api/vendor/* | various | Vendor claim | Vendor product / orders / withdrawal |
/api/employee/* | various | Employee claim | Fulfilment endpoints |
/api/coupons/validate | POST | Session | Validate coupon at checkout |
/api/newsletter | POST | Public | Subscribe email |
/api/contact | POST | Public | Contact form |
/api/categories | GET | Public | Navigation data |
Server Actions
Mutations preferred over API routes — typed end-to-end. All actions return a discriminated union and never throw across the network boundary.
type ActionResult<T> =
| { ok: true; data: T }
| { ok: false; error: string };
"use server";
export async function createReview(
input: ReviewInput
): Promise<ActionResult<Review>> {
const user = await requireUser();
// … validate with zod, write to Sanity, revalidate tags …
}15State Management
Zustand is the only client store. Each concern has its own slice; stores subscribe to authStore when they need to react to sign-in / sign-out.
| Store | Path | State |
|---|---|---|
authStore | stores/authStore.ts | currentUser, loading, role |
cartStore | store.ts | items, totals, hydrate / flush |
cartAddedModalStore | stores/cartAddedModalStore.ts | open/close added-to-cart modal |
compareStore | stores/compareStore.ts | product compare list |
shareStore | stores/shareStore.ts | share sidebar visibility + payload |
userDataStore | stores/userDataStore.ts | profile, wallet, points cache |
16Payments & Orders
Checkout flow
Cart ──▶ /checkout ──▶ /api/checkout/stripe ──▶ Stripe Checkout
│
▼
Sanity order doc (status: pending)
│
▼
Stripe ──▶ /api/webhook (signature verified)
│
┌─────────────────┼──────────────────────┐
▼ ▼ ▼
update order send confirmation GA4 purchase
status: paid email (Measurement Protocol)Order status machine
- pending — created, awaiting payment.
- paid — Stripe / SSLCommerz confirmed.
- processing — assigned to employee.
- shipped — courier tracking attached.
- delivered — final.
- cancelled — refund issued if paid.
17Analytics (GA4)
GoFarm emits the full GA4 e-commerce funnel so Firebase Console → Analytics → Realtime, Monetisation, and Retention reports auto-populate.
| Funnel stage | GA4 event | Fires from |
|---|---|---|
| Browse | view_item_list | Category & home pages |
| Detail | view_item | Product page |
| Search | search | Header search bar |
| Cart | add_to_cart / remove_from_cart | AddToCart / QuantityButtons |
| Cart | view_cart | Cart page mount |
| Checkout | begin_checkout / add_payment_info | Checkout steps |
| Order | purchase / refund | Stripe webhook (server) |
| Auth | login / sign_up / logout | AnalyticsProvider |
components/AnalyticsProvider.tsx calls setUserId(uid) and setUserProperties() whenever auth state changes, enabling cross-device cohort reports. Append ?debug=1 to any page to fire events with debug_mode: true so they appear in GA4 DebugView.
18Admin Dashboard
The admin dashboard lives at /admin behind the admin custom claim.
Catalog
- /admin/products — list, edit, delete
- Bulk update prices / stock
- Variant management
Orders
- /admin/orders — full order list
- Status changes & assignment
- Refund initiation
Users & vendors
- /admin/users — search, roles, suspend
- /admin/vendor-requests — approve / reject
- Wallet adjustments
Content
- /admin/reviews — moderation
- /admin/subscriptions — newsletter
- /admin/notifications
Operations
- /admin/employees — manage staff
- /admin/stores — branding & settings
Analytics
- Revenue, AOV, conversion rate
- Top products and categories
- Cohort retention
19Vendor & Employee Portals
Vendor Portal — /vendor
- Sign-up at
/vendor-registration, awaits admin approval. - Once approved, the
vendorcustom claim is set and the vendor sees their dashboard. - Manage own products, view orders, request payouts via
walletWithdrawal.
Employee Portal — /employee
- Granted manually by an admin via the user management UI.
- Order queue, status transitions, delivery confirmations, warehouse stock movements.
- Activity is logged to the order's
historyarray for audit.
20Coding Standards
Standards are enforced by tooling rather than convention. Biome formats and lints on every commit; commitlint validates every commit message; TypeScript strict mode catches type errors before they ship.
| Concern | Tool | Where it runs |
|---|---|---|
| Format + lint | Biome v2 | Pre-commit (staged), CI (full repo) |
| Type check | tsc --noEmit | Pre-push, CI |
| Hooks | lefthook | Auto-installed on pnpm install |
| Commit messages | commitlint + Conventional Commits | commit-msg hook |
| Editor consistency | .editorconfig | Every editor |
| CI | GitHub Actions | Every PR + push to main |
Naming conventions
| Item | Convention | Example |
|---|---|---|
| React components | PascalCase.tsx | ProductCard.tsx |
| Hooks | use-kebab-case.ts | use-cart.ts |
| Server actions | kebab-case.ts | create-order.ts |
| Stores | kebab-case-store.ts | cart-store.ts |
| Booleans | is/has/can/should | isLoading |
| Constants | SCREAMING_SNAKE_CASE | MAX_CART_ITEMS |
| Sanity schema name | camelCase, singular | walletWithdrawal |
21Git Workflow
Conventional Commits
<type>(<scope>): <subject>
# Allowed types
feat, fix, docs, style, refactor, perf,
test, build, ci, chore, revert
# Examples
feat(cart): add coupon stacking
fix(checkout): correct VAT rounding
chore(deps): bump biome to 2.4.16Pre-commit hooks (lefthook)
| Hook | Runs | Why |
|---|---|---|
| pre-commit | biome check --write | Auto-format & safe lint fixes |
| pre-commit | forbid-secrets | Reject .env* (except example) |
| commit-msg | commitlint --edit | Enforce Conventional Commits |
| pre-push | tsc --noEmit | Full project typecheck |
| pre-push | biome ci . | Full-repo lint & format check |
--no-verify to bypass hooks. If a hook fails, investigate.22Deployment
Deploy to Vercel (recommended)
- Push your branch to GitHub.
- At vercel.com, import the repository.
- Framework Preset: Next.js. Build command:
pnpm build. - Add every variable from
.env.localin Project Settings → Environment Variables. - After the first deploy, update
NEXT_PUBLIC_BASE_URLto your domain. - In Sanity → API → CORS origins, add the production URL with credentials enabled.
- In Stripe, create a production webhook pointing to
/api/webhookand paste the newwhsec_into Vercel env. - In Firebase → Authentication → Authorized domains, add the production domain.
Post-deploy checklist
- Sign in with the email listed in
ADMIN_EMAILS— theadmincustom claim is set automatically on first login. - Run the claims backfill:
pnpm tsx scripts/sync-claims.ts --apply. - In GA4, mark
purchase,sign_up,begin_checkoutas conversion events. - Place a test order with Stripe's test card
4242 4242 4242 4242. - Confirm the GA4 Realtime view shows your
purchaseevent within 30 seconds.
23Pricing & Hire Me
Want me to set up GoFarm for you instead of doing it yourself? Every package starts from the same installation base of $100 — the additional tiers simply layer add-ons on top. Honest, freelance-market rates from Bangladesh, all in USD. Each package is a fixed scope, fixed price. Hourly is available for ad-hoc changes after handover.
Installation Only
Delivery: 2–3 business days
- ✓Clone & install the project on your machine or VPS
- ✓Configure Firebase, Sanity, Stripe, Gmail OAuth2
- ✓Wire up all environment variables
- ✓Create the first admin account
- ✓End-to-end smoke test: sign up → checkout → order
- ✓Vercel production deploy
- ✓1 video / written handover walkthrough
- ✓3-day post-handover bug fix window
Install + Branding
Delivery: 3–5 business days
- ✓Everything in the Starter package
- ✓Replace logo, favicon, and OG image
- ✓Apply your brand colors via Tailwind tokens
- ✓Update site name, footer, contact info
- ✓Seed initial product categories (up to 10)
- ✓Configure SSLCommerz (optional, BD market)
- ✓GA4 + DebugView verification
- ✓7-day post-handover bug fix window
Install + Customization
Delivery: 5–7 business days
- ✓Everything in the Standard package
- ✓Up to 3 hours of custom development
- ✓1 extra page or layout variant
- ✓1 small feature tweak (e.g. new product field, banner)
- ✓Connect a custom domain + SSL on Vercel
- ✓Email template customization
- ✓Performance pass (Lighthouse mobile ≥ 90)
- ✓14-day post-handover support
Hourly & ongoing work
| Type of work | Rate (USD) | Notes |
|---|---|---|
| Bug fix / small change | $20 / hour | Minimum 1 hour. Examples: text change, color tweak, link fix. |
| Custom feature / integration | $25 / hour | New API integration, custom page, dashboard widget. |
| Complex feature / refactor | $30 / hour | Multi-page flows, payment provider, data migration. |
| Performance / SEO audit | $80 (flat) | Lighthouse + Core Web Vitals report with actionable fixes. |
| Monthly retainer | $300 / month | Up to 15 hours/month. Priority response within 24h. |
What's not included
- Third-party service costs (Vercel Pro, Sanity paid plan, Google Workspace, etc.) — you pay these directly to the providers.
- Stripe / SSLCommerz business verification — done by you on their dashboards.
- Domain & SSL purchase — you buy from your preferred registrar; I configure the DNS.
- Content creation (product photos, descriptions, blog posts).
24Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| "Already exists" Firebase Admin warning | App initialised more than once | Import only from lib/firebase/admin.ts. |
| Sanity Studio is blank at /studio | Types out of sync | pnpm typegen, then restart dev server. |
| Stripe webhook rejected | Raw body missing or wrong signature | Verify STRIPE_WEBHOOK_SECRET matches the endpoint. |
| Sign-in works but admin redirects to / | admin claim missing | Add email to ADMIN_EMAILS or run sync-claims.ts --apply. |
| Env var changes have no effect | Dev server not restarted | Restart with pnpm dev. Vercel needs a redeploy. |
| Builds OOM on small machines | Webpack memory budget | Use Turbopack: pnpm dev:turbo, or set NODE_OPTIONS=--max-old-space-size=4096. |
pnpm install | Ignored build scripts (pnpm v10) | Allowlisted in pnpm.onlyBuiltDependencies. Run install again. |
| lefthook hooks not firing | Skipped install | pnpm exec lefthook install |
| GA4 Realtime shows nothing | Wrong Measurement ID or missing API secret | Verify GA4_MEASUREMENT_ID + GA4_API_SECRET. |
25Support
- Email — reactjsbd@gmail.com
- YouTube tutorials — @reactjsbd
- Website — reactbd.com
License. GoFarm is MIT-licensed. Everything in the repository is included — there are no locked features. Buyers of any pricing package get the same codebase, the same docs, and the same support channels.
You made it to the end!
That's every page, table, and config flag in GoFarm — nicely done. Now go build something delicious. 🥕🍅🥦