A mobile-first sales tool for Riverside Lawncare. Customers browse the plants we commonly use; employees log in to manage the catalog, bulk-import from Excel, and build branded plant lists for customers in the field.
- Public — anyone can browse + filter plants, and start a list.
- Employees only — add / edit / disable / delete plants, bulk-import from Excel, save customer plant lists, download a branded PNG to text/AirDrop.
- Next.js 15 (App Router) + TypeScript + Tailwind
- Supabase — Postgres, Auth, Storage (free tier is plenty)
xlsx(SheetJS) for the Excel template + parserhtml-to-imagefor the PNG exportzodfor validation- Deploys to Vercel
You'll do this once. After this everything is managed from the website itself.
-
Create a Supabase project at https://supabase.com (free tier).
-
Run the schema. Open the project → SQL Editor → paste the contents of
supabase/schema.sql→ Run. This creates all tables, row-level security, and theplant-imagesstorage bucket. -
Add employee logins. Supabase → Authentication → Users → Add user. Enter an email + password for each Riverside employee. Disable public signups (they're disabled by default — there is no signup UI in the app).
-
Copy env vars. In Supabase → Project Settings → API, copy:
- Project URL →
NEXT_PUBLIC_SUPABASE_URL anon publickey →NEXT_PUBLIC_SUPABASE_ANON_KEYservice_rolekey →SUPABASE_SERVICE_ROLE_KEY(used by the Excel importer; never commit or expose to the browser)
Create
.env.local(copy from.env.example) and paste them in. - Project URL →
-
Drop your logo at
public/riversidelogo.png. The header + PNG export both pull from there.
npm install
npm run devVisit http://localhost:3000.
- Push the repo to GitHub.
- Import on https://vercel.com.
- Add the same three env vars to Vercel's project settings.
- Deploy. The free tier covers all initial usage.
- Browse plants —
/ - Add a plant —
/admin/plants/new(after sign-in) - Bulk import —
/admin/import. Click Download template, fill in the spreadsheet, upload it. Errors are shown row-by-row before anything is written. Theimage_urlcolumn lets you point to a public image URL and the importer will download & store it automatically. - Build a customer list — browse the catalog, tap Add on plants, then
the floating Build list button. Enter customer name, hit
Download PNG for an image you can text the customer, or Save project
(employees only) to keep it under
/admin/projects. - Disable a plant instead of deleting — keeps it attached to old saved projects but hides it from the public catalog.
The data model is already in place for these in supabase/schema.sql:
- Pavers catalog (
paverstable) - Gallery of recent jobs with plant tagging (
gallery_jobs,gallery_job_plants) - PDF export and email send (via Resend) — currently PNG only
app/
page.tsx public catalog
plants/[id]/ plant detail
login/ employee sign-in
admin/ authed-only: plant CRUD, import, saved lists
builder/ selection builder + saved projects
api/import/ Excel → Supabase
api/projects/ save customer lists
components/ UI building blocks
lib/
supabase/{client,server,admin}.ts
plants.ts, excel.ts, categories.ts
supabase/schema.sql paste once into Supabase SQL editor