β οΈ Disclaimer: This project is for educational purposes only. We are not affiliated with, associated with, or endorsed by Zillow Group, Inc. in any way. "Zillow" is a registered trademark of Zillow Group, Inc. This project does not intend to infringe on any copyrights or trademarks. It is a learning exercise to demonstrate modern web development techniques.
A modern real estate platform that makes buying your first home simple and stress-free.
π― Who is this for? First-time homebuyers looking for a clean, intuitive property search experience, AND real estate agents who want to list properties, manage leads, and grow their business.
β‘ What problem does it solve? Traditional real estate platforms are cluttered and overwhelming. Nestwell provides a clean, modern interface with real-time updates, interactive maps, and a seamless agent subscription system.
π₯ Technical highlights:
- Real-time content with Sanity Live (no page refreshes!)
- Sanity Studio as your super admin dashboard
- Clerk Billing integration (no webhooks needed)
- Interactive Mapbox maps with property markers
- Type-safe schemas with auto-generated TypeScript (typegen)
- Server Actions + Server Components for optimal performance
- React 19 + React Compiler for blazing fast renders
Think of Nestwell as Zillow meets modern web development β a sleek real estate platform where homebuyers can browse listings, save favorites, and contact agents, while real estate professionals can manage their portfolio through a dedicated dashboard.
For homebuyers: Search properties by city, price range, bedrooms, bathrooms, and property type. Toggle between grid and map views. Save your favorites and reach out to agents when you're ready.
For agents: Subscribe to the Agent plan, complete your profile, and start listing properties. Manage leads from potential buyers, track analytics, update listing statuses, and monitor your performance from a comprehensive dashboard.
- π‘ First-time homebuyer browsing properties in a new city
- π’ Real estate agent managing their listing portfolio
- π Property investor researching market opportunities
- π± Relocating professional searching for apartments remotely
| Feature | Description |
|---|---|
| π Advanced Search | Filter by price, beds, baths, property type, amenities, and location |
| πΊοΈ Interactive Map | View properties on a Mapbox-powered map with price markers |
| πΎ Save Favorites | Build a collection of properties you love |
| π§ Contact Agents | Reach out to listing agents directly |
| πΌοΈ Image Galleries | Browse high-quality property photos |
| π± Responsive Design | Works beautifully on any device |
| Feature | Description |
|---|---|
| π Analytics Dashboard | Track views, leads, and performance with charts |
| π Unlimited Listings | Create and manage property listings with image uploads |
| π¬ Lead Inbox | View and manage buyer inquiries |
| π Address Autocomplete | Mapbox-powered address search with geocoding |
| βοΈ Listing Management | Update status (Active/Pending/Sold) |
| π€ Professional Profile | Showcase your bio, agency, and license |
| π³ Billing Management | Manage subscription via Clerk |
| Feature | Why It Matters |
|---|---|
| π Real-Time Updates | Sanity Live pushes content changes instantly β no page refreshes |
| ποΈ Sanity Studio | Built-in super admin dashboard at /studio for content management |
| π Schema + Typegen | Define content schemas once, auto-generate TypeScript types |
| π³ Clerk Billing | Subscription management without complex webhook setups |
| ποΈ Type-Safe Queries | GROQ queries with defineQuery + auto-generated types |
| βοΈ Server Actions | Form submissions handled server-side for security |
| π¨ React 19 + Compiler | Automatic optimizations for component renders |
| π Geocoding | Mapbox SDK for address autocomplete and coordinates |
| π Analytics Charts | Recharts for beautiful data visualization |
flowchart LR
A[Browse Properties] --> B{Authenticated?}
B -->|No| C[Sign Up/Sign In]
B -->|Yes| D[Save Favorites]
D --> E[Contact Agent]
E --> F[Agent Receives Lead]
flowchart TD
A[Visit Pricing Page] --> B[Subscribe via Clerk Billing]
B --> C{First Dashboard Access}
C --> D[Agent Document Created]
D --> E[Complete Onboarding]
E --> F[Start Creating Listings]
F --> G[Manage Leads]
erDiagram
USER ||--o{ SAVED_LISTING : saves
AGENT ||--o{ PROPERTY : lists
AGENT ||--o{ LEAD : receives
PROPERTY ||--o{ LEAD : generates
PROPERTY ||--o{ AMENITY : has
USER {
string clerkId PK
string name
string email
array savedListings
}
AGENT {
string userId PK
string name
string email
string licenseNumber
boolean onboardingComplete
}
PROPERTY {
string slug PK
string title
number price
string status
geopoint location
reference agent
}
LEAD {
reference property
reference agent
string buyerName
string status
}
Before you begin, ensure you have:
- Node.js 20+ installed
- pnpm (recommended) or npm
- Clerk account with Billing enabled
- Sanity project created
- Mapbox access token
1. Clone the repository
git clone https://github.com/your-username/nestwell.git
cd nestwell2. Install dependencies
pnpm install3. Set up environment variables
Create a .env.local file in the root directory:
# Clerk - Authentication & Billing
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_xxxxx
CLERK_SECRET_KEY=sk_test_xxxxx
NEXT_PUBLIC_CLERK_SIGN_IN_URL=/sign-in
NEXT_PUBLIC_CLERK_SIGN_UP_URL=/sign-up
# Sanity - CMS
NEXT_PUBLIC_SANITY_PROJECT_ID=your-project-id
NEXT_PUBLIC_SANITY_DATASET=production
SANITY_API_TOKEN=your-write-token
# Mapbox - Maps & Geocoding
NEXT_PUBLIC_MAPBOX_TOKEN=pk.xxxxx
MAPBOX_ACCESS_TOKEN=pk.xxxxx
# App URL (for metadata)
NEXT_PUBLIC_APP_URL=http://localhost:3000π Security Note: Never commit
.env.localto version control. The.gitignorealready excludes it.
π‘ Tip: Variables prefixed with
NEXT_PUBLIC_are exposed to the browser. Keep sensitive tokens (likeCLERK_SECRET_KEYandSANITY_API_TOKEN) without this prefix.
4. Set up Sanity
# Generate TypeScript types from your schema
pnpm typegen5. Set up Clerk Billing
In your Clerk Dashboard:
- Enable Billing in your application
- Create a "Free" plan (no price)
- Create an "Agent" plan at $29/month
- The app uses
has({ plan: "agent" })to check subscriptions
6. Seed the database (optional)
# Seed sample data
pnpm seed
# Clean and reseed
pnpm seed:clean7. Run the development server
pnpm devOpen http://localhost:3000 to see the app.
8. Access Sanity Studio (Admin Dashboard)
Navigate to http://localhost:3000/studio to manage content:
- Create/edit properties
- Manage agents and users
- View leads
- Full CMS control with real-time preview
- Created Clerk application with Billing enabled
- Created Sanity project and obtained tokens
- Got Mapbox access token
- Set up all environment variables
- Generated TypeScript types with
pnpm typegen - (Optional) Seeded database with sample data
| Collection | Purpose | Key Fields |
|---|---|---|
property |
Property listings | title, price, status, location, agent ref, amenities |
agent |
Agent profiles (linked to Clerk) | userId, name, licenseNumber |
user |
Homebuyer profiles | clerkId, savedListings |
lead |
Buyer inquiries | property ref, agent ref, status |
amenity |
Property amenities | name, icon, category |
-
Lazy Agent Creation: Agent documents are created on first dashboard access (after subscribing), not via webhooks. Clerk Billing is the source of truth.
-
Geopoint for Location: Properties use Sanity's
geopointtype for accurate map placement. -
Reference Relationships: Properties reference their agent, leads reference both property and agent for efficient querying.
-
Seed ID Prefixes: Seeded data uses
seed_prefixed IDs for easy cleanup during development.
Option 1: Vercel CLI
# Install Vercel CLI
pnpm i -g vercel
# Deploy
vercelOption 2: GitHub Integration
- Push your code to GitHub
- Import the repository in Vercel Dashboard
- Add environment variables
- Deploy!
- Verify all environment variables are set in Vercel
- Test authentication flow
- Test subscription/billing flow
- Verify Sanity content is loading
- Check maps are rendering correctly
- Set up CORS origins in Sanity (if needed)
- Vercel Analytics - Page performance
- Clerk Dashboard - Auth metrics
- Sanity Manage - Content analytics
| Problem | Solution |
|---|---|
NEXT_PUBLIC_SANITY_PROJECT_ID is undefined |
Make sure .env.local is in the root directory and restart the dev server |
| Sanity types not generating | Run pnpm typegen after schema changes |
| Maps not showing | Verify NEXT_PUBLIC_MAPBOX_TOKEN is set correctly |
| Address autocomplete not working | Check both NEXT_PUBLIC_MAPBOX_TOKEN and MAPBOX_ACCESS_TOKEN |
| Problem | Solution |
|---|---|
| Sign-in redirects to wrong page | Check NEXT_PUBLIC_CLERK_SIGN_IN_URL in env |
| Billing not working | Enable Billing in Clerk Dashboard and create plans |
| Agent dashboard 404s | Subscribe to Agent plan first, then access dashboard |
| Problem | Solution |
|---|---|
| No properties showing | Run pnpm seed to add sample data |
| Images not loading | Check Sanity CORS settings and image URL configuration |
| Real-time not working | Verify SanityLive component is rendered in layout |
| Problem | Solution |
|---|---|
| Build fails on Vercel | Ensure all env variables are added in Vercel settings |
| Type errors after schema change | Run pnpm typegen and commit generated files |
Ready to level up? Try adding these features:
- Dark mode toggle with
next-themes - Property comparison tool (compare 2-3 properties side by side)
- Virtual tour integration (Matterport embed)
- Neighborhood insights section
- AI-powered property descriptions (OpenAI)
- Smart property recommendations based on saved listings
- Chatbot for property inquiries
- Image auto-tagging for amenities
- Add Redis caching for search results
- Implement ISR for property pages
- Add Algolia for full-text search
- Set up scheduled Sanity backups
- Featured listing upgrades for agents
- Lead priority tiers
- Analytics dashboard for agents (views, saves, etc.)
- Referral program
This project is licensed under CC BY-NC 4.0.
- Use this code for personal projects
- Use this code for learning purposes
- Modify and adapt the code
- Share with attribution
# Development
pnpm dev # Start dev server
pnpm build # Build for production
pnpm start # Start production server
pnpm lint # Run Biome linter
pnpm format # Format code
# Database
pnpm typegen # Generate Sanity types
pnpm seed # Seed sample data
pnpm seed:clean # Clean and reseedβββ app/
β βββ (main)/ # Public pages (home, properties, pricing)
β βββ (dashboard)/ # Agent dashboard (protected)
β β βββ dashboard/
β β βββ analytics/ # Performance charts
β β βββ billing/ # Subscription management
β β βββ leads/ # Lead inbox
β β βββ listings/ # Property management
β βββ studio/ # Sanity Studio
βββ components/
β βββ forms/ # Form components + fields
β βββ layout/ # Navbar, Footer, Sidebar
β βββ map/ # Mapbox components
β βββ property/ # Property cards, grids, filters
β βββ ui/ # shadcn/ui components
βββ actions/ # Server Actions
βββ lib/
β βββ sanity/ # Client, queries, live, upload
β βββ hooks/ # Custom React hooks
β βββ geocoding.ts # Mapbox geocoding utilities
βββ sanity/schemas/ # Content schemas
βββ scripts/seed/ # Database seeding
| Concept | Description |
|---|---|
| Server Actions | Functions in actions/ that run server-side |
| Sanity Live | Real-time content updates via SanityLive component |
| Clerk Billing | Subscription checks via has({ plan: "agent" }) |
| defineQuery | Type-safe GROQ query builder from next-sanity |
| Typegen | Auto-generate TS types from Sanity schemas |