尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證正在載入完整 README。 以下為已儲存的摘錄。
Real estate marketplace and member portal. Listings are scraped from Zillow and Redfin through HasData, stored in Supabase, and searched from there. HasData is never called on a user's page view.
Stack: Next.js 16 (App Router), Supabase (Postgres, Auth, RLS), Tailwind CSS v4, Vercel (hosting and cron).
1. Install: npm install
2. Supabase: create a project at supabase.com, then:
3. Env: cp .env.example .env.local and fill in the values.
4. Run: npm run dev and open http://localhost:3000
5. Make yourself admin: sign up in the app, then in the Supabase SQL editor run:檢視完整 README ↗Real estate marketplace and member portal. Listings are scraped from Zillow and Redfin through HasData, stored in Supabase, and searched from there. HasData is never called on a user's page view.
Stack: Next.js 16 (App Router), Supabase (Postgres, Auth, RLS), Tailwind CSS v4, Vercel (hosting and cron).
Admin "Import" page ─┐
├─► runImport() ─► HasData /scrape/{zillow|redfin}/listing (paged)
Vercel Cron (daily) ─┘ │
├─► normalizeListing() → one schema for every provider
├─► upsert properties (dedupe on provider + provider_id)
└─► import_jobs log (pages, listings, credits, errors)
Visitors ─► /properties (filters in the URL) ─► Supabase (RLS: public read)
Members ─► /dashboard (favorites, saved searches; RLS: owner only)
| Path | Purpose |
|---|---|
src/lib/hasdata/client.ts | HasData REST client: x-api-key auth, timeout, retry on 429/5xx |
src/lib/hasdata/normalize.ts | Maps raw HasData listings to properties rows |
src/lib/hasdata/ingest.ts | Import pipeline: paging, upserts, job logging, scheduled sources |
src/app/api/admin/import | POST, admin-only one-off import |
src/app/api/cron/import | GET, re-runs all active import_sources (needs CRON_SECRET) |
src/lib/properties.ts | Marketplace search, filtering and sorting |
supabase/migrations/ | Schema and RLS policies |
npm installnpx supabase login
npx supabase link --project-ref <your-ref>
npm run db:push # applies supabase/migrations
cp .env.example .env.local and fill in the values.npm run dev and open http://localhost:3000update public.profiles set role = 'admin'
where id = (select id from auth.users where email = '[email protected]');
/admin/import, choose Zillow, enter "Austin, TX" with 1 page (costs 10 credits).HasData doesn't publish its response schema, so normalize.ts tries several likely field names. Pull a real sample and adjust the mappings to match:
npm run hasdata:sample -- zillow "Austin, TX" forSale
npm run hasdata:sample -- redfin "Austin, TX" forSale
Raw JSON is saved to samples/ (gitignored). The full raw listing is also stored in properties.raw, so data from earlier imports can be backfilled after a mapping changes.
http://localhost:3000/auth/confirm and your production URL./auth/confirm..env.example.vercel.json schedules /api/cron/import daily at 06:00 UTC. Vercel sends Authorization: Bearer $CRON_SECRET automatically.maxDuration = 300. Keep max_pages per source modest: each page is one HasData request taking roughly 5–20s.Each HasData listing request costs 10 credits, and every import job records credits_used.
Daily cron cost ≈ sum(max_pages of active sources) × 10 credits.
Zillow and Redfin restrict commercial redistribution of their listing data, and much of it is MLS-licensed. Get a legal review before publicly redisplaying scraped listings. An MLS/IDX feed is the compliant long-term source, and the provider column is there so one can be added alongside.
HasData's MCP server and agent skill let AI coding agents query HasData directly during development. They are not used at runtime.
claude mcp add --transport http hasdata "https://mcp.hasdata.com/mcp?apis=zillow,redfin" --header "x-api-key: <key>"
/dashboard: authenticated personal workspace with Buyer, Seller, and Landlord modes./dashboard/preview: public interactive sample workspace. Add ?role=buyer or ?role=landlord to open a particular preview. Preview edits are kept only in memory.Apply supabase/migrations/20261002020000_workspaces.sql after the existing migrations. It adds owner-scoped tables and row-level security; it does not modify imported marketplace inventory or platform admin roles. Workspace modes are self-selectable, while every record remains owned by its signed-in user.
Inventory records are private management records, not marketplace publications. Deals do not submit offers, and calendar plans do not contact agents or book external appointments. Rental collection, public listing publication, messaging, and electronic contracts are not connected.
Dashboard server actions validate inputs and authenticate each write. RLS also prevents cross-account access and restricts inventory writes to seller/landlord workspaces or existing agent/admin users. A sample workspace cannot write through the production actions.
Validation:
npm run lintnpm run buildnode --test scripts/dashboard-metrics.test.mjs (Node 22.18+ supports the TypeScript import)Design inspiration: the 21st.dev dashboard template collection and its sidebar / metric / table composition, adapted to SOL. Existing shadcn Button and Lucide icons are reused. No paid template was purchased or represented as installed.
Open /dashboard/preview?role=landlord for the interactive preview. Signed-in users select Landlord in their workspace selector; /dashboard/landlord also opens the dedicated dashboard when that role is selected.
Apply supabase/migrations/20261002030000_landlord_management.sql after the workspace migration to enable lease fields, owner-only deletion, and the rental ledger. This migration has passed local SQL/RLS checks but has not yet been applied to the hosted project. Management controls remain disabled until the schema is available.
The preview features the catalog rental at 77 Commercial St #2922S, Brooklyn. Tenant identities and financial history in the preview are illustrative. An empty authenticated portfolio offers a private draft copy of this rental; importing does not assert ownership or change the public catalog. Public publishing and payment collection are not connected.
Property deletion requires typing DELETE and cascades to the property's ledger. Recorded paid income and expenses drive the analytics; pending entries and future payments are excluded. Workspace changes never grant platform administrator access.
Additional checks: node scripts/landlord-metrics.test.mjs; local SQL validation of lease constraints, owner CRUD, cross-owner isolation, and ledger cascade; browser checks for property/ledger CRUD, calendar, reminders, chart filters, role switching, auth redirects, and 320/390/768/1440px layouts. No live tenant or account records were created for testing.