A full-stack task management application built with React, Express, and PostgreSQL. Features user authentication, CRUD operations for tasks, and a terminal-themed UI.
- Prerequisites
- Dependencies
- Installation
- Running the Application
- Project Structure
- API Endpoints
- Troubleshooting
- Node.js (v18.18 or higher)
- npm (v8.0 or higher)
- PostgreSQL (v12 or higher) - Only if you choose local setup
@prisma/client- Prisma ORM clientbcryptjs- Password hashingcors- Cross-Origin Resource Sharing middlewaredotenv- Environment variable managementexpress- Web frameworkjsonwebtoken- JWT authenticationprisma- Prisma CLI and schema management
nodemon- Auto-restart development server
react- UI libraryreact-dom- React DOM renderingreact-router-dom- Client-side routing
vite- Build tool and dev server@vitejs/plugin-react- React plugin for Viteeslint- Code linting- Various ESLint plugins
git clone <your-repository-url>
cd Listo-.env file is not included in the repository for security reasons. You'll need to create it in the next steps.
✨ This option is simpler because you don't need to install or configure PostgreSQL locally. Prisma handles the database for you!
# Navigate to backend directory
cd backend
# Install dependencies
npm installCreate a .env file in the backend directory:
# Create the .env file
touch .envOr create it manually in your code editor.
Add the following to your .env file:
# Database Connection - Prisma Cloud
# Run this command first to get your connection string:
# npx prisma init --datasource-provider postgresql
DATABASE_URL="prisma+postgres://accelerate.prisma-data.net/?api_key=YOUR_API_KEY"
# JWT Secret (REQUIRED - change this!)
JWT_SECRET="your-super-secret-jwt-key-change-this-in-production"
# Server Port
PORT=3000Important Notes:
- If you don't have a Prisma Cloud database URL yet, run:
npx prisma init --datasource-provider postgresql - This will generate a
.envfile with a Prisma connection string - Replace
your-super-secret-jwt-key-change-this-in-productionwith a secure random string - You can generate a secure secret with:
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
# Generate Prisma Client
npx prisma generate
# Run migrations (Prisma Cloud handles the database)
npx prisma migrate dev# Navigate to frontend directory (from project root)
cd ../frontend
# Install dependencies
npm install✅ That's it! Prisma Cloud is ready. Skip to Running the Application
Use this option if you want full control over your database or need to work offline.
# Using Homebrew
brew install postgresql@14
brew services start postgresql@14sudo apt update
sudo apt install postgresql postgresql-contrib
sudo systemctl start postgresqlDownload and install from PostgreSQL Official Website
# Access PostgreSQL prompt
psql postgres
# Create a database
CREATE DATABASE listo_db;
# Create a user (optional, or use your default postgres user)
CREATE USER your_username WITH PASSWORD 'your_password';
# Grant privileges
GRANT ALL PRIVILEGES ON DATABASE listo_db TO your_username;
# Exit psql
\q# Navigate to backend directory
cd backend
# Install dependencies
npm installCreate a .env file in the backend directory:
# Create the .env file
touch .envOr create it manually in your code editor.
Add your LOCAL PostgreSQL credentials to the .env file:
# Database Connection - Local PostgreSQL
DATABASE_URL="postgresql://your_username:your_password@localhost:5432/listo_db"
# JWT Secret (REQUIRED - change this!)
JWT_SECRET="your-super-secret-jwt-key-change-this-in-production"
# Server Port
PORT=3000Replace:
your_usernamewith your PostgreSQL username (default is oftenpostgres)your_passwordwith your PostgreSQL passwordlisto_dbwith your database name (if different)
Generate a secure JWT secret:
# Option 1: Use Node.js
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
# Option 2: Use OpenSSL
openssl rand -hex 32Copy the output and use it as your JWT_SECRET.
# Generate Prisma Client
npx prisma generate
# Run migrations to create tables
npx prisma migrate dev --name init# Navigate to frontend directory (from project root)
cd ../frontend
# Install dependencies
npm install✅ Local PostgreSQL is ready!
You'll need two terminal windows - one for backend and one for frontend.
cd backend
# Development mode (with auto-restart)
npm run dev
# OR Production mode
npm start✅ The backend server will start on http://localhost:3000
cd frontend
# Development mode
npm run dev✅ The frontend dev server will start on http://localhost:5173
Open your browser and navigate to:
http://localhost:5173
Create a test account:
Since there's no email verification, you can use any email format to register:
-
Go to the Register page
-
Use these test credentials (or create your own):
- Name:
Test User - Email:
test@example.com(any valid email format works) - Password:
testpassword123(minimum 8 characters) - Confirm Password:
testpassword123
- Name:
-
Click Register - you'll be automatically logged in
-
Start creating tasks!
For subsequent logins, use the same credentials you registered with.
Note:
- ✉️ No actual emails are sent - email validation is format-only
- 🔒 Passwords are securely hashed with bcrypt
- 🗄️ Each user's database is independent (local or Prisma Cloud)
Listo-/
├── backend/
│ ├── controllers/
│ │ ├── auth.controller.js # Authentication logic
│ │ └── task.controller.js # Task CRUD operations
│ ├── middleware/
│ │ └── auth.middleware.js # JWT verification
│ ├── prisma/
│ │ ├── schema.prisma # Database schema
│ │ └── migrations/ # Database migrations
│ ├── routes/
│ │ ├── auth.routes.js # Auth endpoints
│ │ └── tasks.routes.js # Task endpoints
│ ├── utils/
│ │ ├── generateToken.js # JWT token generation
│ │ └── prisma.js # Prisma client instance
│ ├── .env # Environment variables (not in git)
│ ├── .gitignore
│ ├── server.js # Express server entry point
│ └── package.json
│
└── frontend/
├── src/
│ ├── components/
│ │ ├── Dashboard.jsx # Main dashboard
│ │ ├── Login.jsx # Login page
│ │ ├── Register.jsx # Registration page
│ │ └── ProtectedRoute.jsx # Route protection
│ ├── context/
│ │ └── AuthContext.jsx # Authentication state
│ ├── services/
│ │ └── api.js # API client (Axios)
│ ├── App.jsx # Main app component
│ ├── main.jsx # React entry point
│ └── index.css # Terminal-themed styles
├── index.html
├── vite.config.js
└── package.json
-
POST /api/auth/register- Register new user{ "name": "John Doe", "email": "john@example.com", "password": "password123", "confirmPassword": "password123" } -
POST /api/auth/login- Login user{ "email": "john@example.com", "password": "password123" }
GET /api/tasks- Get all user's tasksPOST /api/tasks- Create new task{ "title": "Complete project", "description": "Finish the Listo app" }PUT /api/tasks/:id- Update task{ "title": "Updated title", "description": "Updated description", "completed": true }DELETE /api/tasks/:id- Delete task
Note: All protected endpoints require an Authorization header:
Authorization: Bearer <your-jwt-token>
# Generate Prisma Client (run after schema changes)
npx prisma generate
# Create and apply new migration
npx prisma migrate dev --name migration_name
# Apply existing migrations
npx prisma migrate deploy
# Open Prisma Studio (database GUI)
npx prisma studio
# Reset database (WARNING: deletes all data)
npx prisma migrate reset
# Pull database schema into Prisma
npx prisma db pull
# Push schema changes without migration
npx prisma db push# Development mode with auto-restart
npm run dev
# Production mode
npm start# Development server
npm run dev
# Build for production
npm run build
# Preview production build
npm run preview
# Run linter
npm run lint- ✅ User authentication (register/login)
- ✅ JWT-based authorization
- ✅ Create, read, update, delete tasks
- ✅ Mark tasks as complete/incomplete
- ✅ Edit task title and description
- ✅ Terminal/hacker-themed UI
- ✅ Responsive design
- ✅ Protected routes
- ✅ Password hashing with bcrypt
- ✅ Form validation
- ✅ No email verification required (format validation only)
For Prisma Cloud:
- Verify your
DATABASE_URLin.envcontains the correct API key - Check if you have internet connection (Prisma Cloud requires network access)
- Try regenerating Prisma Client:
npx prisma generate
For Local PostgreSQL:
- Make sure PostgreSQL is running:
# macOS brew services list # Linux sudo systemctl status postgresql # Windows - check Services app
- Verify your DATABASE_URL credentials in
.env - Test connection:
psql -U your_username -d listo_db - Ensure database exists:
psql -l(list all databases)
# Regenerate Prisma Client
npx prisma generate# Reset database and migrations (WARNING: deletes data)
npx prisma migrate reset
# Then regenerate
npx prisma generate
npx prisma migrate dev- Ensure backend is running on port 3000
- Check
API_URLinfrontend/src/services/api.js(should behttp://localhost:3000/api) - Verify CORS is enabled in
backend/server.js
- Backend might not be running
- Check if you're using the correct port
- Clear browser cache and localStorage
- Logout and login again
- Check if JWT_SECRET is set in backend
.env - Clear localStorage: Open browser console and run
localStorage.clear()
# Run migrations
npx prisma migrate dev- Email already exists in database
- Use a different email or delete the existing user:
npx prisma studio # Delete user from GUI
- Install PostgreSQL locally (see Option 2)
- Create a database
- Update
DATABASE_URLin.env:# Change from: DATABASE_URL="prisma+postgres://..." # To: DATABASE_URL="postgresql://username:password@localhost:5432/listo_db"
- Run migrations:
npx prisma generate npx prisma migrate dev
- Get Prisma Cloud connection string
- Update
DATABASE_URLin.env:# Change from: DATABASE_URL="postgresql://username:password@localhost:5432/listo_db" # To: DATABASE_URL="prisma+postgres://..."
- Run migrations:
npx prisma generate npx prisma migrate deploy
# Database Connection
# Option 1 - Prisma Cloud:
DATABASE_URL="prisma+postgres://accelerate.prisma-data.net/?api_key=YOUR_API_KEY"
# Option 2 - Local PostgreSQL:
# DATABASE_URL="postgresql://username:password@localhost:5432/database_name"
# JWT Secret (REQUIRED)
JWT_SECRET="your-super-secret-jwt-key-change-this"
# Server Port (optional, defaults to 3000)
PORT=3000- Never commit
.envfiles to version control (already in.gitignore) - Change default JWT_SECRET in production
- Use strong passwords for PostgreSQL
- Enable HTTPS in production
- Rotate JWT secrets periodically
- Implement rate limiting for production APIs
ISC
David Reyes
Vitrinnea Technical Assessment Project
- Terminal theme inspired by hacker aesthetic
- Built as part of a technical assessment for Vitrinnea
If you encounter issues:
- Check the Troubleshooting section
- Ensure all dependencies are installed
- Verify your environment variables
- Check that all required services are running
For Prisma Cloud issues: Visit Prisma Support
For Local PostgreSQL issues: Check PostgreSQL Documentation