Comprehensive README improvements: structure, accuracy, and deployment guidance
CollabTable
A collaborative list management system with Android app and server for creating and managing shared lists with custom fields and items.
Overview
CollabTable allows multiple users to collaboratively create and manage lists with custom fields. Perfect for:
- Shopping lists with price tracking
- Product catalogs
- Task management with custom attributes
- Any structured data collection
Features
Android App
- ✨ Beautiful Material 3 design with dynamic colors
- 📱 Native Android app built with Jetpack Compose
- 💾 Offline-first with Room database
- 🔄 Real-time synchronization via WebSocket (with HTTP fallback)
- 🎨 Custom fields (name, link, price, category, etc.)
- ✏️ Inline editing of items with auto-save
- 📤 Export functionality (CSV format)
- 🗑️ Soft delete support for data recovery
- ⚙️ Configurable server URL and authentication
- 📊 Optimized performance for large tables with thousands of rows
- 🎯 Column alignment options (left, center, right)
Server
- 🚀 Express.js REST API with TypeScript
- 🐳 Fully containerized with Docker
- 💾 Flexible database support: SQLite or PostgreSQL
- 🔄 Advanced sync protocol for conflict resolution
- 🔌 WebSocket support for real-time updates
- 🔐 Optional authentication with shared password
- 📊 Complete CRUD operations for all entities
- 💽 Persistent storage with Docker volumes
Prerequisites
Server
- Docker and Docker Compose (recommended)
- Or Node.js 20+ for local development
Android App
- Android Studio Hedgehog or later
- Android SDK 26+ (Android 8.0 or higher)
- JDK 21
- Android emulator or physical device
Quick Start
Server (Docker)
-
Navigate to server directory:
cd CollabTableServer -
Copy environment file (optional):
cp .env.example .env -
Configure authentication (optional): Edit
.envand setSERVER_PASSWORDfor API protection:SERVER_PASSWORD=your_secure_password -
Start the server:
docker-compose up -d
Server runs on http://localhost:3000
Database Options:
- SQLite (default): Data persists in Docker volume
sqlite_data - PostgreSQL: Configure in
.envwithDB_CLIENT=postgres
Android App
-
Open project in Android Studio:
- Open
CollabTableAndroidfolder in Android Studio - Wait for Gradle sync to complete
- Open
-
Run the app:
- Run on emulator or physical device
-
Configure server connection:
- Tap the Settings icon (⚙️) in the top bar
- Enter your server URL:
- For emulator:
http://10.0.2.2:3000/api/ - For physical device:
http://YOUR_COMPUTER_IP:3000/api/
- For emulator:
- If server has authentication enabled, enter the password
- Tap "Save"
Note: Make sure to include the trailing /api/ in the URL.
Project Structure
CollabTable/
├── CollabTableAndroid/ # Android app
│ ├── app/
│ │ ├── src/main/java/com/collabtable/app/
│ │ │ ├── data/ # Database, API, repositories
│ │ │ │ ├── api/ # Retrofit interfaces
│ │ │ │ ├── dao/ # Room DAOs
│ │ │ │ ├── database/ # Room database setup
│ │ │ │ ├── model/ # Data models
│ │ │ │ └── repository/ # Repository pattern
│ │ │ └── ui/ # Compose UI
│ │ │ ├── navigation/ # Navigation setup
│ │ │ ├── screens/ # UI screens & ViewModels
│ │ │ └── theme/ # Material 3 theme
│ │ └── build.gradle
│ └── README.md
│
└── CollabTableServer/ # Node.js server
├── src/
│ ├── models/ # Data models & database logic
│ ├── routes/ # API endpoints
│ └── index.ts # Server entry point
├── data/ # SQLite database storage
├── Dockerfile
├── docker-compose.yml
└── README.md
Technology Stack
Android
- Language: Kotlin
- UI Framework: Jetpack Compose with Material 3
- Database: Room (SQLite)
- Networking: Retrofit (HTTP), OkHttp WebSocket
- Async: Coroutines & Flow
- Architecture: MVVM with Repository pattern
- Build System: Gradle with Kotlin DSL
Server
- Runtime: Node.js 20+
- Framework: Express.js
- Language: TypeScript
- Database: SQLite (better-sqlite3) or PostgreSQL (pg)
- Containerization: Docker & Docker Compose
- Real-time: WebSocket support
API Endpoints
All endpoints are prefixed with /api/ and can be protected with optional authentication.
Authentication
If SERVER_PASSWORD is set in the server's .env file, include this header in all requests:
Authorization: Bearer your_password_here
Lists
GET /api/lists- Get all listsGET /api/lists/:id- Get a specific listPOST /api/lists- Create a new listPUT /api/lists/:id- Update a listDELETE /api/lists/:id- Delete a list (soft delete)
Fields
GET /api/fields/list/:listId- Get all fields for a listPOST /api/fields- Create a new fieldPUT /api/fields/:id- Update a field (including alignment)DELETE /api/fields/:id- Delete a field (soft delete)
Items
GET /api/items/list/:listId- Get all items for a listGET /api/items/:itemId/values- Get all values for an itemPOST /api/items- Create a new itemPOST /api/items/values- Create/update item valuesPUT /api/items/:id- Update an itemDELETE /api/items/:id- Delete an item (soft delete)
Sync
POST /api/sync- Synchronize data (HTTP fallback)WebSocket /api/ws- WebSocket endpoint for real-time sync
Health
GET /health- Server health check
See Server README for detailed API documentation.
Development
Server Development
Local development without Docker:
-
Install dependencies:
cd CollabTableServer npm install -
Create
.envfile:cp .env.example .env -
Start development server with hot reload:
npm run dev -
Build for production:
npm run build npm start
Useful commands:
npm run lint # Check code style
npm run format # Auto-format code
Android Development
-
Open
CollabTableAndroidin Android Studio -
Build the project:
./gradlew build -
Run linters:
./gradlew ktlintCheck # Check Kotlin code style ./gradlew detekt # Run static analysis -
Format code:
./gradlew ktlintFormat
Data Model
Database Schema
List
Represents a table/list container:
{
id: string; // Unique identifier
name: string; // List name
createdAt: number; // Creation timestamp
updatedAt: number; // Last update timestamp
isDeleted: boolean; // Soft delete flag
}
Field
Defines a column/attribute in a list:
{
id: string; // Unique identifier
listId: string; // Parent list ID
name: string; // Field name (e.g., "Price", "Category")
order: number; // Display order
alignment: string; // Content alignment: "left", "center", "right"
createdAt: number; // Creation timestamp
updatedAt: number; // Last update timestamp
isDeleted: boolean; // Soft delete flag
}
Item
Represents a row in a list:
{
id: string; // Unique identifier
listId: string; // Parent list ID
createdAt: number; // Creation timestamp
updatedAt: number; // Last update timestamp
isDeleted: boolean; // Soft delete flag
}
ItemValue
The actual value for a specific field of an item:
{
id: string; // Unique identifier
itemId: string; // Parent item ID
fieldId: string; // Associated field ID
value: string; // The actual value
updatedAt: number; // Last update timestamp
}
Relationships
- One List has many Fields
- One List has many Items
- One Item has many ItemValues (one per Field)
Troubleshooting
Common Issues
Android App
Cannot connect to server
- Verify server is running: visit
http://localhost:3000/healthin browser - Check server URL in app settings:
- Emulator: Use
http://10.0.2.2:3000/api/ - Physical device: Use your computer's IP address
- Emulator: Use
- Ensure trailing
/api/is included in URL - If server has authentication, verify password is correct
Gradle sync failed
- Update Android Studio to latest version
- Ensure JDK 21 is installed and selected
- Try: File → Invalidate Caches → Invalidate and Restart
Build errors with Room/Kotlin
- Clean and rebuild: Build → Clean Project → Rebuild Project
- Check that you're using compatible versions
Large tables are slow
- Performance is optimized for thousands of rows
- For tens of thousands of rows, consider server-side filtering
- Check that debouncing is enabled (default)
Server
Port 3000 already in use
# Find and kill process using port 3000
lsof -ti:3000 | xargs kill -9
# Or change port in docker-compose.yml or .env
Docker container won't start
# View logs
docker-compose logs -f
# Rebuild container
docker-compose down
docker-compose up -d --build
Database connection error (PostgreSQL)
- Verify PostgreSQL is running
- Check connection details in
.env - Ensure database exists
Data not persisting after container restart
- Verify Docker volume exists:
docker volume ls - Check volume mount in
docker-compose.yml - For SQLite, data is in
sqlite_datavolume
Getting Help
- Check the Android README for app-specific details
- Check the Server README for server-specific details
- Review Docker logs:
docker-compose logs -f - Open an issue on GitHub with detailed error messages
Synchronization
CollabTable uses a sophisticated sync protocol to keep data consistent across clients:
Sync Strategy
- Primary: WebSocket (
/api/ws) for real-time, low-latency sync - Fallback: HTTP POST (
/api/sync) when WebSocket fails - Conflict Resolution: Latest timestamp wins
How It Works
- Client → Server: Client sends all local changes since last sync timestamp
- Server Processing: Server saves client changes and retrieves server changes
- Server → Client: Server returns changes made since client's last sync
- Client Update: Client applies server updates locally
- Timestamp Update: Client stores new server timestamp for next sync
Sync Flow
Client Server
| |
|-- Sync Request (local changes) ---->|
| (lists, fields, items, values) |
| |
|<-- Sync Response (server changes) --|
| (updates + new serverTimestamp) |
| |
WebSocket Protocol
Send JSON messages to /api/ws:
{
"type": "sync",
"id": "unique-request-id",
"payload": {
"lastSyncTimestamp": 1234567890,
"lists": [...],
"fields": [...],
"items": [...],
"itemValues": [...]
}
}
Response:
{
"type": "syncResponse",
"id": "unique-request-id",
"payload": {
"lists": [...],
"fields": [...],
"items": [...],
"itemValues": [...],
"serverTimestamp": 1234567890
}
}
Features
- Automatic Sync: Triggered on app start and after local changes
- Soft Deletes: Deleted items can be recovered on server
- Optimistic Updates: UI updates immediately, syncs in background
- Performance: Debounced updates for large table operations
Docker & Deployment
Data Persistence
SQLite (Default)
- Database stored in Docker volume:
sqlite_data - Persists across container restarts
- Backup database:
# Using container name (set in docker-compose.yml) docker cp collabtable-server:/data/collabtable.db ./backup.db # Or using docker-compose (if in server directory) docker-compose exec server cat /data/collabtable.db > ./backup.db - Restore database:
docker cp ./backup.db collabtable-server:/data/collabtable.db docker-compose restart
PostgreSQL
- Configure in
.env:DB_CLIENT=postgres - Use standard PostgreSQL backup tools (
pg_dump,pg_restore) - Docker volume manages persistence automatically
Docker Commands
Start services:
docker-compose up -d
Stop services:
docker-compose down
View logs:
docker-compose logs -f
Rebuild and restart:
docker-compose up -d --build
Check running containers:
docker ps
Production Deployment
Environment Variables
Configure these in .env or docker-compose.yml:
PORT=3000 # Server port
NODE_ENV=production # Environment
SERVER_PASSWORD=your_secure_pass # API authentication (recommended)
DB_CLIENT=sqlite # Database: sqlite or postgres
DB_PATH=/data/collabtable.db # SQLite path (in container)
Security Recommendations
- Set
SERVER_PASSWORDfor production - Use HTTPS with a reverse proxy (nginx, Caddy)
- Regular database backups
- Keep Docker images updated
- Restrict network access to server ports
Reverse Proxy Example (nginx)
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
Contributing
Contributions are welcome! Here's how you can help:
Getting Started
- Fork the repository
- Create a feature branch:
git checkout -b feature/your-feature-name - Make your changes
- Test your changes thoroughly
- Commit with clear messages:
git commit -m "feat: add new feature" - Push to your fork:
git push origin feature/your-feature-name - Open a Pull Request
Development Guidelines
Code Style
- Android: Follow Kotlin conventions, use ktlint for formatting
- Server: Follow TypeScript/JavaScript conventions, use Prettier
- Keep functions small and focused
- Write meaningful variable and function names
- Add comments for complex logic
Testing
- Test your changes on both emulator and physical devices (Android)
- Test with both SQLite and PostgreSQL backends (Server)
- Verify sync works correctly with multiple clients
- Test with large datasets to ensure performance
Commit Messages Follow conventional commits:
feat:for new featuresfix:for bug fixesdocs:for documentation changesstyle:for formatting changesrefactor:for code refactoringtest:for adding testschore:for maintenance tasks
Areas for Contribution
Features
- Additional export formats (JSON, Excel)
- Search and filter functionality
- Batch operations
- User authentication and permissions
- Drag-and-drop row reordering
- Rich text field support
Improvements
- Performance optimization for very large tables
- Better offline support
- Enhanced error handling
- Accessibility improvements
- Internationalization (i18n)
Documentation
- API documentation improvements
- Tutorial videos or blog posts
- Translation to other languages
- More code examples
Pull Request Guidelines
- Keep PRs focused on a single feature or fix
- Update documentation if needed
- Ensure all tests pass
- Add screenshots for UI changes
- Reference any related issues
License
MIT