Lendly is a mobile-first web app for lending everyday items between neighbors. Users can be both owners and borrowers from the same account, browse nearby listings, request loans for date ranges, and complete the full request → loan → return → review loop.
- Authentication + profiles (Supabase Auth + Postgres)
- Email/password sign-in and sign-up
- Onboarding flow for name + location (city + lat/lng)
- Public profile pages and editable own profile
- Profile photo upload (Supabase Storage)
- Listings
- Create, edit, and unlist items
- Photo upload generates listing information (Gemini)
- Browse feed with category + radius filtering
- Requests, loans, and returns
- Borrow requests with date range + message
- Owner inbox with accept/decline flow
- Overlap protection for accepted bookings (app logic + DB constraint/RPC)
- Loan detail page, return flow, and post-loan reviews
- Loan issue tracking
- Extension requests, damage reports, and late-return flags tied to a loan
- Search
- Text matching search
- Optional conversational search powered by Gemini (returns ranked matches with reasons)
- AI-assisted listing creation (optional)
- Generate a draft listing from a single photo via Gemini
- Mobile-first UI
- Designed for mobile viewports
- Floating bottom tab bar, loading shell, error boundary, and toast notifications
- Framework: Next.js 16 (App Router)
- Language: TypeScript
- UI / styling: Tailwind CSS 4, shadcn/ui-style components, Base UI primitives
- Backend: Supabase (Auth, Postgres, Storage, RLS, RPC)
- Verification (optional): Stripe (Stripe Identity + Checkout in
mode="setup"for card-on-file) - AI (optional): Google Gemini via
@google/genai
This is the full list of third-party packages declared in package.json.
nextreact,react-dom@supabase/supabase-js,@supabase/ssrstripe@google/genaireact-hook-form,@hookform/resolverszod@base-ui/reactlucide-reactshadcnthree,@types/threeclass-variance-authority,clsx,tailwind-mergetw-animate-css
typescripteslint,eslint-config-nexttailwindcss,@tailwindcss/postcss@types/node,@types/react,@types/react-dom
- Node.js: recommended Node 20+ (project uses modern Next + TypeScript + ESM tests)
- Supabase project (local or hosted)
- Optional:
- Gemini API key for AI listing drafts + conversational search
- Stripe secret key for ID verification and card setup routes
npm installCreate a .env.local file at the repo root with:
# Supabase (required)
NEXT_PUBLIC_SUPABASE_URL=...
NEXT_PUBLIC_SUPABASE_ANON_KEY=...
# AI (optional)
GEMINI_API_KEY=...
# Stripe (optional)
STRIPE_SECRET_KEY=...Notes:
- If
GEMINI_API_KEYis missing, AI features fail safely (draft listing returnsunclear_photo, conversational search returns no matches). - If
STRIPE_SECRET_KEYis missing, Stripe-powered routes (ID verification / card setup) will throw if visited.
- Apply the base schema:
supabase/schema.sql - Apply any additive migrations in
supabase/migrations/
Create the Supabase Storage buckets referenced by the app:
avatarsitem-photos
The schema includes:
- Core tables (
users,items,requests,loans,reviews,loan_exceptions) - RLS policies and indexes
- Overlap protection via an exclusion constraint and an RPC-based transactional accept flow (
accept_request_transaction) - A transactional return RPC (
return_loan_transaction) - Storage policies for the buckets used by the app (
item-photos,avatars)
npm run devThen open http://localhost:3000.
npm run dev— start Next.js dev servernpm run build— production buildnpm run start— run the production servernpm run lint— ESLintnpm test— Node’s built-in test runner (seelib/*.test.mts)
- Reverse geocoding:
lib/geocode.tsuses OpenStreetMap Nominatim (https://nominatim.openstreetmap.org) to turn a lat/lng into a city/state label. - Images: Next Image is configured to allow
*.supabase.coStorage URLs.
app/— Next.js routes (browse, inbox, loans, profile, onboarding, auth)components/— UI components (forms, cards, mobile shell/nav)lib/actions/— server actions for writes (listings, requests, loans, reviews, profile, onboarding, loan issues)lib/supabase/— Supabase SSR helpers + Storage signingsupabase/— schema + migrations