A minimal barebones instant chat messenger app built with Solid.JS (frontend) and Erlang (backend).
- π In-house authentication system (username/password)
- π¬ Real-time messaging via HTTP polling
- π Built for scalability with extensible OAuth 2.0 architecture
- β‘ Lightweight and fast - no external dependencies
- π¨ Clean, modern UI
- Built-in TCP/HTTP server using only standard library modules
- OTP application structure for reliability
- gen_server based authentication and chat room management
- Token-based authentication (easily extensible to OAuth 2.0)
- No external dependencies - uses only Erlang/OTP built-ins
- Reactive UI with minimal bundle size
- HTTP polling for real-time updates (1 second interval)
- Local storage for session persistence
- Erlang/OTP 24+ - Installation guide
- Rebar3 - Installation guide
- Node.js 18+ - Installation guide
- npm or yarn
git clone https://github.com/codewriter3000/squidward-chat.git
cd squidward-chatrebar3 compilecd frontend
npm install
npm run build
cd ..# Build frontend
cd frontend && npm install && npm run build && cd ..
# Start the backend (includes compiled frontend)
rebar3 shellThe application will be available at http://localhost:8080
For frontend development with hot reload:
# Terminal 1: Start backend
rebar3 shell
# Terminal 2: Start frontend dev server
cd frontend
npm run devFrontend dev server will run on http://localhost:5173 with proxy to backend at http://localhost:8080
- Open your browser to
http://localhost:8080 - Register a new account with a username and password
- Login with your credentials
- Start chatting in real-time!
Run the included test script to verify all API endpoints:
./test_api.shOr test manually with curl:
# Register
curl -X POST http://localhost:8080/api/register \
-H "Content-Type: application/json" \
-d '{"username": "alice", "password": "pass123"}'
# Login
curl -X POST http://localhost:8080/api/login \
-H "Content-Type: application/json" \
-d '{"username": "alice", "password": "pass123"}'
# Send message (replace TOKEN with actual token from login)
curl -X POST http://localhost:8080/api/messages/send \
-H "Content-Type: application/json" \
-H "Authorization: Bearer TOKEN" \
-d '{"message": "Hello, World!"}'
# Get messages
curl -X GET http://localhost:8080/api/messages \
-H "Authorization: Bearer TOKEN"POST /api/register- Register a new user- Body:
{"username": "string", "password": "string"}
- Body:
POST /api/login- Login user- Body:
{"username": "string", "password": "string"} - Returns:
{"success": true, "token": "string", "username": "string"}
- Body:
POST /api/messages/send- Send a chat message (requires Bearer token)- Body:
{"message": "string"}
- Body:
GET /api/messages- Get recent messages (requires Bearer token)- Returns:
{"success": true, "messages": [...]}
- Returns:
The authentication system is designed with extensibility in mind. The current architecture supports easy integration of OAuth 2.0 providers:
squidward_chat_authmodule manages all authentication- Token-based system with Bearer authentication
- Stateless JWT-ready token generation
- Separate authentication from authorization
1. Add OAuth library to rebar.config:
{deps, [
{oauth2, "..."} % or other OAuth library
]}.2. Extend squidward_chat_auth module:
% New function for OAuth login
oauth_login(Provider, Code) ->
% Exchange authorization code for access token
AccessToken = exchange_code(Provider, Code),
% Fetch user info from provider
{ok, UserInfo} = get_user_info(Provider, AccessToken),
% Create or retrieve user in local system
Username = maps:get(<<"email">>, UserInfo),
% Generate internal token
Token = generate_token(Username),
store_oauth_mapping(Username, Provider, AccessToken),
{ok, Token, Username}.3. Add OAuth HTTP handlers:
% In squidward_chat_app.erl, add routes:
{"/api/oauth/:provider/callback", oauth_callback_handler, []},
{"/api/oauth/:provider/login", oauth_login_handler, []}4. Update frontend for OAuth:
// In Auth.jsx component
<button onClick={() => window.location.href = '/api/oauth/google/login'}>
Login with Google
</button>The modular design means OAuth can be added without changing core chat functionality.
squidward-chat/
βββ src/ # Erlang backend source
β βββ squidward_chat_app.erl # Main application
β βββ squidward_chat_sup.erl # Supervisor
β βββ squidward_chat_auth.erl # Authentication module
β βββ squidward_chat_room.erl # Chat room manager
β βββ squidward_chat_ws_handler.erl # WebSocket handler
β βββ squidward_chat_login_handler.erl # Login HTTP handler
β βββ squidward_chat_register_handler.erl # Register HTTP handler
βββ frontend/ # Solid.JS frontend
β βββ src/
β β βββ components/ # UI components
β β β βββ Auth.jsx # Login/Register component
β β β βββ Chat.jsx # Chat interface component
β β βββ App.jsx # Main app component
β β βββ index.jsx # Entry point
β β βββ styles.css # Styles
β βββ index.html # HTML template
β βββ package.json # Node dependencies
β βββ vite.config.js # Vite configuration
βββ rebar.config # Erlang dependencies
βββ README.md # This file
- Passwords are hashed with SHA-256 (use bcrypt in production)
- Tokens are simple hashes (use proper JWT in production)
- No HTTPS enforcement (enable in production)
- No rate limiting (add in production)
- No input validation (add comprehensive validation in production)
Apache 2.0
Pull requests are welcome! For major changes, please open an issue first to discuss what you would like to change.