A lightweight note-taking application built with Next.js and SQLite. Create an account, sign in, and save your thoughts securely to a local database.
- Node.js 16+ installed
- npm or yarn
- Install dependencies:
npm install- Run the development server:
npm run dev- Open your browser: Navigate to http://localhost:3000
The app will automatically redirect you to the sign-in page. Create an account or sign in to access your notes.
my-app/
βββ src/
β βββ app/
β β βββ api/ # API routes
β β β βββ auth/ # Authentication endpoints
β β β βββ notes/ # Notes CRUD endpoints
β β βββ signin/ # Sign in/up page
β β βββ dashboard/ # Main notes dashboard
β β βββ page.js # Root page (redirects to signin/dashboard)
β β βββ layout.js # Root layout
β β βββ globals.css # Global styles
β βββ components/ # Reusable React components
β β βββ NoteEditor.js # Note editor with auto-save
β β βββ NoteList.js # List of user's notes
β βββ lib/
β βββ db.js # SQLite database setup
β βββ auth.js # Password hashing utilities
βββ middleware.js # Auth middleware for route protection
βββ notion.db # SQLite database (auto-generated)
βββ package.json
Handles user sign up and sign in.
Request Body:
{
"email": "user@example.com",
"password": "password123",
"action": "signup" or "signin"
}Responses:
- 201 (Sign Up Success): User created and logged in
- 200 (Sign In Success): User authenticated
- 400 (Bad Request): Missing email/password or user already exists
- 401 (Unauthorized): Invalid credentials
- 500 (Server Error): Database error
Example:
# Sign Up
curl -X POST http://localhost:3000/api/auth \
-H "Content-Type: application/json" \
-d '{"email":"user@example.com","password":"pass123","action":"signup"}'
# Sign In
curl -X POST http://localhost:3000/api/auth \
-H "Content-Type: application/json" \
-d '{"email":"user@example.com","password":"pass123","action":"signin"}'Retrieves all notes for the authenticated user.
Query Parameters:
userId(required): The user's ID from the session cookie
Response:
[
{
"id": 1,
"title": "My First Note",
"content": "Note content here...",
"created_at": "2024-01-22T10:30:00Z",
"updated_at": "2024-01-22T11:45:00Z"
}
]Responses:
- 200: List of notes
- 400: Missing user ID
- 500: Server error
Example:
curl -X GET "http://localhost:3000/api/notes?userId=1"Creates a new note for the authenticated user.
Request Body:
{
"userId": 1,
"title": "New Note",
"content": "Note content..."
}Response:
{
"id": 2,
"title": "New Note",
"content": "Note content...",
"created_at": "2024-01-22T10:30:00Z"
}Responses:
- 201: Note created successfully
- 401: User not authenticated
- 404: User not found
- 500: Server error
Example:
curl -X POST http://localhost:3000/api/notes \
-H "Content-Type: application/json" \
-d '{
"userId": 1,
"title": "Shopping List",
"content": "Milk, eggs, bread"
}'Updates an existing note.
URL Parameters:
id(required): Note ID to update
Request Body:
{
"userId": 1,
"title": "Updated Title",
"content": "Updated content..."
}Response:
{
"success": true
}Responses:
- 200: Note updated successfully
- 401: User not authenticated
- 403: Unauthorized (note doesn't belong to user)
- 404: Note not found
- 500: Server error
Example:
curl -X PUT http://localhost:3000/api/notes/2 \
-H "Content-Type: application/json" \
-d '{
"userId": 1,
"title": "Updated Shopping List",
"content": "Milk, eggs, bread, cheese"
}'Deletes a note.
URL Parameters:
id(required): Note ID to delete
Query Parameters:
userId(required): The user's ID for authorization
Response:
{
"success": true
}Responses:
- 200: Note deleted successfully
- 401: User not authenticated
- 403: Unauthorized (note doesn't belong to user)
- 404: Note not found
- 500: Server error
Example:
curl -X DELETE "http://localhost:3000/api/notes/2?userId=1"| Route | Description | Auth Required |
|---|---|---|
/ |
Root page - Redirects to /signin or /dashboard |
No |
/signin |
Sign in/up page | No |
/dashboard |
Main notes dashboard | Yes |
CREATE TABLE users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
email TEXT UNIQUE NOT NULL,
password_hash TEXT NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
)CREATE TABLE notes (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER NOT NULL,
title TEXT NOT NULL DEFAULT 'Untitled',
content TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
)-
Create API Route (if needed):
- Add file in
src/app/api/your-feature/route.js - Export
GET,POST,PUT, orDELETEfunctions - Use
getDatabase()fromsrc/lib/db.jsto access SQLite
- Add file in
-
Create/Update Components:
- Add React component in
src/components/YourComponent.js - Use
'use client'directive for client-side interactivity - Import and use in pages
- Add React component in
-
Update Pages:
- Modify files in
src/app/(e.g.,src/app/dashboard/page.js) - Pages are Server Components by default, use
'use client'for interactivity
- Modify files in
-
Update Database:
- Modify
src/lib/db.jsin theinitializeDatabase()function - Add new tables or columns as needed
- Modify
To add OAuth or other auth methods:
- Modify
src/app/api/auth/route.js - Update
src/app/signin/page.jswith new auth UI - Add necessary dependencies to
package.json
The project uses Tailwind CSS. Customize styling in component className attributes. Global styles are in src/app/globals.css.
- β Password hashing with bcrypt
- β HTTP-only secure cookies for sessions
- β Middleware protection for dashboard routes
- β User ownership validation on notes (can't access others' notes)
- β CSRF protection with SameSite cookies
- Next.js - React framework
- better-sqlite3 - SQLite database
- bcrypt - Password hashing
- Tailwind CSS - Styling
"Database is locked" error:
- Close any other instances of the app
- Delete
notion.db-shmandnotion.db-walfiles and restart
Sign in redirects to sign in page:
- Check browser cookies are enabled
- Verify the API request completed successfully
- Check browser console for errors
Notes not saving:
- Open browser DevTools (F12) and check Network tab for API errors
- Ensure you're signed in (check cookies in Application tab)
- Check terminal for server-side errors