No description
Find a file
2025-07-22 00:00:34 +02:00
data init 2025-07-22 00:00:34 +02:00
frontend init 2025-07-22 00:00:34 +02:00
.air.toml init 2025-07-22 00:00:34 +02:00
.dockerignore init 2025-07-22 00:00:34 +02:00
.gitignore init 2025-07-22 00:00:34 +02:00
build-container.sh init 2025-07-22 00:00:34 +02:00
Containerfile init 2025-07-22 00:00:34 +02:00
demo.sh init 2025-07-22 00:00:34 +02:00
docker-compose.yml init 2025-07-22 00:00:34 +02:00
go.mod init 2025-07-22 00:00:34 +02:00
go.sum init 2025-07-22 00:00:34 +02:00
main.go init 2025-07-22 00:00:34 +02:00
README.md init 2025-07-22 00:00:34 +02:00

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):

    go mod init gocheck
    
  2. Install dependencies:

    go mod tidy
    
  3. Build the application:

    go build
    
  4. Run the server:

    ./gocheck
    

    Or use the demo script for a guided experience:

    ./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:

# 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:

# 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

# 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)
    # 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

# 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:

{
   "success": true,
   "message": "Operation completed successfully"
   // ... additional data specific to the endpoint
}

Example Responses

Create Checklist:

{
   "success": true,
   "message": "Checklist created successfully",
   "uuid": "123e4567-e89b-12d3-a456-426614174000"
}

Add Item:

{
   "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:

{
   "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:

{
   "success": true,
   "message": "Item deleted successfully",
   "id": 1
}

Lock Item:

{
   "success": true,
   "message": "Item locked successfully",
   "id": 1,
   "locked_by": "user123",
   "expires": "2024-01-01T12:00:00Z"
}

Get Items:

{
   "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.