A modern Next.js app that converts books into an interactive AI experience. Upload PDFs, search book content, and chat with your books using voice-powered AI and subscription-managed access.
bookWorm is built with:
- Next.js 16
- React 19
- TypeScript
- Clerk for authentication
- MongoDB + Mongoose for persistent storage
- VAPI AI voice assistant integration
- PDF upload and book parsing
- Subscription and billing UI via Clerk pricing pages
- Tailwind CSS + shadcn/ui for styling
- User authentication with Clerk
- Book upload and PDF handling
- MongoDB-backed book metadata and segment storage
- Voice conversation control via VAPI and ElevenLabs voices
- Searchable book content
- Subscription management page
- Protected routes for authenticated users
bookworm/
├── .clerk/ # Clerk auth config
├── app/ # Next.js app routes and pages
│ ├── (root)/
│ │ └── page.tsx # Home page
│ ├── books/
│ │ ├── [slug]/
│ │ │ └── page.tsx # Book detail page with VAPI controls
│ │ ├── new/
│ │ │ └── page.tsx # Upload new book page
│ │ ├── subscriptions/
│ │ │ └── page.tsx # Subscription pricing page
│ │ ├── sign-in/
│ │ │ └── [[...sign-in]]/
│ │ │ └── page.tsx # Clerk sign-in route
│ │ ├── sign-up/
│ │ │ └── [[...sign-up]]/
│ │ │ └── page.tsx # Clerk sign-up route
│ │ ├── api/
│ │ │ ├── upload/
│ │ │ │ └── route.ts # Blob upload API route
│ │ │ └── vapi/
│ │ │ └── search-book/
│ │ │ └── route.ts # VAPI helper route
│ │ └── layout.tsx # Root layout with Clerk provider
├── components/ # Reusable UI components
│ ├── BannerSection.tsx
│ ├── BookCard.tsx
│ ├── BookSearchBar.tsx
│ ├── BooksSection.tsx
│ ├── FileUploader.tsx
│ ├── LoadingOverlay.tsx
│ ├── Navbar.tsx
│ ├── Transcript.tsx
│ ├── UplaodBook.tsx
│ ├── VapiControls.tsx
│ ├── VoiceSelector.tsx
│ └── ui/
│ ├── button.tsx
│ ├── form.tsx
│ ├── input.tsx
│ ├── label.tsx
│ ├── radio-group.tsx
│ └── sonner.tsx
├── database/ # MongoDB connection and models
│ ├── mongoose.ts
│ └── models/
│ ├── bookModel.ts
│ ├── bookSegModel.ts
│ └── voiceSessionModel.ts
├── hooks/ # Custom React hooks
│ ├── draft.ts
│ ├── useSubscription.ts
│ └── useVapi.ts
├── lib/ # Shared utils and actions
│ ├── actions/
│ │ ├── book.actions.ts
│ │ └── session.actions.ts
│ ├── constants.ts
│ ├── subscriptionServer.ts
│ ├── types.ts
│ ├── utils.ts
│ └── zod.ts
├── preview/ # Screenshot assets for this README
│ ├── preview 1.png
│ ├── preview 4.png
│ ├── preview2.png
│ └── preview3.png
├── next-env.d.ts
├── next.config.ts
├── package-lock.json
├── package.json
├── postcss.config.mjs
├── proxy.ts
├── README.md
├── tsconfig.json
└── types.d.ts
- Next.js 16
- React 19
- TypeScript
- Tailwind CSS v4
- Clerk Authentication
- MongoDB + Mongoose
- VAPI AI (
@vapi-ai/web) - PDF.js (
pdfjs-dist) - Vercel Blob Storage (
@vercel/blob) - Radix UI + shadcn/ui
- React Hook Form + Zod
- Sonner toast notifications
- Lucide icons
Create a .env.local file at the project root with the following values:
MONGODB_URI=<your-mongodb-connection-string>
NEXT_PUBLIC_VAPI_API_KEY=<your-vapi-public-api-key>
NEXT_PUBLIC_ASSISTANT_ID=<your-vapi-assistant-id>
BLOB_READ_WRITE_TOKEN=<vercel-blob-read-write-token>Additional Clerk environment variables are required for authentication and deployment:
CLERK_FRONTEND_APICLERK_PUBLISHABLE_KEYCLERK_SECRET_KEYCLERK_JWT_KEYCLERK_JWT_ISSUER
- Create a Clerk application at https://dashboard.clerk.com.
- In the Clerk dashboard, add a new frontend application and copy:
Publishable keyFrontend API
- Under API keys, create a new secret key and copy:
Secret keyJWT keyJWT issuer
- Add those values to
.env.local. - Use the Clerk app URLs as the redirect callback for sign-in/sign-up if required by your Clerk app settings.
- Create a VAPI account and log in to the VAPI dashboard.
- Create or select a voice assistant and copy the public API key.
- Copy the assistant ID for the assistant you want to use.
- Add these values to
.env.local:
NEXT_PUBLIC_VAPI_API_KEY=<your-vapi-public-api-key>
NEXT_PUBLIC_ASSISTANT_ID=<your-vapi-assistant-id>- In this app,
hooks/useVapi.tsusesNEXT_PUBLIC_VAPI_API_KEYto initialize the VAPI client andNEXT_PUBLIC_ASSISTANT_IDto start the assistant. - If your assistant requires custom settings, configure them in the VAPI dashboard and ensure the assistant ID matches the one saved in
.env.local.
VAPI integration requires a valid assistant ID and public API key. The app loads voice controls on the book detail page via
components/VapiControls.tsx.
- Clone the repository:
git clone <repo-url>
cd bookworm- Install dependencies:
npm install-
Create
.env.localwith the required variables. -
Start the development server:
npm run dev- Open the app in your browser:
http://localhost:3000To build the project for production:
npm run buildStart the production server locally:
npm start- The app uses
proxy.tsto protect authenticated routes with Clerk middleware. database/mongoose.tsconnects to MongoDB and caches the connection.hooks/useVapi.tsinitializes the VAPI client and manages audio state.lib/actions/book.actions.tsis responsible for book creation, listing, and searching.app/api/upload/route.tshandles secure blob uploads for book files.
This app is ready to deploy to Vercel. Make sure your environment variables are configured in the Vercel dashboard, including Clerk and VAPI keys.
This project is provided as-is. Update the README with your license details if needed.



