No description
Find a file
2025-07-25 21:15:45 +02:00
data init 2025-07-22 00:00:34 +02:00
frontend shrink 2025-07-25 21:15:45 +02:00
.air.toml init 2025-07-22 00:00:34 +02:00
.dockerignore devmode 2025-07-25 15:23:52 +02:00
.gitignore init 2025-07-22 00:00:34 +02:00
build-and-push.sh wip 2025-07-24 11:35:37 +02:00
Containerfile shrink 2025-07-25 21:15:45 +02:00
dev-docker.sh devmode 2025-07-25 15:23:52 +02:00
dev.sh devv 2025-07-25 14:41:43 +02:00
docker-compose.dev.yml devmode 2025-07-25 15:23:52 +02:00
docker-compose.yml wip 2025-07-24 11:35:37 +02:00
Dockerfile.dev devmode 2025-07-25 15:23:52 +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 shrink 2025-07-25 21:15:45 +02:00
podman-compose.yml wip 2025-07-24 11:35:37 +02:00
README.md datestuff 2025-07-25 16:27:30 +02:00
test-checklist.json import export 2025-07-25 20:18:05 +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)
  • Item dependencies: Define prerequisites for completing items
  • Date constraints: Set "not before" and "not after" times for item completion
  • 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:

The application is optimized for rootless Podman operation:

# 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 Podman Compose (recommended for rootless):
podman-compose -f podman-compose.yml up -d

# Or with Docker Compose (also works with Podman):
docker-compose up -d

Rootless Podman Compatibility:

  • Uses UID/GID 1000 for better user mapping
  • Includes security options for rootless operation
  • Supports both podman-compose and docker-compose
  • Alternative compose file available: podman-compose.yml

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, Alpine for runtime
  • Minimal footprint: Runtime container is optimized for size
  • Persistent data: SQLite database is stored in a named volume
  • Security: Runs as non-root user with UID 1000
  • Rootless Podman compatible: Optimized for rootless container operation
  • 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",
      "dependencies": [],
      "not_before": "2025-07-25T16:20:00Z",
      "not_after": "2025-07-25T18:00:00Z"
   }
}

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",
      "dependencies": [2, 3],
      "not_before": "2025-07-25T16:20:00Z",
      "not_after": "2025-07-25T18:00:00Z"
   }
}

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": [],
         "not_before": null,
         "not_after": null
      },
      {
         "id": 2,
         "content": "Item 2",
         "checked": true,
         "parent_id": null,
         "checklist_uuid": "123e4567-e89b-12d3-a456-426614174000",
         "dependencies": [1],
         "not_before": "2025-07-25T16:20:00Z",
         "not_after": null
      }
   ]
}

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:

  • checklist_info table: Stores checklist metadata (uuid, name)
  • items table: Stores checklist items with hierarchical relationships and date constraints
  • dependencies table: Stores item dependencies (item_id, dependency_id)

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

Item Dependencies

The application supports item dependencies, allowing you to define prerequisites that must be completed before an item can be marked as done.

How Dependencies Work

  • Prerequisites: Items can depend on other items being completed first
  • Visual Indicators: Items with unmet dependencies show warning indicators
  • Prevention: Items cannot be completed until all dependencies are satisfied
  • Circular Prevention: The system prevents circular dependencies
  • Real-time Updates: Dependency status updates in real-time across all clients

Managing Dependencies

  1. Add Dependencies: Click the dependency icon () on any item to open the dependency manager
  2. Select Prerequisites: Choose which items must be completed first
  3. Visual Feedback: Items show dependency status with color-coded indicators:
    • 🟠 Orange: Dependencies not met (shows count)
    • 🟢 Green: All dependencies met (shows "Ready")
  4. Completion Prevention: Items with unmet dependencies cannot be checked off

Dependency Features

  • Flexible Dependencies: Items can depend on any number of other items
  • Hierarchical Support: Dependencies work with parent-child relationships
  • Real-time Validation: Dependency status updates immediately when items are completed
  • Clear Feedback: Users see exactly which items need to be completed first
  • Error Prevention: System prevents circular dependencies automatically

Item Date Constraints

The application supports date constraints, allowing you to set time windows when items can be completed.

How Date Constraints Work

  • Not Before: Set the earliest time an item can be completed
  • Not After: Set the latest time an item can be completed
  • Validation: Items cannot be completed outside their allowed time window
  • Visual Indicators: Items show date constraint status with color-coded indicators
  • Real-time Updates: Constraint status updates in real-time

Managing Date Constraints

  1. Set Constraints: Click the clock icon (🕐) on any item to open the date constraint manager
  2. Configure Times: Set "not before" and/or "not after" times
  3. Visual Feedback: Items show constraint status:
    • 🟢 Green: Time constraints met (shows "Ready")
    • 🔴 Red: Time constraints not met (shows "Time locked")
  4. Completion Prevention: Items cannot be checked off outside their time window

Date Constraint Features

  • Flexible Scheduling: Set any combination of start and end times
  • ISO 8601 Format: Uses standard datetime format for precision
  • Real-time Validation: Constraint status updates immediately
  • Clear Feedback: Users see exactly when items can be completed
  • Error Prevention: System prevents completion outside allowed times

Example Use Cases

  • Meeting Preparation: Set items to be completed before a meeting starts
  • Deadline Management: Set items to be completed by a specific deadline
  • Time-sensitive Tasks: Ensure tasks are completed within business hours
  • Sequential Workflows: Use in combination with dependencies for complex workflows

Development

Local Development

To run in development mode with automatic reloading, you can use tools like air or realize.

Using the Development Script

The project includes a development script that runs both backend and frontend with hot reloading:

# Start development environment
./dev.sh

This will:

  • Start the Go backend with Air for hot reloading
  • Start the React frontend with Vite for hot reloading
  • Proxy API requests from frontend to backend
  • Clean up processes on exit

Docker Development

For a consistent development environment using Docker with hot reloading:

Prerequisites

  • Docker and Docker Compose installed
  • Ports 8080 and 5173 available

Quick Start

# Start development environment with Docker
./dev-docker.sh

This will:

  • Build a development container with all dependencies
  • Mount your source code for hot reloading
  • Start both backend (Air) and frontend (Vite) with hot reloading
  • Make the application available at:

Manual Docker Commands

# Build and start the development container
docker-compose -f docker-compose.dev.yml up --build

# Stop the development container
docker-compose -f docker-compose.dev.yml down

# View logs
docker-compose -f docker-compose.dev.yml logs -f

# Rebuild the container
docker-compose -f docker-compose.dev.yml up --build --force-recreate

Development Features

The Docker development environment includes:

  • Hot Reloading: Both Go backend and React frontend reload automatically on code changes
  • Volume Mounts: Your local code is mounted into the container for live editing
  • Dependency Management: All dependencies are pre-installed in the container
  • Consistent Environment: Same environment across all developers
  • Easy Cleanup: Simple commands to start/stop the development environment

File Watching

The development container uses:

  • Air for Go backend hot reloading (watches .go files)
  • Vite for React frontend hot reloading (watches all frontend files)
  • inotify-tools for efficient file system watching

Troubleshooting

If you encounter issues:

  1. Port conflicts: Ensure ports 8080 and 5173 are not in use
  2. Permission issues: The container runs with appropriate permissions
  3. Hot reload not working: Check that your files are being watched by the respective tools
  4. Container won't start: Check Docker logs with docker-compose -f docker-compose.dev.yml logs