π About This Project
This is a feature-rich note-taking web application built to provide a smooth, customizable, and accessible writing experience.
The project started as a challenge to recreate a design as closely as possible and has grown into a full-fledged application with both frontend and backend features.
β¨ Core Features
π CRUD Functionality β Create, read, update, and delete notes.
π¦ Archive System β Archive and view archived notes separately.
π Tag Management β Filter and view notes by tags.
π Smart Search β Search by title, tag, or content.
π¨ Themes & Fonts β Choose from multiple color themes and font styles.
β Validation Messages β Get instant feedback on required form fields.
β¨οΈ Keyboard Navigation β Perform all actions without a mouse.
π± Responsive Layout β Optimized for all screen sizes.
π±οΈ Interactive UI β Clear hover and focus states for every element.
π Bonus Features (in development / implemented)
πΎ Database Integration β Save notes permanently with backend support.
π€ User Authentication β Create an account, log in, update profile, and change password.
π Password Reset β Recover access securely.
To run this project locally:
-
Navigate to the server directory:
cd server -
Install dependencies:
npm install
-
Create a
.envfile in the server directory with the following content:PORT=5050 JWT_SECRET=your_jwt_secret_key JWT_EXPIRES_IN=24h -
Start the backend server:
npm start
The server will run on http://localhost:5050
-
Navigate to the client directory:
cd client -
Install dependencies:
npm install
-
Create a
.envfile in the client directory with the following content:REACT_APP_API_URL=http://localhost:5050/api -
Start the frontend development server:
npm start
-
Open http://localhost:3000 to view it in the browser.
You can test the API using Postman. Refer to the "Creating a User via Postman POST Request and Setting Up Authorization" section below for detailed instructions.
- React 18.2.0
- Tailwind CSS 3.4.17
- Heroicons 2.2.0
- React Router DOM 7.2.0
- Node.js
- Express.js
- SQLite (for database)
- JWT (for authentication)
The project follows a client-server architecture:
-
client/: Contains the React frontend application
- src/components/: Reusable UI components
- src/pages/: Page components for different routes
- src/services/: Service modules for API communication
- authService.js: Handles authentication API calls
- noteService.js: Handles notes API calls
- src/assets/: Static assets like images and icons
-
server/: Contains the Node.js/Express backend application
- models/: Database models
- routes/: API route definitions
- middleware/: Express middleware
- config/: Configuration files
- data/: SQLite database files
- Favicon
- Fonts Family Inter
- Responsive UI
- User Authentication (Register, Login, Logout)
- Create New Note
- Edit Notes
- Delete Notes
- Archive Notes
- Tags for Notes
- Search Notes
- Theme Settings
- Add a WYSIWYG editor with text formatting for the notes
- Use animations and transitions to add a layer of polish to the application
- Build the project out as a full-stack application
- Add user authentication (if building it as a full-stack app)
- Add password reset capabilities
This guide will walk you through creating a user via a Postman POST request and setting up authorization for subsequent requests.
This request does not require an authorization token because it's the endpoint that allows new users to sign up.
- Open Postman
- Create a new request: Click the "+" button to open a new tab
- Select the HTTP Method: Choose POST from the dropdown menu
- Enter the Request URL: Based on your server setup, the URL for user registration will be:
http://localhost:5050/api/auth/register - Go to the "Body" tab: Below the URL bar, select the "Body" tab
- Choose "raw" and "JSON":
- Select the raw radio button
- From the dropdown menu to the right (which might initially say "Text"), select JSON
- Enter the JSON payload: In the text area, you'll provide the user details. Your backend expects username, email,
and password.
Replace with the desired username, email, and password.
{ "username": "postmanuser", "email": "postmanuser@example.com", "password": "password123" } - Go to the "Headers" tab (Optional but good practice):
Ensure a header
Content-Typewith a value ofapplication/jsonis present. Postman often adds this automatically when you select JSON in the body, but it's good to verify. - Send the request: Click the blue "Send" button
Status Code: 201 Created
Body: A JSON response similar to this (as defined in your server/routes/auth.js):
{
"success": true,
"message": "User registered successfully",
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...your.jwt.token...",
"user": {
"id": 123,
"username": "postmanuser",
"email": "postmanuser@example.com"
}
}Once a user is registered and/or logged in, your other API endpoints (like those for notes) will require a JWT token for authorization. Here's how to use the token you received from the registration (or login) response:
- Copy the Token: From the response body of a successful registration or login, copy the entire token string
- Open a new request tab (or an existing one for a protected endpoint):
For example, if you want to fetch notes, the method would be GET and the URL might be
http://localhost:5050/api/notes - Go to the "Authorization" tab:
- Select Bearer Token from the "Type" dropdown menu
- On the right side, in the "Token" field, paste the JWT token you copied earlier
- Send the request: Click "Send"
Alternatively, set Authorization via Headers (Manual way):
- Go to the "Headers" tab
- Add a new header:
- Key:
Authorization - Value:
Bearer YOUR_JWT_TOKEN_HERE(ReplaceYOUR_JWT_TOKEN_HEREwith the actual token, making sure the word "Bearer" is followed by a space and then the token)
- Key:
- Send the request: Click "Send"
You should receive a successful response from the protected endpoint (e.g., a list of notes, a 200 OK status).
You should receive an error response, typically with a status code like 401 Unauthorized or 403 Forbidden, and a JSON body like:
{
"success": false,
"message": "Access token required"
}or
{
"success": false,
"message": "Invalid or expired token"
}-
Environments: For managing tokens across multiple requests, Postman's "Environments" feature is very useful. You can save the token as an environment variable after login/registration and then reference that variable (e.g.,
{{authToken}}) in the Authorization tab of other requests. -
Collections: Organize your requests into collections. You can even set authorization at the collection level, so all requests within that collection inherit the same authorization method (though you might need to update the token value periodically).
Let me know if any of these steps are unclear!
This repository already includes render.yaml to deploy both the API (Express) and the client (React) on Render using a Blueprint.
Prerequisites
- A Render account (https://render.com)
- This repo pushed to your default branch on GitHub/GitLab
Steps
- Push/commit the current repo (including render.yaml) to your main branch.
- In Render, click New β Blueprint and connect your repository.
- Render will detect two services:
- note-app-api (Web Service, rootDir: server)
- note-app-client (Static Site, rootDir: client)
- Configure environment variables:
- For note-app-api (Web Service):
- JWT_SECRET: set a strong random string (required for auth)
- JWT_EXPIRES_IN: 24h (optional)
- PORT: Do not set; Render provides this automatically
- Optional: ALLOWED_ORIGIN to restrict CORS (e.g., https://.onrender.com). Current code allows all origins by default.
- For note-app-client (Static Site):
- REACT_APP_API_URL: the full API base URL including /api Example: https://.onrender.com/api
- For note-app-api (Web Service):
- Deploy order:
- Deploy note-app-api first. Wait until the health check at / is green and shows { message: "Note Taking App API Server" }.
- Then deploy note-app-client.
- Verify after deploy:
- Visit the API URL in a browser to see the health message.
- Open the client URL, register/login, and create a note.
Notes on data persistence (SQLite)
- The API currently uses SQLite stored on the service filesystem. On Render Free plans, the filesystem is ephemeral (data may be lost on redeploy/restart). For a demo this may be acceptable; for persistence consider:
- Attaching a Render Disk to the API service and pointing your DB file to the disk mount path, or
- Migrating to a managed database (e.g., PostgreSQL) and updating the code accordingly.
Troubleshooting
- 404 or network errors from the client: ensure REACT_APP_API_URL points to your deployed API and includes /api.
- CORS errors: either keep default permissive CORS (current setup) or set ALLOWED_ORIGIN on the API and adjust CORS logic in code accordingly.
- Client still calling localhost: ensure you redeployed the client after setting REACT_APP_API_URL.
- JWT errors: make sure JWT_SECRET is set on the API and that the client stores/sends the token.