A romantic-themed journaling web app. Users register, log in to get a JWT, and then create/read/update/delete their own private βlove lettersβ. Styled with a soft pastel love theme featuring floating hearts, elegant script fonts, and a dreamy aesthetic.
journal-app/
βββ index.js # Server entry point + all routes + static file serving
βββ package.json
βββ public/
β βββ index.html # Full frontend: auth screens + entry editor (vanilla JS, no build step)
βββ db/
β βββ schema.sql # Table definitions (user, entry)
β βββ journal.db # SQLite DB file (auto-created on first run)
βββ middleware/
βββ logger.js # Logs query params on each request
βββ authenticateToken.js # Verifies JWT, attaches request.userId
npm install
npm run dev # uses nodemon, auto-restarts on file changes
# or
npm start
Server runs at http://localhost:3000/ β open that URL in a browser to use the app (register, log in, write/edit/delete entries). The same server also exposes the JSON API below if you want to hit it directly (curl, Postman, etc).
public/index.html) with embedded CSS/JS β no build tooling, no framework, works as soon as Express serves it.localStorage, so refreshing the page logs you out. Swap in localStorage/cookies if you want persistence across reloads.authFetch() helper, which attaches the Authorization: Bearer <token> header and auto-logs-out on a 401.Register β POST /users/
{ "username": "rahul", "name": "Rahul", "password": "pass123", "gender": "Male", "location": "Hyderabad" }
Login β POST /login
{ "username": "rahul", "password": "pass123" }
Returns: { "jwtToken": "..." }
All
/entries/routes below require the header:Authorization: Bearer <jwtToken>
| Method | Path | Description |
|---|---|---|
| GET | /entries/ |
List your entries (supports offset, limit, order, order_by, search_q) |
| GET | /entries/:entryId/ |
Get a single entry |
| POST | /entries/ |
Create an entry β body: { "title", "content", "mood" } |
| PUT | /entries/:entryId/ |
Update an entry β same body as POST |
| DELETE | /entries/:entryId/ |
Delete an entry |
Example: list with filters
GET /entries/?limit=5&offset=0&order=DESC&order_by=date_created&search_q=grateful
After starting the server, open http://localhost:3000 in your browser:
bcrypt before storage β never stored in plain text."MY_SECRET_TOKEN" for learning purposes β move this to an environment variable (.env) before deploying anywhere real.request.userId from the verified token, so users can only ever see or modify their own entries.db.all(query, [param1, param2])) to prevent SQL injection.