A full-stack article publishing platform built around a custom Java HTTP server. The project combines a Java/JPA backend, a React frontend, MySQL persistence, JWT-based authentication, and Docker Compose deployment.
- User registration and login.
- Password hashing and verification.
- JWT generation and validation.
- Protected frontend routes.
- Profile updates and password changes.
- Environment-based secret configuration.
- List all articles.
- Search articles by title and summary in the frontend.
- View article details and metadata.
- Create new articles after authentication.
- Associate references with other articles.
- Display citation counts.
- Show a user's articles on the profile page.
The backend does not rely on a full web framework for request handling. It implements:
- Socket-based HTTP server startup.
- Per-client request handling.
- HTTP request parsing.
- Exact and prefix route matching.
- Handler abstractions for API endpoints.
- JSON request and response processing.
┌────────────────────┐ HTTP/JSON ┌──────────────────────────┐
│ React + Vite │ ────────────────────▶ │ Custom Java HTTP server │
│ Nginx container │ │ API handlers + services │
└────────────────────┘ └─────────────┬────────────┘
│ JPA/Hibernate
▼
┌────────────────────┐
│ MySQL 8.4 │
└────────────────────┘
| Method | Endpoint | Purpose |
|---|---|---|
GET |
/api/articles |
List articles |
GET |
/api/articles/{id} |
Retrieve article details |
POST |
/api/articles |
Create an article |
POST |
/api/auth/register |
Register a user |
POST |
/api/auth/login |
Authenticate and receive a token |
GET |
/api/profile |
Retrieve the authenticated profile |
PUT |
/api/profile |
Update contact information |
PUT |
/api/profile/password |
Change the current password |
.
├── back/article-platform/
│ ├── src/main/java/ir/borna/webserver/
│ │ ├── server/ # HTTP server, parser, routing, and handlers
│ │ └── app/ # API, models, repositories, services, and security
│ ├── src/main/resources/META-INF/persistence.xml
│ ├── pom.xml
│ └── Dockerfile
├── front/
│ ├── src/components/ # Reusable UI components
│ ├── src/pages/ # Home, article, auth, and profile pages
│ ├── src/api/ # Backend API clients
│ ├── nginx.conf
│ ├── package.json
│ └── Dockerfile
├── docker-compose.yml
├── .env.example
├── .gitignore
└── README.md
Copy the example file:
cp .env.example .envReplace every placeholder in .env:
MYSQL_ROOT_PASSWORD=use-a-strong-local-password
MYSQL_DATABASE=webserver_db
JWT_SECRET=use-a-random-secret-of-at-least-32-charactersNever commit the real .env file.
docker compose up --buildThe default compose configuration exposes:
- Frontend:
http://localhost:80 - Backend:
http://localhost:8080 - MySQL: available to the backend on the internal Docker network
docker compose downTo remove the database volume as well, use docker compose down -v only when persistent data is no longer needed.
Requirements:
- Java 17 or the version configured in
pom.xml - Maven
- MySQL
Set DB_URL, DB_USER, DB_PASSWORD, and JWT_SECRET, then run the Maven project from back/article-platform/.
Requirements:
- Node.js
- npm
cd front
npm install
npm run devThe frontend uses React Router, Axios, and toast notifications. API base URLs should match the backend address used in the selected environment.
- Database passwords are read from environment variables.
- JWT secrets are read from
JWT_SECRETand must be at least 32 characters. - The real
.envfile is ignored. - Build outputs, dependencies, and IDE metadata are excluded.
This remains an educational implementation. A production deployment should also add HTTPS, robust token rotation, rate limiting, validation hardening, database migrations, and automated tests.
Java · Custom HTTP Server · JPA/Hibernate · MySQL · JWT · React · Vite · Nginx · Docker Compose