- Add auth handlers (signup, login, logout, account management) with bcrypt - Add client, customer, service, scheduling, payment, question, answer handlers - Add dashboard, monthly report, and lead pipeline pages - Add UTF-8 middleware to force charset on HTML responses - Add config package with env-based overrides for DB path, secrets, endpoints - Add parser package for WhatsApp message ingestion - Add clean-arch layers: pkg/domain, pkg/repo, pkg/usecase for leads - Add cmd/migrate utility for DB migrations - Add Makefile, README, run-tests.sh, and dev scripts - Update docker-compose.yml with memory limits - Update .air.toml to exclude DB files and stop on errors - Update whatsapp-sync dependencies and add src/index.js entrypoint - Add whatsme standalone WhatsApp reader app (source only) - Untrack .opencode-sandbox/data/go-crm.db from git history - Expand root .gitignore: ngrok, tmp dirs, sandbox DBs, compiled binaries
go-crm (lightweight local dev)
This service is intentionally small so junior Go developers can understand it end-to-end without Docker, hot reloads, or other heavy tooling. The goal: go run main.go with a single SQLite file in .dev-data/.
Local development (junior-friendly)
- Ensure Go 1.25+ is installed and
gois in yourPATH. - Run the helper script (no Docker):
./scripts/dev.sh - The server boots on http://localhost:8080.
- The database and WhatsApp store live under
.dev-data/(auto-created).
There are no file watchers or air hot reloads—just the plain Go toolchain so newcomers can focus on code, not tooling.
Project layout (modern, clean layers)
go-crm/
├── cmd/ # optional commands (e.g. migrations)
│ └── migrate/ # lightweight migration CLI (future)
├── config/ # templated configs (kept simple)
├── data/ # production data path (gitignored)
├── internal/ # HTTP handlers (usecases wired to HTTP)
│ ├── handlers/
│ ├── middleware/
│ └── templates/
├── pkg/ # reusable application packages
│ ├── domain/ # entities + repository interfaces
│ ├── usecase/ # application services / business logic
│ └── repo/ # persistence adapters (SQLite, etc.)
├── scripts/ # helper scripts (dev runner, migrations)
├── main.go # application entrypoint (wire handlers → usecases)
├── go.mod
└── go.sum
Recommended architecture / interfaces
pkg/domain/lead.go
package domain
// Lead is the core business entity.
type Lead struct {
LeadID int64
ClientID int64
Name string
PhoneRaw string
PhoneNormalized string
ServiceInterest string
Status string
PaymentStatus string
}
// LeadRepository abstracts persistence.
type LeadRepository interface {
FindAll(ctx context.Context, clientID int64) ([]Lead, error)
FindByID(ctx context.Context, clientID, leadID int64) (*Lead, error)
Update(ctx context.Context, lead Lead) error
}
pkg/usecase/lead_service.go
package usecase
import (
"context"
"go-crm/pkg/domain"
)
// LeadService orchestrates business logic.
type LeadService struct {
Repo domain.LeadRepository
}
func (s *LeadService) ListAll(ctx context.Context, clientID int64) ([]domain.Lead, error) {
return s.Repo.FindAll(ctx, clientID)
}
pkg/repo/sqlite_lead_repo.go
package repo
import (
"context"
"database/sql"
"go-crm/pkg/domain"
)
// SQLiteLeadRepository implements LeadRepository using sqlite.
type SQLiteLeadRepository struct {
DB *sql.DB
}
func (r *SQLiteLeadRepository) FindAll(ctx context.Context, clientID int64) ([]domain.Lead, error) {
// query leads table, scan rows, return []domain.Lead
}
Handlers in internal/handlers should accept a clear service layer (usecase.LeadService), not raw DB logic. Keep controllers thin: parse request, call service, write HTML/JSON.
Migration strategy
- Do not scan/clean the entire
leadstable on every startup (that was causing RAM blowups). - Run the lightweight CLI with
make migrate(which builds and runs the migration binary) whenever you need to refresh the schema or re-decode legacy Latin-1 data. To target non-default files, run the migration binary directly:go build -o migrate cmd/migrate/main.go && ./migrate --db /path/to/go-crm.db
Running tests
go test ./...
Summary
- No Docker or
airwatchers—justgo run main.go. - Clean package boundaries (domain/usecase/repo) improve readability and testability.
- Scripts under
scripts/orchestrate database setup or helper tasks. - Use the architecture sketch above to guide future refactors.