A web application for managing an internal second-hand store within a company, allowing employees to buy and sell items.
- User authentication and authorization
- Item listing and management
- Category organization
- Search and filtering capabilities
- Reservation system
- User profiles and history
- Node.js with Express
- TypeScript
- MongoDB with Mongoose
- JWT for authentication
- React
- TypeScript
- Tailwind CSS
kirppis/
├── server/ # Backend server
│ ├── src/
│ │ ├── config/ # Configuration files
│ │ ├── controllers/ # Request handlers
│ │ ├── middlewares/ # Express middlewares
│ │ ├── models/ # Mongoose models
│ │ ├── routes/ # API routes
│ │ ├── services/ # Business logic
│ │ ├── types/ # TypeScript type definitions
│ │ ├── utils/ # Utility functions
│ │ └── index.ts # Entry point
│ ├── package.json
│ └── tsconfig.json
├── client/ # Frontend (to be implemented)
├── .env # Environment variables
├── .gitignore
└── README.md
- Node.js (v16 or higher)
- MongoDB (local or Atlas)
- npm or yarn
-
Clone the repository
git clone <repository-url> cd kirppis
-
Install server dependencies
cd server npm install
-
Set up environment variables
- Copy
.env.example
to.env
(if available) - Update the values in
.env
file
- Copy
-
Start MongoDB (if using local instance)
mongod
-
Start the development server
npm run dev
The Docker setup provides a containerized environment with separate services for the frontend, backend, and database. This is ideal for production deployments and ensures consistent environments across different machines.
- Docker (v20.10.0 or higher)
- Docker Compose (v2.0.0 or higher, included with Docker Desktop)
-
Make sure Docker is running on your system
docker --version
-
Build and start the containers
docker compose up -d
-
Access the application
- Frontend: http://localhost:5173
- Backend API: http://localhost:5001/api/v1
-
Stop the containers
docker compose down
-
View logs
# View all logs docker compose logs # View specific service logs docker logs kirppis-server docker logs kirppis-client docker logs kirppis-mongo
The Docker setup uses persistent volumes to store data:
mongo_data
: Stores the MongoDB database filesuploads_data
: Stores uploaded files (images, etc.)
These volumes ensure that your data persists even when containers are restarted or rebuilt.
The npm version is ideal for development as it allows for faster iteration and easier debugging.
- Node.js (v16 or higher)
- MongoDB (local or Atlas)
- npm (v7 or higher)
-
Install dependencies for both server and client
# Install server dependencies cd server npm install # Install client dependencies cd ../client npm install
-
Start MongoDB (if using local instance)
mongod
-
Start the server in development mode
cd server npm run dev
-
In a separate terminal, start the client
cd client npm run dev
-
Access the application
- Frontend: http://localhost:5173 (default Vite port)
- Backend API: http://localhost:5000/api/v1
You can easily switch between Docker and npm versions:
-
To switch from npm to Docker:
- Stop any running npm processes (Ctrl+C)
- Run
docker compose up -d
-
To switch from Docker to npm:
- Run
docker compose down
- Start MongoDB, server, and client with npm as described above
- Run
Both Docker and npm versions use environment variables for configuration. The Docker version has these variables defined in the docker-compose.yml
file, while the npm version uses the .env
file.
Key differences in environment variables:
- Docker:
MONGO_URI=mongodb://mongo:27017/kirppis
(uses the Docker service name) - npm:
MONGO_URI=mongodb://localhost:27017/kirppis
(uses localhost)
For production deployment on Mirantis Swarm, we'll use separate stacks for each component (database, server, and client). This approach allows for independent scaling, updates, and maintenance of each component without affecting the others.
- Access to a Mirantis Swarm cluster
- Docker registry for storing images
- Swarm overlay network for communication between stacks
First, create an overlay network that will be used by all stacks to communicate with each other:
docker network create --driver overlay --attachable kirppis-network
The database stack contains only the MongoDB service and its associated volumes.
-
Create a
db-stack.yml
file:version: '3.8' services: mongo: image: mongo:latest deploy: replicas: 1 restart_policy: condition: on-failure update_config: parallelism: 1 delay: 10s resources: limits: cpus: '1' memory: 1G volumes: - mongo_data:/data/db environment: - MONGO_INITDB_DATABASE=kirppis networks: - kirppis-network healthcheck: test: ["CMD", "mongo", "--eval", "db.adminCommand('ping')"] interval: 10s timeout: 5s retries: 5 volumes: mongo_data: driver: local networks: kirppis-network: external: true
-
Deploy the database stack:
docker stack deploy -c db-stack.yml kirppis-db
The server stack contains the backend API service.
-
Build and push the server image:
# Build the server image docker build -t your-registry.com/kirppis/server:latest ./server # Push the image to your registry docker push your-registry.com/kirppis/server:latest
-
Create a
server-stack.yml
file:version: '3.8' services: server: image: your-registry.com/kirppis/server:latest deploy: replicas: 2 restart_policy: condition: on-failure update_config: parallelism: 1 delay: 10s order: start-first resources: limits: cpus: '0.5' memory: 512M environment: - NODE_ENV=production - PORT=5000 - HOST=0.0.0.0 - MONGO_URI=mongodb://mongo:27017/kirppis - UPLOAD_DIR=/app/uploads - JWT_SECRET_FILE=/run/secrets/jwt_secret - JWT_EXPIRES_IN=1d volumes: - uploads_data:/app/uploads networks: - kirppis-network secrets: - jwt_secret healthcheck: test: ["CMD", "wget", "--spider", "-q", "http://localhost:5000/api/v1/health"] interval: 30s timeout: 10s retries: 3 volumes: uploads_data: driver: local networks: kirppis-network: external: true secrets: jwt_secret: external: true
-
Create the JWT secret:
echo "your-secure-jwt-secret" | docker secret create jwt_secret -
-
Deploy the server stack:
docker stack deploy -c server-stack.yml kirppis-server
The client stack contains the frontend service.
-
Build and push the client image:
# Build the client image docker build -t your-registry.com/kirppis/client:latest ./client # Push the image to your registry docker push your-registry.com/kirppis/client:latest
-
Create a
client-stack.yml
file:version: '3.8' services: client: image: your-registry.com/kirppis/client:latest deploy: replicas: 2 restart_policy: condition: on-failure update_config: parallelism: 1 delay: 10s order: start-first resources: limits: cpus: '0.3' memory: 256M ports: - "80:5173" environment: - VITE_API_URL=http://server:5000/api/v1 networks: - kirppis-network healthcheck: test: ["CMD", "wget", "--spider", "-q", "http://localhost:5173"] interval: 30s timeout: 10s retries: 3 networks: kirppis-network: external: true
-
Deploy the client stack:
docker stack deploy -c client-stack.yml kirppis-client
One of the main benefits of separate stacks is the ability to update components independently:
-
Update the server without affecting the database or client:
# Build and push the new server image docker build -t your-registry.com/kirppis/server:v2 ./server docker push your-registry.com/kirppis/server:v2 # Update the server-stack.yml file with the new image tag # Then redeploy only the server stack docker stack deploy -c server-stack.yml kirppis-server
-
Update the client without affecting the database or server:
# Build and push the new client image docker build -t your-registry.com/kirppis/client:v2 ./client docker push your-registry.com/kirppis/client:v2 # Update the client-stack.yml file with the new image tag # Then redeploy only the client stack docker stack deploy -c client-stack.yml kirppis-client
Scale components based on their specific needs:
# Scale the server to 4 replicas
docker service scale kirppis-server_server=4
# Scale the client to 3 replicas
docker service scale kirppis-client_client=3
Monitor the status of each stack:
# List all stacks
docker stack ls
# List services in a specific stack
docker stack services kirppis-db
docker stack services kirppis-server
docker stack services kirppis-client
# Check logs for a specific service
docker service logs kirppis-server_server
docker service logs kirppis-client_client
For a production deployment, consider these additional security enhancements:
-
Use Docker secrets for all sensitive information
# Create additional secrets as needed echo "mongodb://mongo:27017/kirppis" | docker secret create mongo_uri -
-
Set up HTTPS with a reverse proxy (like Traefik)
- Configure Traefik as an edge router
- Set up automatic SSL certificate management
- Implement proper HTTP to HTTPS redirection
-
Implement proper monitoring and logging
- Set up Prometheus for metrics collection
- Use Grafana for visualization
- Configure centralized logging with ELK stack
-
Set up database backups
# Create a backup service in the db stack backup: image: mongo:latest command: sh -c 'mongodump --host mongo --archive=/backup/kirppis-$$(date +%Y%m%d%H%M).archive' volumes: - backup_data:/backup networks: - kirppis-network deploy: restart_policy: condition: none
The API will be available at http://localhost:5000/api/v1
(npm version) or http://localhost:5001/api/v1
(Docker version)
POST /api/v1/auth/register
- Register a new userPOST /api/v1/auth/login
- LoginPOST /api/v1/auth/logout
- Logout
GET /api/v1/users
- Get all users (admin only)GET /api/v1/users/:id
- Get user by IDPATCH /api/v1/users/:id
- Update userDELETE /api/v1/users/:id
- Delete user (admin only)
GET /api/v1/items
- Get all itemsGET /api/v1/items/:id
- Get item by IDPOST /api/v1/items
- Create new itemPATCH /api/v1/items/:id
- Update itemDELETE /api/v1/items/:id
- Delete item
GET /api/v1/categories
- Get all categoriesGET /api/v1/categories/:id
- Get category by IDPOST /api/v1/categories
- Create new category (admin only)PATCH /api/v1/categories/:id
- Update category (admin only)DELETE /api/v1/categories/:id
- Delete category (admin only)
This project is licensed under the MIT License.
- Server: Runs on port 5000
- Client: Runs on port 5173
- API URL: http://localhost:5000/api/v1
- MongoDB: Runs on port 27017
- Server: Container port 5000 mapped to host port 5001
- Client: Runs on port 5173
- API URL: http://localhost:5001/api/v1
- MongoDB: Container port 27017 mapped to host port 27018
VITE_API_URL=http://localhost:5000/api/v1 # For local development
VITE_API_URL=http://localhost:5001/api/v1 # For Docker environment
PORT=5000
CORS_ORIGINS=http://localhost:3000,http://localhost:5173,http://localhost:5001
- Start MongoDB
- Start the server:
cd server && npm run dev
- Start the client:
cd client && npm run dev
- Build the images:
cd deploy && docker compose build
- Start the containers:
cd deploy && docker compose up -d
If you encounter CORS issues:
- Check that the server's CORS configuration includes all necessary origins
- Ensure the client is using the correct API URL
- Verify that the server is running on the expected port
If you have port conflicts:
- Check if another process is using the required ports
- Update the port configuration in the appropriate files
Notes by human: docker setup: docker compose up --build server client or docker compose up --build --no-deps server client
local: docker compose up -d mongo cd server npm run dev cd ../client npm run dev