A members-only message board where users can post anonymous messages. Only verified members can see who wrote each message and when. Built with Node.js, Express, EJS, and custom JWT authentication.
This project demonstrates role-based access control with three user levels:
- Guest - Can view messages (content only)
- Member - Can see usernames and timestamps
- Admin - Can delete any message
| Technology | Purpose |
|---|---|
| Node.js | JavaScript runtime |
| Express.js 5 | Web framework |
| EJS | Templating engine |
| JWT (jsonwebtoken) | Stateless authentication & authorization |
| bcrypt | Password hashing |
| cookie-parser | HTTP cookie parsing |
| Neon | Serverless Postgres hosting |
| @neondatabase/serverless | Neon's serverless driver |
| Render | Deployment |
- User Authentication - Sign up and login with secure password hashing
- JWT Authorization - Stateless authentication using HTTP-only cookies
- Role-Based Access - Three levels: Guest, Member, Admin
- Become a Member - Enter a secret code to unlock member privileges
- Become an Admin - Enter admin code to gain message deletion rights
- Create Messages - Post new messages (logged-in users only)
- View Message Details - Click the eye icon to see full message details
- Delete Messages - Admins can delete any message
- Responsive Design - Fully responsive on all devices
- Serverless Database - Powered by Neon's serverless PostgreSQL
the-clubhouse/
├── app.js # Express application entry point
├── .env # Environment variables (JWT_SECRET, MEMBER_CODE, ADMIN_CODE)
├── .gitignore # Git ignore file
├── package.json # Dependencies and scripts
│
├── db/
│ └── pool.js # Neon database connection
│
├── routes/
│ └── index.js # All route handlers with JWT middleware
│
├── views/
│ ├── partials/
│ │ ├── head.ejs # HTML head partial
│ │ └── footer.ejs # Footer partial
│ ├── index.ejs # Main message board page
│ ├── login.ejs # Login form
│ ├── signup.ejs # Signup form
│ ├── new-msg-form.ejs # New message form
│ ├── message.ejs # Message detail page
│ ├── become-member.ejs # Member secret code form
│ └── become-admin.ejs # Admin secret code form
│
├── public/
│ ├── styles.css # All CSS styles
│ ├── favicon.ico # Favicon files
│ └── ... # Other static assets
- Node.js (v18+)
- A Neon PostgreSQL database
-
Clone the repository
git clone https://github.com/roshhi/mini-msg-board.git cd mini-msg-board -
Install dependencies
npm install
-
Set up environment variables
Create a
.envfile in the root directory:DATABASE_URL=postgresql://username:password@your-neon-host/database?sslmode=require JWT_SECRET=your-super-secret-jwt-key MEMBER_CODE=clubhouse ADMIN_CODE=admin123
-
Create the database tables
Run this SQL in your Neon console:
CREATE TABLE users ( id SERIAL PRIMARY KEY, username VARCHAR(20) UNIQUE NOT NULL, password VARCHAR(255) NOT NULL, is_member BOOLEAN DEFAULT FALSE, is_admin BOOLEAN DEFAULT FALSE ); CREATE TABLE messages ( msg_id SERIAL PRIMARY KEY, user_id INTEGER REFERENCES users(id), msg_text VARCHAR(200) NOT NULL, date_added TIMESTAMP DEFAULT NOW() );
-
Start the server
node app.js
-
Open in browser
http://localhost:3000
Through building this project, I learned:
- Custom JWT Authentication - Implementing stateless auth with JSON Web Tokens stored in HTTP-only cookies
- Role-Based Authorization - Protecting routes and conditionally rendering UI based on user roles
- Password Security - Using bcrypt to hash and compare passwords securely
- EJS Templating - Dynamic HTML rendering with embedded JavaScript
- Neon Serverless - Using Neon's serverless driver for edge-compatible database connections
- MVC Architecture - Separating concerns with routes, views, and database logic
Contributions are welcome! Feel free to open an issue or submit a pull request.
This project is open source and available under the MIT License.
- The Odin Project for the curriculum
- Neon for serverless PostgreSQL