Accordion Chat MVP - A self-hosted real-time chat application with Spring Boot WebSocket backend and LibGDX frontend.
Accordion is a Discord-like self-hosted chat application designed for simplicity and extensibility. This MVP demonstrates core chat functionality with multiple chat rooms/channels, username-based login, and real-time messaging.
Technology Stack:
- Backend: Spring Boot 3.x, WebSocket (STOMP), H2 Database, Spring Data JPA
- Web Frontend: Spring Boot, Thymeleaf, SockJS, STOMP.js (browser-based)
- Desktop Frontend: LibGDX, Java WebSocket client, Scene2D UI
- ✅ Multiple chat rooms/channels - Create and switch between different channels
- ✅ Single chat room (global) - Backwards compatible default channel
- ✅ Username-based login (no password required for MVP)
- ✅ Real-time message broadcasting via WebSocket
- ✅ Message persistence in H2 database (survives container restarts)
- ✅ Message history on login (channel-specific)
- ✅ Timestamp for each message
- ✅ User join/leave notifications
- ✅ Browser-based web interface (accessible from any device)
- ✅ Cross-platform desktop support (LibGDX)
- ✅ Docker containerization for easy deployment
- Java 17 or higher
- Maven 3.6+ (for backend and webapp)
- Gradle 7+ (included via wrapper for LibGDX desktop frontend)
- Docker & Docker Compose (for containerized deployment)
Option 1: Using Docker Compose (Recommended)
# Copy sample environment file and customize if needed
cp sample.env .env
# Edit .env to configure ports and other settings
# Start all services (backend + web app)
docker compose up -d
# Access the web application
open http://localhost:3000
# For network access from other devices:
# 1. Set DOCKER_HOST_IP to your machine's IP in .env
# 2. Restart: docker compose down && docker compose up -d
# 3. Access from other devices: http://YOUR_IP:3000Option 2: Run services manually
# Terminal 1 - Start backend
cd backend
mvn spring-boot:run
# Terminal 2 - Start web application
cd webapp
mvn spring-boot:run
# Access at http://localhost:3000
# Optional: Terminal 3 - Start LibGDX desktop client
cd frontend
./gradlew desktop:runOption 3: Run backend + multiple LibGDX clients
# Terminal 1 - Start backend
cd backend && mvn spring-boot:run
# Terminal 2+ - Start as many LibGDX clients as you want
cd frontend && ./gradlew desktop:runWeb Application (Browser):
- Navigate to
http://localhost:3000 - Enter your username (minimum 3 characters, alphanumeric + underscore)
- Click "Join Chat"
- Select a channel from the sidebar or create a new one with "+ New Channel"
- Type your message and click "Send" or press Enter
- Switch between channels by clicking on channel names in the sidebar
- Open in multiple browser tabs to test real-time messaging across channels
LibGDX Desktop Client:
- Frontend window will open (800x600)
- Enter your username (minimum 3 characters)
- Click "Login" to enter the chat room
- Type your message and click "Send" or press Enter
- Open multiple clients to test real-time messaging
Backend API:
- Backend runs on
http://localhost:8080 - WebSocket endpoint:
ws://localhost:8080/ws - REST API endpoints:
GET /api/channels- List all channelsPOST /api/channels- Create a new channelGET /api/channels/{id}- Get channel detailsGET /api/messages?channelId={id}- Get messages for a specific channelPOST /api/users/login- User login
- Docker 20.10+
- Docker Compose 2.0+
The application uses environment variables for configuration. A sample.env file is provided with all available options:
# Copy and customize the environment file
cp sample.env .env
# Edit .env to configure:
# - Port numbers (BACKEND_PORT, WEBAPP_PORT)
# - CORS settings (APP_CORS_ALLOWED_ORIGINS)
# - Database configuration
# - Validation rules (message length, username constraints)
# - And more...Key configuration options:
BACKEND_PORT: Backend service port (default: 8080)WEBAPP_PORT: Web application port (default: 3000)APP_CORS_ALLOWED_ORIGINS: CORS allowed origins (default:*for development)APP_MESSAGE_MAX_LENGTH: Maximum message length (default: 1000)APP_USERNAME_MIN_LENGTH: Minimum username length (default: 3)APP_USERNAME_MAX_LENGTH: Maximum username length (default: 50)
See sample.env for the complete list of configurable options.
The easiest way to run the backend in a container:
# Build and start the backend
docker compose up -d
# View logs
docker compose logs -f backend
# Stop the service
docker compose downThe services will be available at:
- Web Application:
http://localhost:3000(browser-based UI) - Backend API:
http://localhost:8080(REST & WebSocket)
Note: If you customized ports in .env, use those port numbers instead.
Backend:
# Build the backend image
docker build -t accordion-backend:latest -f Dockerfile .
# Run the container
docker run -d \
-p 8080:8080 \
--name accordion-backend \
accordion-backend:latestWeb Application:
# Build the webapp image
docker build -t accordion-webapp:latest -f Dockerfile.webapp .
# Run the container (requires backend to be running)
docker run -d \
-p 3000:3000 \
-e ACCORDION_BACKEND_URL=http://backend:8080 \
-e ACCORDION_BACKEND_WS_URL=ws://backend:8080/ws \
--link accordion-backend:backend \
--name accordion-webapp \
accordion-webapp:latestView logs:
docker logs -f accordion-backend
docker logs -f accordion-webappStop and remove:
docker stop accordion-backend accordion-webapp
docker rm accordion-backendConfigure the application using environment variables:
docker run -d \
-p 8080:8080 \
-e APP_CORS_ALLOWED_ORIGINS="https://yourdomain.com" \
-e APP_USERNAME_MIN_LENGTH=5 \
-e APP_MESSAGE_MAX_LENGTH=500 \
--name accordion-backend \
accordion-backend:latestSee compose.yml for all available environment variables.
View the database contents:
- URL:
http://localhost:8080/h2-console - JDBC URL: When using Docker Compose with persistence (default):
jdbc:h2:file:/app/data/chatdb;MODE=MySQL;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE - JDBC URL: When using in-memory mode:
jdbc:h2:mem:chatdb - Username:
sa - Password: (leave empty)
- Note: The JDBC URL (including parameters) should match your
SPRING_DATASOURCE_URLenvironment variable.
By default, when running via Docker Compose, the application uses a file-based H2 database with Docker volume persistence. This means your chat messages and channels are preserved across container restarts.
Note: When running the backend directly from source (without Docker), it defaults to in-memory H2 as configured in backend/src/main/resources/application.properties.
Default Configuration (with Docker Compose):
- Database is stored in a Docker volume named
h2_data - Data persists when containers are stopped and restarted
- Database files are stored at
/app/data/chatdbinside the container - Schema management uses
updatemode by default (convenient for development)- For production: Consider using
validatemode with proper database migrations (Flyway/Liquibase) - Override in
.env:SPRING_JPA_HIBERNATE_DDL_AUTO=validate
- For production: Consider using
To use in-memory database instead (data lost on restart):
Edit your .env file:
SPRING_DATASOURCE_URL=jdbc:h2:mem:chatdb
SPRING_JPA_HIBERNATE_DDL_AUTO=create-dropThen restart:
docker compose down && docker compose up -dTo clear persisted data:
# Stop containers and remove the volume
docker compose down -v
# Restart fresh
docker compose up -daccordion-prototype/
├── MVP.md # Detailed MVP documentation
├── README.md # This file
├── Dockerfile # Docker image for backend
├── Dockerfile.webapp # Docker image for web application
├── compose.yml # Docker Compose configuration
├── .dockerignore # Docker build exclusions
├── backend/ # Spring Boot backend
│ ├── pom.xml # Maven configuration
│ └── src/main/java/com/accordion/
│ ├── AccordionApplication.java
│ ├── config/ # WebSocket configuration
│ ├── controller/ # REST and WebSocket controllers
│ ├── model/ # JPA entities
│ ├── repository/ # Data repositories
│ ├── service/ # Business logic
│ └── util/ # Validation utilities
├── webapp/ # Spring Boot web application
│ ├── pom.xml # Maven configuration
│ └── src/main/
│ ├── java/com/accordion/webapp/
│ │ ├── AccordionWebApplication.java
│ │ └── controller/ # Web controllers
│ └── resources/
│ ├── templates/ # Thymeleaf HTML templates
│ │ ├── index.html # Login page
│ │ └── chat.html # Chat interface
│ └── application.properties
└── frontend/ # LibGDX frontend (desktop)
├── build.gradle # Root Gradle config
├── core/ # Shared code
│ └── src/com/accordion/
│ ├── AccordionGame.java
│ ├── config/ # Configuration
│ ├── screen/ # Login & Chat screens
│ └── websocket/ # WebSocket client
└── desktop/ # Desktop launcher
└── src/com/accordion/desktop/
└── DesktopLauncher.java
cd backend
mvn clean installcd frontend
./gradlew buildserver.port=8080
spring.datasource.url=jdbc:h2:mem:chatdb
spring.h2.console.enabled=trueWebSocket endpoint is configured in ChatScreen.java:
URI uri = new URI("ws://localhost:8080/ws");To connect to a remote server, change localhost to your server's address.
See MVP.md for the complete roadmap and architecture details.
- ✅ Multiple chat rooms/channels - NEW!
- ✅ Channel creation and management - NEW!
- ✅ Channel-specific message history - NEW!
- User authentication (password-based)
- Private direct messages
- User online/offline status
- Message search and pagination
- PostgreSQL/MySQL support for production
- File/image sharing
- MVP.md - Complete MVP documentation including:
- Architecture details
- API documentation
- Setup instructions
- Feature roadmap
- Troubleshooting guide
This is an MVP prototype. Contributions are welcome for:
- Bug fixes
- Performance improvements
- Documentation updates
- Feature implementations from the roadmap
This project is licensed under the Stephenson Software Non-Commercial License (Stephenson-NC).
© 2025 Daniel McCoy Stephenson. All rights reserved.
You may use, modify, and share this software for non-commercial purposes only.
Commercial use is prohibited without explicit written permission from the copyright holder.
Full license text: Stephenson-NC License
SPDX Identifier: Stephenson-NC
For issues or questions, please open an issue on GitHub.