This commit is contained in:
lubiana 2025-07-22 00:00:34 +02:00
commit ba1f43fd8e
Signed by: lubiana
SSH key fingerprint: SHA256:vW1EA0fRR3Fw+dD/sM0K+x3Il2gSry6YRYHqOeQwrfk
35 changed files with 5926 additions and 0 deletions

364
README.md Normal file
View file

@ -0,0 +1,364 @@
# GoCheck - Collaborative Checklist Application
A real-time collaborative checklist application built with Go and React,
featuring Server-Sent Events (SSE) for live updates and SQLite for data
persistence.
## Features
- Create and manage checklists
- Add, update, and delete checklist items
- Real-time collaboration with Server-Sent Events
- Item locking mechanism to prevent conflicts
- Hierarchical items (parent-child relationships)
- SQLite database for data persistence
- **Modern web frontend with React and TypeScript**
- **Real-time updates across multiple browser tabs/windows**
- **SSE-first architecture: All data flows through Server-Sent Events**
## Architecture
### SSE-First Design
This application follows an **SSE-first architecture** where all checklist data
flows through Server-Sent Events:
- **No API calls for data retrieval**: The frontend never calls the
`/api/checklists/{uuid}/items` endpoint
- **SSE as primary data source**: All checklist items are received via SSE
streaming
- **Real-time state management**: The frontend maintains state purely through
SSE events
- **Immediate updates**: Changes appear instantly across all connected clients
#### Data Flow
1. **Initial Connection**: When a client connects to a checklist, the SSE
endpoint sends the complete current state
2. **Real-time Updates**: All subsequent changes (add, update, delete, lock) are
broadcast via SSE
3. **State Synchronization**: The frontend updates its local state based on SSE
events without API calls
This design ensures:
- **Consistency**: All clients see the same data at the same time
- **Performance**: No unnecessary API calls to reload data
- **Real-time Experience**: Changes appear instantly across all connected
browsers
- **Scalability**: Reduces server load by eliminating polling
## Prerequisites
- Go 1.16 or later
- SQLite3 (usually included with Go)
## Setup
1. **Initialize the Go module** (already done):
```bash
go mod init gocheck
```
2. **Install dependencies**:
```bash
go mod tidy
```
3. **Build the application**:
```bash
go build
```
4. **Run the server**:
```bash
./gocheck
```
Or use the demo script for a guided experience:
```bash
./demo.sh
```
The server will start on `http://localhost:8080`
## Deployment
The application is built as a single binary with embedded static files, making
deployment simple:
- **Single Executable**: The `gocheck` binary contains all necessary files
- **No External Dependencies**: Just copy the binary to your server
- **Cross-Platform**: Build for different platforms as needed
### Binary Deployment
To build for different platforms:
```bash
# Linux
GOOS=linux GOARCH=amd64 go build -o gocheck-linux
# Windows
GOOS=windows GOARCH=amd64 go build -o gocheck.exe
# macOS
GOOS=darwin GOARCH=amd64 go build -o gocheck-macos
```
### Container Deployment
The application includes a multi-stage Containerfile for containerized
deployment:
#### Using Podman (Recommended)
```bash
# Build and run with the provided script
./build-container.sh
# Or manually:
podman build -t gocheck -f Containerfile .
podman run -d --name gocheck-container -p 8080:8080 -v gocheck-data:/app gocheck
# With custom port:
PORT=3000 ./build-container.sh
# Or manually:
podman run -d --name gocheck-container -p 3000:8080 -e PORT=8080 -v gocheck-data:/app gocheck
```
#### Using Docker
```bash
# Build the image
docker build -t gocheck -f Containerfile .
# Run the container
docker run -d --name gocheck-container -p 8080:8080 -v gocheck-data:/app gocheck
# With custom port:
docker run -d --name gocheck-container -p 3000:8080 -e PORT=8080 -v gocheck-data:/app gocheck
```
#### Container Features
- **Multi-stage build**: Uses Go Alpine for building, distroless for runtime
- **Minimal footprint**: Runtime container is only ~2MB
- **Persistent data**: SQLite database is stored in a named volume
- **Security**: Runs as non-root user in distroless container
- **Configurable**: Supports environment variables for customization
#### Environment Variables
- `PORT`: Set the port the application listens on (default: 8080)
```bash
# Example: Run on port 3000
PORT=3000 ./build-container.sh
```
## Frontend
The application includes a modern web frontend built with **React**:
- **Single Page Application**: No page reloads needed
- **Home Page**: Welcome page for creating new checklists
- **Checklist Page**: Dedicated page for viewing and editing checklists
- **Local Storage**: Automatically saves and lists your checklists
- **Real-time Updates**: Changes appear instantly across all connected browsers
- **Responsive Design**: Works on desktop and mobile devices
- **Item Locking**: Visual indicators when items are being edited
- **Hierarchical Items**: Support for parent-child relationships
- **Modern UI**: Clean, intuitive interface
- **TypeScript**: Full type safety and better developer experience
- **Component-based**: Modular, maintainable code structure
- **URL-based Routing**: Share checklist URLs directly
- **ESLint**: Code quality enforcement with no-semicolon style
### Frontend Development
The frontend is located in the `frontend/` directory and uses:
- **React**: Modern JavaScript library for building user interfaces
- **TypeScript**: Type-safe JavaScript
- **Vite**: Fast build tool and dev server
- **CSS Modules**: Scoped styling
#### Development Commands
```bash
# Install dependencies
cd frontend && npm install
# Start development server (with API proxy)
cd frontend && npm run dev
# Build for production
cd frontend && npm run build
# Lint code (check for issues)
cd frontend && npm run lint
# Lint and auto-fix issues
cd frontend && npm run lint:fix
# Build frontend and copy to static directory
./build-frontend.sh
```
#### Development Workflow
1. Start the backend server: `./gocheck`
2. Start the frontend dev server: `cd frontend && npm run dev`
3. Access the app at: `http://localhost:5173` (frontend dev server)
4. The frontend will proxy API requests to the backend at
`http://localhost:8080`
Simply open `http://localhost:8080` in your browser to use the production
application.
#### Page Structure
- **Home Page** (`/`): Welcome page with option to create new checklists and
view saved checklists
- **Checklist Page** (/{uuid}`): View and edit specific checklists
- when opening this route and that checklistid is not yet saved into
localstorage it should be committed there
- **URL Sharing**: Share checklist URLs directly with others for collaboration
- **Local Storage**: Checklists are automatically saved and can be renamed or
removed from the home page
## API Endpoints
### Checklists
- `POST /api/checklists` - Create a new checklist
- `POST /api/checklists/{uuid}/items` - Add an item to a checklist
- `PATCH /api/checklists/{uuid}/items/{id}` - Update an item
- `DELETE /api/checklists/{uuid}/items/{id}` - Delete an item
- `POST /api/checklists/{uuid}/items/{id}/lock` - Lock an item for editing
- `GET /api/checklists/{uuid}/sse` - Server-Sent Events stream for real-time
updates (primary data source)
**Note**: The `GET /api/checklists/{uuid}/items` endpoint exists but is not used
by the frontend. All data flows through the SSE endpoint for real-time updates.
### API Response Format
All API endpoints return JSON responses with a consistent format:
```json
{
"success": true,
"message": "Operation completed successfully"
// ... additional data specific to the endpoint
}
```
#### Example Responses
**Create Checklist:**
```json
{
"success": true,
"message": "Checklist created successfully",
"uuid": "123e4567-e89b-12d3-a456-426614174000"
}
```
**Add Item:**
```json
{
"success": true,
"message": "Item added successfully",
"item": {
"id": 1,
"content": "New item",
"checked": false,
"parent_id": null,
"checklist_uuid": "123e4567-e89b-12d3-a456-426614174000"
}
}
```
**Update Item:**
```json
{
"success": true,
"message": "Item updated successfully",
"item": {
"id": 1,
"content": "Updated content",
"checked": true,
"parent_id": null,
"checklist_uuid": "123e4567-e89b-12d3-a456-426614174000"
}
}
```
**Delete Item:**
```json
{
"success": true,
"message": "Item deleted successfully",
"id": 1
}
```
**Lock Item:**
```json
{
"success": true,
"message": "Item locked successfully",
"id": 1,
"locked_by": "user123",
"expires": "2024-01-01T12:00:00Z"
}
```
**Get Items:**
```json
{
"success": true,
"message": "Items loaded successfully",
"items": [
{
"id": 1,
"content": "Item 1",
"checked": false,
"parent_id": null,
"checklist_uuid": "123e4567-e89b-12d3-a456-426614174000"
}
]
}
```
## Dependencies
- `github.com/google/uuid` - UUID generation
- `github.com/mattn/go-sqlite3` - SQLite driver for Go
## Database
The application uses SQLite with the following schema:
- `checklists` table: Stores checklist metadata
- `items` table: Stores checklist items with hierarchical relationships
## Real-time Features
- **SSE-first architecture**: All data flows through Server-Sent Events
- **Real-time state synchronization**: No API polling required
- **Item locking with automatic expiration** (30 seconds)
- **Broadcast updates to all connected clients**
- **Immediate UI updates**: Changes appear instantly across all browsers
## Development
To run in development mode with automatic reloading, you can use tools like
`air` or `realize`.