You are a senior full-stack developer tasked with building a fully functional MVP of 'ISBN Insight' using Next.js (App Router), Tailwind CSS, and Drizzle ORM. The application will allow users to input ISBNs and visualize related book data.
**1. PROJECT OVERVIEW:**
'ISBN Insight' aims to transform how users interact with book data. The core problem it solves is the fragmented and often inaccessible nature of detailed book information beyond basic metadata. Users typically have to visit multiple sources to gather information about a book's history, publisher, language trends, genre distribution, etc. Our value proposition is to provide a centralized, visually engaging platform where users can input an ISBN and instantly access a rich, visualized dashboard of comprehensive data, fostering deeper understanding and discovery for book enthusiasts, researchers, and collectors.
**2. TECH STACK:**
- **Framework:** Next.js (App Router)
- **UI Library:** shadcn/ui (for accessible, reusable components)
- **Styling:** Tailwind CSS
- **Database:** PostgreSQL (with Neon serverless option)
- **ORM:** Drizzle ORM (for type-safe database interactions)
- **Authentication:** NextAuth.js (with PostgreSQL adapter)
- **State Management:** React Context API / Zustand (for global state), Server State Management via Next.js data fetching utilities.
- **Data Fetching:** Server Components, Client Components, Route Handlers (API).
- **Charting:** Recharts or Chart.js (for data visualization).
- **Deployment:** Vercel
- **Other:** TypeScript, ESLint, Prettier
**3. DATABASE SCHEMA (Drizzle ORM - PostgreSQL):**
```typescript
// db/schema.ts
import { pgTable, text, timestamp, integer, uuid, varchar, boolean, pgEnum } from 'drizzle-orm/pg-core';
import { relations } from 'drizzle-orm';
// Enum for user roles if needed later
export const userRoleEnum = pgEnum('user_role', ['admin', 'user']);
// User Table
export const users = pgTable('users', {
id: uuid('id').primaryKey().defaultRandom(),
name: text('name'),
email: varchar('email', { length: 255 }).notNull().unique(),
emailVerified: timestamp('email_verified', { mode: 'date' }),
image: text('image'),
role: userRoleEnum('role').default('user'),
createdAt: timestamp('created_at').defaultNow(),
updatedAt: timestamp('updated_at').defaultNow(),
});
// Session Table (for NextAuth.js)
export const sessions = pgTable('sessions', {
sessionToken: text('session_token').primaryKey(),
userId: uuid('user_id').notNull().references(() => users.id, { onDelete: 'cascade' }),
expires: timestamp('expires', { mode: 'date' }).notNull(),
});
// Verification Token Table (for NextAuth.js)
export const verificationTokens = pgTable('verification_tokens', {
identifier: text('identifier').notNull(),
token: text('token').notNull(),
expires: timestamp('expires', { mode: 'date' }).notNull(),
}).primaryKey(identifier, token);
// Book Metadata Table
export const books = pgTable('books', {
id: uuid('id').primaryKey().defaultRandom(),
isbn: varchar('isbn', { length: 13 }).notNull().unique(), // ISBN-13
title: varchar('title', { length: 255 }).notNull(),
subtitle: varchar('subtitle', { length: 255 }),
authors: text('authors').array().notNull(), // Store as array
publisher: varchar('publisher', { length: 255 }),
language: varchar('language', { length: 10 }),
pages: integer('pages'),
publicationDate: timestamp('publication_date', { mode: 'date' }),
genre: varchar('genre', { length: 100 }), // Simplified for MVP
description: text('description'),
coverImageUrl: text('cover_image_url'),
createdAt: timestamp('created_at').defaultNow(),
updatedAt: timestamp('updated_at').defaultNow(),
});
// User Book Lists Table (e.g., 'Read', 'To Read', 'Favorites')
export const userBookLists = pgTable('user_book_lists', {
id: uuid('id').primaryKey().defaultRandom(),
userId: uuid('user_id').notNull().references(() => users.id, { onDelete: 'cascade' }),
bookId: uuid('book_id').notNull().references(() => books.id, { onDelete: 'cascade' }),
listType: varchar('list_type', { length: 50 }).notNull(), // e.g., 'read', 'wishlist', 'favorites'
addedAt: timestamp('added_at').defaultNow(),
});
// Relations (for easier querying)
export const usersRelations = relations(users, ({ many }) => ({
userBookLists: many(userBookLists),
}));
export const booksRelations = relations(books, ({ many }) => ({
userBookLists: many(userBookLists),
}));
export const userBookListsRelations = relations(userBookLists, ({ one }) => ({
user: one(users, {
fields: [userBookLists.userId],
references: [users.id],
}),
book: one(books, {
fields: [userBookLists.bookId],
references: [books.id],
}),
}));
```
**4. CORE FEATURES & USER FLOW:**
* **A. User Authentication:**
* **Flow:** User lands on the homepage. Clicks 'Sign In / Sign Up'. Presented with options (e.g., Google, Email/Password). Upon successful authentication, user is redirected to their dashboard. Protected routes (Dashboard, My Lists) redirect to sign-in if not authenticated.
* **Implementation:** Use NextAuth.js with email/password and OAuth providers (e.g., Google).
* **B. ISBN Search & Book Data Display:**
* **Flow:** Authenticated user sees a prominent search bar on the dashboard or a dedicated search page. User inputs a valid ISBN-13. Upon submission, the system queries the database for the ISBN. If found, it displays the book's cover, title, author(s), publisher, language, page count, and publication date. If not found in our DB, an external API (e.g., Open Library API, Google Books API) is called to fetch data. Fetched data is then stored in our `books` table. The UI displays the retrieved metadata.
* **Implementation:** A search form component triggering a server action or API route. Data fetching logic handles both DB lookup and external API calls. Displayed using a dedicated `BookDetailsCard` component.
* **C. Data Visualization Dashboard:**
* **Flow:** After a book is searched or viewed, a dashboard section displays visualizations based on the book's metadata and potentially aggregated data from similar books or user lists. Initial MVP visualizations:
* Publication Date Trend (if multiple books are analyzed or a list exists).
* Language Distribution (for a user's list).
* Genre Distribution (for a user's list).
* Publisher Distribution (for a user's list).
* **Implementation:** Fetch aggregated data from the `books` and `userBookLists` tables. Use a charting library (Recharts) to render components like `BarChart`, `PieChart`, `LineChart` based on the data.
* **D. User Lists (My Bookshelf):**
* **Flow:** User navigates to 'My Bookshelf'. They can view books added to different lists ('Read', 'Wishlist', 'Favorites'). A button on the `BookDetailsCard` allows adding the current book to one or more lists. Users can remove books from lists.
* **Implementation:** Create entries in the `userBookLists` table via server actions. Display list items on a dedicated 'My Bookshelf' page, fetching data using relations.
**5. API & DATA FETCHING:**
* **Authentication API:** Handled by NextAuth.js (`/api/auth/[...nextauth]`).
* **ISBN Search API Route (`/api/books/isbn/[isbn]`):**
* **Method:** GET
* **Logic:** Checks `books` table first. If not found, calls external API (e.g., Open Library), stores the result in `books`, and returns the data.
* **Response (Success):** `{ success: true, data: Book[] }` or `{ success: true, data: null }`
* **Response (Error):** `{ success: false, error: 'message' }`
* **User List API Routes (`/api/user/lists`, `/api/user/lists/:bookId`):**
* **Method:** POST (add book to list), DELETE (remove book from list).
* **Logic:** Interacts with `userBookLists` table, ensuring user ownership.
* **Request Body (POST):** `{ bookId: string, listType: string }`
* **Response:** `{ success: true/false, message: string }`
* **Data Fetching in Components:**
* **Server Components:** Fetch data directly within the component (e.g., for dashboard pages, initial loads).
* **Client Components:** Use `fetch` with caching disabled or libraries like SWR/React Query for dynamic data updates (e.g., adding to list, search results).
* **Server Actions:** Used for mutations (POST, DELETE) directly from client components without needing separate API routes for simple CRUD operations.
**6. COMPONENT BREAKDOWN (Next.js App Router):**
* **`app/layout.tsx`:** Root layout (includes providers, Tailwind base CSS, global elements).
* **`app/page.tsx`:** Landing Page (Public - Feature highlights, Call to Action).
* **`app/(auth)/sign-in/page.tsx`:** Sign-in page (using NextAuth.js components).
* **`app/(app)/layout.tsx`:** Authenticated App Layout (includes sidebar/navbar, main content area).
* **`app/(app)/dashboard/page.tsx`:** User Dashboard (Protected). Contains search bar, overview of recent searches, quick stats, links to 'My Bookshelf'. Fetches initial user data.
* **`app/(app)/books/[isbn]/page.tsx`:** Dynamic route for displaying book details and visualizations.
* **`components/ui/BookDetailsCard.tsx`:** Displays core book info (cover, title, author, etc.). Includes 'Add to List' button.
* **`components/charts/GenreChart.tsx`, `components/charts/LanguageChart.tsx`, etc.:** Reusable chart components.
* **`components/ui/SearchBar.tsx`:** Input field for ISBN search.
* **`app/(app)/my-bookshelf/page.tsx`:** User's bookshelf page (Protected). Displays books categorized by lists ('Read', 'Wishlist', 'Favorites'). Allows removal.
* **`components/ui/BookListItem.tsx`:** Renders a single book within a list.
* **`components/layout/Navbar.tsx`:** Top navigation bar (Logo, links, user menu/sign out).
* **`components/layout/Sidebar.tsx`:** (Optional) Sidebar navigation for authenticated sections.
* **`components/auth/SignInForm.tsx`, `components/auth/SignUpForm.tsx`:** Forms for authentication.
* **`components/ui/DataTable.tsx`:** (Future use) For displaying user book lists in a tabular format.
* **`components/ui/AlertDialog.tsx`, `components/ui/Toast.tsx`:** For confirmations, errors, and notifications (using shadcn/ui).
**7. UI/UX DESIGN & VISUAL IDENTITY:**
* **Style:** Minimalist Clean with subtle gradient accents.
* **Color Palette:**
* Primary (Dark background): `#121212`
* Secondary (Darker UI elements): `#1E1E1E`
* Accent (Interactive elements, highlights): `#8B5CF6` (a pleasant purple)
* Subtle Gradient (Hero section/cards): Linear gradient from `#8B5CF6` to `#3B82F6` (Purple to Blue)
* Text (Primary): `#FFFFFF`
* Text (Secondary/Muted): `#A0A0A0`
* **Typography:**
* Headings: Inter (Variable font, Bold)
* Body Text: Inter (Variable font, Regular)
* **Layout:** Single or two-column layout depending on screen size. Generous white space. Focus on clear visual hierarchy. Use cards for distinct information blocks.
* **Responsiveness:** Mobile-first approach. Navigation collapses into a burger menu on smaller screens. Grids adjust, content reflows logically.
* **Visual Elements:** Clean icons, subtle shadows for depth on cards, smooth transitions.
**8. SAMPLE/MOCK DATA (for `books` table & `userBookLists`):**
* **Book 1:**
* `isbn`: "9780321765723"
* `title`: "The Lord of the Rings"
* `authors`: `["J.R.R. Tolkien"]`
* `publisher`: "Houghton Mifflin Harcourt"
* `language`: "English"
* `pages`: 1178
* `publicationDate`: `1954-07-29T00:00:00.000Z`
* `genre`: "Fantasy"
* `coverImageUrl`: "https://covers.openlibrary.org/b/isbn/9780321765723.jpg"
* **Book 2:**
* `isbn`: "9780743273565"
* `title`: "The Great Gatsby"
* `authors`: `["F. Scott Fitzgerald"]`
* `publisher`: "Scribner"
* `language`: "English"
* `pages`: 180
* `publicationDate`: `1925-04-10T00:00:00.000Z`
* `genre`: "Classic"
* `coverImageUrl`: "https://covers.openlibrary.org/b/isbn/9780743273565.jpg"
* **Book 3:**
* `isbn`: "9780141187761"
* `title`: "Nineteen Eighty-Four"
* `authors`: `["George Orwell"]`
* `publisher`: "Penguin Books"
* `language`: "English"
* `pages`: 328
* `publicationDate`: `1949-06-08T00:00:00.000Z`
* `genre`: "Dystopian Fiction"
* `coverImageUrl`: "https://covers.openlibrary.org/b/isbn/9780141187761.jpg"
* **User 1 (`userId`):** `uuid_for_user_1`
* **User List Entry 1 (User 1, Book 1, 'read'):**
* `userId`: `uuid_for_user_1`
* `bookId`: `uuid_for_book_1`
* `listType`: "read"
* **User List Entry 2 (User 1, Book 2, 'wishlist'):**
* `userId`: `uuid_for_user_1`
* `bookId`: `uuid_for_book_2`
* `listType`: "wishlist"
**9. TURKISH TRANSLATIONS:**
* **App Title:** ISBN Insight
* **Search Bar Placeholder:** ISBN girin (örn: 9780141187761)
* **Buttons:**
* 'Sign In / Sign Up': 'Giriş Yap / Kayıt Ol'
* 'Search': 'Ara'
* 'Add to List': 'Listeye Ekle'
* 'View Details': 'Detayları Gör'
* 'My Bookshelf': 'Kitaplığım'
* 'Read': 'Okundu'
* 'Wishlist': 'Alınacaklar'
* 'Favorites': 'Favoriler'
* 'Remove': 'Kaldır'
* 'Sign Out': 'Çıkış Yap'
* **Page Titles:**
* Dashboard: 'Kontrol Paneli'
* My Bookshelf: 'Kitaplığım'
* Book Details: 'Kitap Detayları'
* **Labels/Text:**
* 'Title': 'Başlık'
* 'Author(s)': 'Yazar(lar)'
* 'Publisher': 'Yayıncı'
* 'Language': 'Dil'
* 'Pages': 'Sayfa Sayısı'
* 'Publication Date': 'Yayın Tarihi'
* 'Genre': 'Tür'
* 'Description': 'Açıklama'
* 'Loading...': 'Yükleniyor...'
* 'No data available': 'Veri bulunamadı'
* 'Error fetching data': 'Veri alınamadı'
**10. ANIMATIONS:**
* **Page Transitions:** Subtle fade-in/out using Next.js's built-in capabilities or libraries like `Framer Motion` if needed for more complex transitions between pages.
* **Button Hovers:** Slight scale-up or background color change on hover states.
* **Loading States:** Use shadcn/ui's `Skeleton` component or a subtle loading spinner/overlay when fetching data.
* **Chart Animations:** Animate chart elements on load or update using Recharts' built-in animation features.
* **Card Transitions:** Slight elevation change or background shift on hover for book cards.
**11. EDGE CASES:**
* **Invalid ISBN Format:** Display an inline error message and prevent submission.
* **ISBN Not Found (External API):** Display a clear message to the user: "Bu ISBN ile ilgili bilgi bulunamadı."
* **API Errors (External):** Implement retry logic or fallback to a more generic message. Log errors server-side.
* **Database Errors:** Gracefully handle connection issues or query failures, showing an informative message.
* **Empty States:** 'My Bookshelf' and chart sections should display friendly messages and possibly CTAs when empty (e.g., "Henüz kitap eklemediniz. Bir ISBN aratarak başlayın!").
* **Authorization:** All routes under `app/(app)` and Server Actions must verify user authentication. Unauthorized access attempts should redirect to the sign-in page.
* **Data Validation:** Server-side validation for all incoming data (ISBN format, list types) before database operations.
* **Rate Limiting:** Implement rate limiting on ISBN search endpoints to prevent abuse of external APIs and our own infrastructure.