A full-stack video sharing platform built with Next.js, Better Auth, Xata, Drizzle ORM, Bunny CDN, and Arcjet.
Watch the full demo on YouTube:
- π Secure authentication with Better Auth
- π₯ Video upload and streaming via Bunny CDN
- π§ Smart database and search powered by Xata.io
- π‘οΈ Bot detection and security rules via Arcjet
- ποΈ Type-safe ORM with Drizzle
π Arcjet
Arcjet is a developer-first security platform that integrates bot protection, rate limiting, email validation, and attack protection into your application with minimal code.
It offers customizable protection for forms, login pages, and API routes, supporting frameworks like Node.js, Next.js, Deno, Bun, Remix, SvelteKit, and NestJS.
π₯ Bunny.net
Bunny.net is a developer-friendly video delivery platform offering global CDN, edge storage, adaptive streaming, and a customizable player.
It simplifies video management with features like automatic encoding, token-based security, and real-time analytics β ideal for seamless, secure, and scalable video streaming.
π‘οΈ Better Auth
Better Auth is a TypeScript-first authentication and authorization library that simplifies implementing secure login, two-factor authentication, and social sign-ins, all while supporting multi-tenancy.
π§ Drizzle ORM
Drizzle ORM is a type-safe, lightweight ORM for SQL databases. It provides a modern solution for interacting with databases using TypeScript, supporting migrations, queries, and schema management.
β‘ Next.js
Next.js is a powerful React framework that enables the development of fast, scalable web applications with features like server-side rendering (SSR), static site generation (SSG), and API routes for full-stack development.
π¨ Tailwind CSS
Tailwind CSS is a utility-first CSS framework that allows developers to design custom user interfaces using low-level utility classes directly in HTML β greatly streamlining the design process.
π§Ύ TypeScript
TypeScript is a superset of JavaScript that adds static typing, providing better tooling, code quality, and error detection, making it ideal for building large-scale applications.
π Xata
Xata is a serverless PostgreSQL platform offering auto-scaling, zero-downtime schema migrations, real-time branching, and built-in full-text search.
It provides a spreadsheet-like UI for intuitive data management, enhancing modern development workflows.
git clone https://github.com/mistrypavankumar/loom-clone.git
cd loom-clone
npm installRename .env.example to .env and add your keys:
# Public API URL
NEXT_PUBLIC_API_URL=http://localhost:3000
# Better Auth
BETTER_AUTH_SECRET=
BETTER_AUTH_URL=http://localhost:3000
# Google OAuth
GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=
# Xata DB
XATA_API_KEY=
DATABASE_URL=
DATABASE_URL_POSTGRES=
# Bunny CDN
BUNNY_STORAGE_ACCESS_KEY=
BUNNY_STREAM_ACCESS_KEY=
BUNNY_LIBRARY_ID=
# Arcjet (Security middleware)
ARCJET_API_KEY=- Go to Better Auth Docs
- Add values for:
BETTER_AUTH_SECRETGOOGLE_CLIENT_IDandGOOGLE_CLIENT_SECRETfrom Google Console
- Make sure redirect URI is set to:
http://localhost:3000/api/auth/callback/google
- Sign up at xata.io
- Create a database.
- In your terminal:
npm install -g @xata.io/cli
xata init
# Select your database, choose TypeScriptThis creates xata.config.ts and links your app to the database.
Install dependencies:
npm install drizzle-orm
npm install -D drizzle-kit
npm install pgnpm install dotenvYouβll also need a drizzle.config.ts file to generate schema types from Postgres. So create this file in root folder
and add below code. (Only if file not exists)
import {config} from "dotenv";
import {defineConfig} from "drizzle-kit";
config({
path: "./.env",
})
export default defineConfig({
schema: "./drizzle/schema.ts",
out: "./drizzle/migrations",
dialect: "postgresql",
dbCredentials: {
url: process.env.DATABASE_URL_POSTGRES!
}
})
- Go to bunny.net
- Create:
- Storage Zone
- Video Library
- Set the following keys in
.env:BUNNY_STORAGE_ACCESS_KEYBUNNY_STREAM_ACCESS_KEYBUNNY_LIBRARY_ID
- Sign up at arcjet.com
- Copy your
ARCJET_API_KEYto.env - Arcjet provides:
- Bot detection
- Rate limiting
- Attack protection
Middleware is configured using createMiddleware(validate) in middleware.ts.
npm run devVisit: http://localhost:3000
loom-clone/
βββ .xata/ # Xata-generated config & schema files
βββ app/ # Next.js app directory (routes, layout)
βββ components/ # Reusable React components
βββ constants/ # Constant values (e.g., limits, enums)
βββ drizzle/ # Drizzle ORM schema and DB setup
βββ fonts/ # Custom font files
βββ lib/ # Utility functions and third-party wrappers (e.g., Arcjet, auth)
βββ node_modules/ # Installed dependencies
βββ public/ # Static files like images, icons
βββ .env # Environment variables
βββ .gitignore # Git ignored files
βββ .prettierrc # Prettier code formatting config
βββ drizzle.config.ts # Drizzle ORM CLI config
βββ eslint.config.mjs # ESLint rules
βββ middleware.ts # Global middleware for auth and Arcjet protection
βββ next.config.ts # Next.js config file
βββ package.json # Project metadata and scripts
βββ postcss.config.mjs # PostCSS config for TailwindCSS
βββ tsconfig.json # TypeScript config
βββ xata.ts # Xata DB client (generated)
βββ README.md # Project documentation (youβre reading it!)
xata init # Setup Xata connection
drizzle-kit push # Push schema changes
npm run dev # Start local serverMIT Β© 2025 Pavan Kumar Mistry
