A modern, intelligent invoicing web app for freelancers and small businesses — designed to make invoice creation, tracking, and payments seamless.
Built with Next.js 15, TypeScript, Tailwind CSS, shadcn/ui, NextAuth, and Prisma (MongoDB).
Live Demo: [https://billq.vercel.app]
| Dashboard & Overview | Create Invoice with AI | Create Client |
|---|---|---|
![]() |
![]() |
![]() |
- Email/password authentication using NextAuth.
- Session management integrated with Prisma user model.
- User profile and company info stored in MongoDB.
- Invoice CRUD: Create, view, and edit invoices.
- Invoice Preview Page: Responsive layout with itemized details, client info, and summary totals.
- Download as PDF: Users can download invoice previews as a PDF using a custom
printPDF()utility. - Public Invoice Page (SSR):
- Fully server-rendered for SEO and OG tags.
- Dynamically generates metadata (
title,og:title, and description) from invoice data. - Fetches user and client information directly from the database via Prisma.
- Each invoice is linked to a specific client.
- Client details (name, email, address) are rendered dynamically.
Using Prisma ORM with a MongoDB adapter. Main models include:
UserClientInvoiceInvoiceItemPayment
To get a local copy up and running, follow these simple steps.
- Node.js (v22)
- npm or yarn
- Clone the repository:
git clone https://github.com/devadedeji/billq.git
- Navigate to the project directory:
cd billq - Install NPM packages:
npm install
-
Create a
.env.localfile in the root of the project. -
Add your configuration variables.
# .env.local DATABASE_URL="" GEMINI_API_KEY="" NEXTAUTH_SECRET="" GOOGLE_CLIENT_ID="" GOOGLE_CLIENT_SECRET=""" VERCEL_TOKEN="" STRIPE_PUBLIC_KEY="" STRIPE_SECRET_KEY="" NEXT_PUBLIC_APP_URL=http://localhost:3000
Start the development server:
npm run devOpen http://localhost:3000 to view it in the browser.
This project uses Vitest for unit and component tests, and Playwright for end-to-end (E2E) tests.
To run the component and integration tests, use the following command:
npm run test:all

