squidby ivoraExplore the demo

SMALL SQUID. OPEN OCEAN.

A charging experience
you can call your own.

Squid is an open-source example of building a vacation-rental charging business on the Ivora API. It keeps the guest experience, host relationships, and payments in your application.

One small app. Connected.

Run it on your machine.

npm install
cp .env.example .env
# Add your own credentials to .env
npm run db:migrate
npm run dev

No credentials yet? The landing page, host demo, and guest demo run independently. The demo doesn’t call Stripe or control a charger.

Give the database a home.

Create a Supabase project, enable email authentication, and run the files in supabase/migrations in filename order in its SQL editor. Alternatively, set SUPABASE_DB_URL and run the migration command above. Add your app’s /auth/callback and /login/confirm URLs to Supabase’s allowed redirect URLs.

Host data has row-level security. The fleet key and service-role key stay on the server. Guest sessions use private, HTTP-only browser cookies.

A warm welcome, in their inbox.

Set RESEND_API_KEY and RESEND_FROM_EMAIL to send sign-in links from your verified domain. Squid generates the token with Supabase, sends its own branded email, and asks the recipient to confirm before signing in. Keep email link tracking disabled. The included database migration provides rate limits shared across Vercel instances.

Without Resend, sign-in uses the email provider configured in Supabase. For either path, set your canonical app URL before inviting hosts.

Connect your own Stripe platform.

Enable Stripe Connect and use a test secret key while developing. Hosts complete Express onboarding. Checkout authorizes a $25 hold, then Squid captures the final metered amount with a 6% application fee. The unused hold is released. Stripe processing fees come from the platform’s share.

stripe listen --forward-to localhost:3000/api/stripe/webhook
# Save the printed whsec_ value as STRIPE_WEBHOOK_SECRET

Listen for checkout.session.completed and checkout.session.expired. Webhook signatures are verified against the raw request body. Browser redirects are never treated as payment confirmation.

Make yourself at home on Vercel.

Import the repository as a Next.js project, add the environment variables listed in .env.example, and set NEXT_PUBLIC_APP_URL to your canonical HTTPS domain. Configure the Stripe webhook and Supabase redirects for that domain before printing QR stickers.

The included job reconciles charging every minute, including when a guest closes their browser. A one-minute Vercel Cron schedule requires an eligible plan. You can also invoke the protected endpoint from your own scheduler:

GET /api/cron/reconcile
Authorization: Bearer <CRON_SECRET>

A reference implementation, with clear boundaries.

The current Ivora endpoint is preproduction. Validate the complete flow with an explicitly designated test charger and Stripe test accounts before accepting real guest payments. Unknown charger or payment outcomes are held for review instead of creating a second transaction. Automatic cutoff requests use a margin below the authorization amount; delayed meter reports or an offline charger can still cause overages that need reconciliation.

The repository includes setup, architecture, deployment, and contribution notes. Code is Apache-2.0 licensed. The included demo photograph retains its separate image license.

Squid is designed for Airbnb and other vacation-rental hosts. It is not affiliated with or endorsed by Airbnb.
Back to the good energy