Free shopping assistant
A fast and simple app for managing your shopping list together
Pronounced KOF-fan (rhymes with "coffin" but with an "a" at the end). The name comes from the Polish word "kochanie" (meaning "darling" or "sweetheart"), which evolved into a playful nickname. It's a long story, but let's just say the name stuck! :D
Koffan is a lightweight web application for managing shopping lists, designed for couples and families. It allows real-time synchronization between multiple devices, so everyone knows what to buy and what's already in the cart.
The app works in any browser on both mobile and desktop. Just one password to log in - no complicated registration required.
I needed an app that would let me and my wife create a shopping list together and do grocery shopping quickly and efficiently. I tested various solutions, but none of them were simple and fast enough.
I built the first version in Next.js, but it turned out to be very resource-heavy. I have a lot of other things running on my server, so I decided to optimize. I rewrote the app in Go and now it uses only ~2.5 MB RAM instead of hundreds of megabytes!
- Ultra-lightweight - ~16 MB on disk, ~2.5 MB RAM
- Multiple lists - Create separate lists for different stores or purposes, with custom icons
- PWA - Install on your phone like a native app
- Offline mode - Add, edit, check/uncheck products without internet (auto-sync when back online)
- Auto-completion - Fuzzy search suggestions from your history, remembers sections
- Organize products into sections (e.g., Dairy, Vegetables, Cleaning)
- Mark products as purchased
- Mark products as "uncertain" (can't find it in the store)
- Real-time synchronization (WebSocket)
- Responsive interface (mobile-first)
- Dark mode - Automatic theme based on system preferences
- Multi-language support (PL, EN, DE, ES, FR, PT, UK, NO, LT, EL, SK, SV, RU)
- Simple login system
- Rate limiting protection against brute-force attacks
- REST API - Programmatic access for integrations and migrations (docs)
- Backend: Go 1.21 + Fiber
- Frontend: HTMX + Alpine.js + Tailwind CSS
- Database: SQLite
You can run Koffan directly on your machine using Go. This works on any system (macOS, Linux, Windows).
macOS (Homebrew):
brew install goLinux (Debian/Ubuntu):
sudo apt install golang-goWindows: Download from go.dev/dl
git clone https://github.com/PanSalut/Koffan.git
cd Koffan
go run main.goApp available at http://localhost:3000
Default password: shopping123
To set a custom password:
APP_PASSWORD=yourpassword go run main.godocker run -d -p 3000:80 -e APP_PASSWORD=yourpassword -v koffan-data:/data ghcr.io/pansalut/koffan:latestApp available at http://localhost:3000
docker-compose up -d
# App available at http://localhost:80| Variable | Default | Description |
|---|---|---|
APP_ENV |
development |
Set to production for secure cookies |
APP_PASSWORD |
shopping123 |
Login password |
DISABLE_AUTH |
false |
Set to true to disable authentication (for reverse proxy setups) |
PORT |
80 (Docker) / 3000 (local) |
Server port |
DB_PATH |
./shopping.db |
Database file path |
DEFAULT_LANG |
en |
Default UI language (pl, en, de, es, fr, pt, uk, no, lt, el, sk, ru) |
LOGIN_MAX_ATTEMPTS |
5 |
Max login attempts before lockout |
LOGIN_WINDOW_MINUTES |
15 |
Time window for counting attempts |
LOGIN_LOCKOUT_MINUTES |
30 |
Lockout duration after exceeding limit |
API_TOKEN |
(disabled) | Enable REST API with this token (docs) |
A Makefile is provided to build and push the Docker image to your own registry.
| Command | Description |
|---|---|
make build REGISTRY=... |
Build the image (tagged with current version and latest) |
make push REGISTRY=... |
Push both tags to the registry |
make release REGISTRY=... |
Build then push in one step |
# Build and push in one step
make release REGISTRY=registry.example.com
# Or step by step
make build REGISTRY=registry.example.com
make push REGISTRY=registry.example.comThe tag is resolved automatically in this order:
- Latest git tag (
git describe --tags --abbrev=0) - Content of the
VERSIONfile if no git tag is found
To override the tag explicitly, pass TAG= on the command line:
make release REGISTRY=registry.example.com TAG=v2.3Note: the variable is
TAG, notVERSION. PassingVERSION=has no effect.
The resulting image references will be:
registry.example.com/koffan:v2.3registry.example.com/koffan:latest
REGISTRYis required — the command will fail with an error if omitted.
Koffan supports delegating authentication entirely to Authentik via Traefik's forward auth mechanism. In this mode, Koffan's built-in login is disabled and Authentik handles the auth flow.
Browser → Traefik → Authentik (forward auth check) → Koffan
For each request, Traefik asks Authentik whether the user is authenticated. If not, Authentik redirects to its login page. Once authenticated, the request is forwarded to Koffan with DISABLE_AUTH=true, which skips Koffan's own session checks.
In the Authentik admin panel:
- Create a Provider → Type: Forward Auth (single application)
- Authentication flow: your default flow
- Authorization flow: your default flow
- External host:
https://koffan.example.com
- Create an Application linked to this provider
- Assign the application to the users or groups that should have access
If your Authentik outpost doesn't already define the authentik middleware, add it to your Traefik static or dynamic config (or in the Authentik outpost's own docker-compose.yaml labels):
labels:
- "traefik.http.middlewares.authentik.forwardauth.address=http://<authentik-outpost>:9000/outpost.goauthentik.io/auth/traefik"
- "traefik.http.middlewares.authentik.forwardauth.trustForwardHeader=true"
- "traefik.http.middlewares.authentik.forwardauth.authResponseHeaders=X-authentik-username,X-authentik-groups,X-authentik-email,X-authentik-name,X-authentik-uid"Replace <authentik-outpost> with the hostname or container name of your Authentik proxy outpost.
If the middleware is already defined elsewhere (e.g.
authentik@fileorauthentik@docker), skip this step and just setAUTHENTIK_MIDDLEWAREaccordingly.
Copy .env.example to .env and fill in the values:
DATA_DIR=./dataThen start the stack:
docker compose up -dKoffan will be accessible at https://koffan.example.com, protected by Authentik. The built-in login page is no longer reachable.
git clone https://github.com/PanSalut/Koffan.git
cd Koffan
docker build -t koffan .
docker run -d -p 80:80 -e APP_PASSWORD=your-password -v koffan-data:/data koffan- Add new resource → Docker Compose → Select your Git repository or use
https://github.com/PanSalut/Koffan - Set domain in Domains section
- Enable Connect to Predefined Network in Advanced settings
- Add environment variable
APP_PASSWORDwith your password - Deploy
Data is stored in /data/shopping.db. The volume ensures your data persists across deployments.
For more information, check the Wiki:
- REST API - Programmatic access, migrations, integrations
- Multiple Instances - Running separate instances for different households
Have an idea? Check open feature requests and vote with 👍 on the ones you want most.
Want to suggest something new? Create an issue.
I love and admire the open source philosophy. That's why I created Koffan - to give back to the community that has given me so much over the years.
If you find this project useful and want to support my work (completely optional!), you can become a sponsor:
I'm incredibly grateful to these amazing people for supporting Koffan:
MIT License with Commons Clause.
You are free to use, modify, and share this software for any purpose, including commercial use within your organization. However, you may not sell the software or offer it as a paid service.

