Lodgebit is a multi-residence transient booking management platform built with Next.js 16. Each residence gets its own public-facing website while sharing a single admin panel.
- Multi-residence support — manage multiple properties from one admin panel
- Dynamic public pages — each residence gets a templated page at
/r/[slug] - Booking calendar — month view with real-time availability for guests and admins
- Unit gallery — bento-grid image gallery with lightbox per unit
- OCR contract scanning — extract booking details from contract photos via Google Cloud Vision
- Facebook auto-posting — post booking updates to a Facebook Page via Meta Graph API
- Dark mode — system-aware, toggle in admin topbar
- PWA — installable on mobile via
next-pwa - Google Sign-in — OAuth login for admins (only pre-registered emails allowed)
| Layer | Technology |
|---|---|
| Framework | Next.js 16.2 (App Router, Server Components) |
| Auth | NextAuth v5 (Credentials + Google OAuth) |
| Database | Supabase (PostgreSQL) |
| Storage | Supabase Storage (S3-compatible) |
| UI | shadcn/ui + Tailwind CSS v4 |
| Map | Leaflet (OpenStreetMap, no API key needed) |
| PWA | next-pwa |
| OCR | Google Cloud Vision API |
| Social | Meta Graph API |
git clone <repo-url>
cd lodgebit
npm installCopy .env.example to .env.local and fill in the values:
cp .env.example .env.local| Variable | Description |
|---|---|
NEXT_PUBLIC_SUPABASE_URL |
Your Supabase project URL |
NEXT_PUBLIC_SUPABASE_ANON_KEY |
Supabase anon/public key |
SUPABASE_SERVICE_ROLE_KEY |
Supabase service role key (server-only) |
AUTH_SECRET |
Random secret for NextAuth JWT — generate with openssl rand -base64 32 |
AUTH_URL |
Full base URL (e.g. http://localhost:3000) |
GOOGLE_CLIENT_ID |
Google OAuth client ID |
GOOGLE_CLIENT_SECRET |
Google OAuth client secret |
GOOGLE_CLOUD_VISION_API_KEY |
Google Cloud Vision API key (for OCR) |
META_APP_ID |
Meta (Facebook) App ID |
META_APP_SECRET |
Meta App Secret |
META_PAGE_ACCESS_TOKEN |
Long-lived Facebook Page access token |
Run the database migration in the Supabase SQL editor (database/migration.sql).
Create the following Storage buckets in Supabase → Storage:
| Bucket | Access | Purpose |
|---|---|---|
unit-images |
Public | Unit gallery photos |
residence-covers |
Public | Hero cover images for public pages |
guest-ids |
Private | Guest ID photo uploads |
contracts |
Private | Contract scan uploads |
Lodgebit uses bcrypt to hash passwords. You must never insert plain-text passwords into the database.
The pgcrypto extension is enabled by default on Supabase. Run this directly in the SQL editor:
INSERT INTO admins (full_name, email, password_hash, role)
VALUES (
'Your Name',
'you@example.com',
crypt('yourpassword', gen_salt('bf')),
'super_admin'
);gen_salt('bf') generates a bcrypt salt (blowfish). crypt() hashes the password against it. This is compatible with the bcryptjs verification used by the app.
If you prefer to generate the hash outside of Supabase:
node -e "const b = require('bcryptjs'); b.hash('yourpassword', 10).then(h => console.log(h));"Then insert the printed hash directly:
INSERT INTO admins (full_name, email, password_hash, role)
VALUES (
'Your Name',
'you@example.com',
'$2a$10$...', -- paste the hash from the command above
'super_admin'
);Use the same SQL INSERT for each additional admin. To give Google Sign-in access, insert the admin row with any placeholder password_hash — the password is never used when signing in via Google:
INSERT INTO admins (full_name, email, password_hash, role)
VALUES (
'Another Admin',
'colleague@example.com',
crypt(gen_random_uuid()::text, gen_salt('bf')), -- random unusable password
'admin'
);Roles:
super_adminhas full access.adminis a standard admin (role enforcement is handled at the app level).
Facebook posting requires a Page Access Token and the correct Page ID stored in Supabase per residence. Follow these steps exactly — order matters.
- Go to Meta for Developers → My Apps → Create App
- Choose Business type, name it (e.g.
Lodgebit) - Note the App ID and App Secret from Settings → Basic
Page Access Tokens generated from a long-lived user token do not expire. Page tokens generated from a short-lived token expire in 1 hour.
- Go to Tools → Graph API Explorer
- Select your app (e.g.
Lodgebit) under Meta App - Under User or Page, keep your user account selected
- Under Permissions, add:
pages_show_list,pages_read_engagement,pages_manage_posts - Click Generate Access Token → approve the OAuth dialog
- Click the ⓘ info icon next to the token → Open in Access Token Debugger → Extend Access Token → copy the 60-day user token
- Go back to Graph API Explorer → manually paste the 60-day token into the Access Token field
- Open the User or Page dropdown → under Page Access Tokens → click your Page name
- Copy the token now shown in the Access Token field
- Paste it into the Access Token Debugger — confirm Type = Page and Expires = Never (or ~60 days if app is in Development mode)
Note: The "Never" expiry only applies to apps in Live mode (requires Meta app review). In Development mode, tokens expire after ~60 days. Set a reminder to refresh before expiry.
In the Access Token Debugger, copy the Page ID shown next to your page name (e.g. 1099355329923830). Do not use a personal profile ID.
Navigate throught the application under residences page and update the Facebook Page ID
- Create a project at Google Cloud Console
- Enable the Google+ API or People API
- Create OAuth 2.0 credentials (Web application)
- Add authorized redirect URI:
http://localhost:3000/api/auth/callback/google - Copy Client ID and Client Secret to
.env.local
Only users whose email already exists in the
adminstable can sign in with Google.
npm run devOpen http://localhost:3000 to see the Lodgebit index. Admin panel: http://localhost:3000/admin
| URL | Description |
|---|---|
/ |
Lodgebit index — lists all residences |
/r/[slug] |
Public page for a specific residence |
/admin |
Redirects to /admin/calendar |
/admin/login |
Admin sign-in (credentials or Google) |
/admin/calendar |
Booking calendar view |
/admin/bookings |
All bookings list |
/admin/residences |
Manage residences |
/admin/units |
Manage units per residence |
/admin/ocr |
Scan and parse booking contracts |
/admin/facebook |
Facebook post history |
/admin/logs |
Booking change audit log |
- Push the repo to GitHub
- Import into Vercel
- Add all environment variables from
.env.examplein the Vercel project settings - Update
AUTH_URLto your production domain (e.g.https://yourdomain.com) - Add your production domain to Google OAuth authorized redirect URIs
The build command is
next build --webpack(required fornext-pwacompatibility with Turbopack).









