Skip to content

turbothomas01/KitchenIO

Repository files navigation

KitchenIO

KitchenIO logo

KitchenIO is a small self-hosted grocery list service. Version 1 is intentionally focused on two simple lists: products at home and the shopping list.

It is similar in concept to Grocy, but intentionally simpler for daily use.

Features

  • Accessible web UI built with semantic HTML.
  • Products tab with product name, amount, and plus/minus controls.
  • Shopping List tab with checkbox, item name, amount, and plus/minus controls.
  • Floating + button with tab-specific accessible label.
  • Light and dark themes.
  • English and Norwegian UI language.
  • Settings page for default theme, default language, and API key creation.
  • Optional API key protection for integrations: once a key exists, API calls require it.
  • SQLite storage.
  • REST API for Home Assistant, Hermes Agent, scripts, and automations.
  • Home Assistant custom integration under custom_components/kitchenio.
  • Shopping-list items sync both ways with the default Home Assistant todo.shopping_list.
  • Accessible modal add screen opened from a + button.
  • Docker and Docker Compose support.
  • Basic automated tests.

Architecture

KitchenIO is intentionally simple for home hosting:

  • Backend: FastAPI
  • Database: SQLite
  • Frontend: server-rendered HTML with minimal CSS
  • Container: Docker image exposing port 8000

No Node.js build step is required.

Quick start with Docker Compose

git clone https://github.com/turbothomas01/KitchenIO.git
cd KitchenIO
docker compose up -d --build

Open:

http://localhost:8000

Data is stored in the Docker volume kitchenio-data.

Local development setup

git clone https://github.com/turbothomas01/KitchenIO.git
cd KitchenIO
python3 -m venv .venv
. .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install -r requirements.txt -r requirements-dev.txt
python -m uvicorn kitchenio.app:app --reload

Open:

http://localhost:8000

By default, the SQLite database is created at data/kitchenio.db. Override it with:

KITCHENIO_DB=/path/to/kitchenio.db python -m uvicorn kitchenio.app:app --reload

Running tests

. .venv/bin/activate
python -m pytest -q

Settings and API keys

Open the settings page from the KitchenIO header, or go directly to:

http://localhost:8000/settings

The settings page lets you choose the default UI language and theme. It also lets you create API keys for trusted integrations such as Home Assistant and Hermes Agent.

API key behavior is intentionally simple for home setup:

  • If no API key exists yet, the API is open on the local server so you can bootstrap KitchenIO.
  • After you create the first API key, API endpoints require a valid key.
  • The UI remains available locally for managing KitchenIO.
  • Newly generated keys are shown once. Copy the key immediately.
  • After the first key exists, creating additional keys from settings requires entering an existing API key.

Use either header format:

X-API-Key: kio_your_key_here

or:

Authorization: Bearer kio_your_key_here

Home Assistant integration

The repository includes a HACS-compatible custom integration in custom_components/kitchenio.

Recommended display:

  • Use sensor.kitchenio_stock as a single stock summary sensor.
  • Use the sensor's items, low_stock_items, and stock_table attributes for dashboard cards and automations.
  • Keep shopping in Home Assistant's built-in list, todo.shopping_list, instead of managing a second list.
  • Open shopping-list items sync both ways between Home Assistant and the KitchenIO dashboard, with kitchenio.sync_shopping_list available for immediate syncs.
  • Home Assistant shopping items use the Name x1, Name x2 quantity format.

Full setup instructions are in docs/home-assistant.md.

Accessibility notes

KitchenIO is designed accessibility-first:

  • Semantic headings, forms, labels, lists, buttons, and landmarks.
  • The main navigation uses accessible tab semantics.
  • Every input has an associated <label>.
  • Buttons use visible text.
  • Keyboard users can reach every control with normal tab navigation.
  • Focus indicators are visible in both themes.
  • Completion state is communicated with text, not color alone.
  • Light and dark themes maintain strong contrast.
  • The language selector updates the document lang attribute.

API documentation

Interactive OpenAPI documentation is available at:

http://localhost:8000/docs

Raw OpenAPI JSON is available at:

http://localhost:8000/openapi.json

Health check

GET /health

Response:

{"status":"ok"}

Stock endpoints

List stock items

GET /api/stock

Example response:

[
  {
    "id": 1,
    "name": "Coffee",
    "description": "Whole beans",
    "amount": "1"
  }
]

Add stock item

POST /api/stock
Content-Type: application/json

{
  "name": "Coffee",
  "description": "Whole beans",
  "amount": "1"
}

Update stock item

PUT /api/stock/1
Content-Type: application/json

{
  "name": "Coffee",
  "description": "Whole beans",
  "amount": "2"
}

Delete stock item

DELETE /api/stock/1

Add stock item to shopping list

POST /api/stock/1/add-to-shopping-list

This creates a shopping list item using the stock item's name and amount.

Shopping list endpoints

List shopping list items

GET /api/shopping-list

Example response:

[
  {
    "id": 1,
    "item": "Milk",
    "amount": "2",
    "completed": false,
    "stock_item_id": null
  }
]

Add shopping list item

Plain text item:

POST /api/shopping-list
Content-Type: application/json

{
  "item": "Milk",
  "amount": "2"
}

Item linked to stock:

POST /api/shopping-list
Content-Type: application/json

{
  "item": "Coffee",
  "amount": "1",
  "stock_item_id": 1
}

Update shopping list item

PUT /api/shopping-list/1
Content-Type: application/json

{
  "item": "Milk",
  "amount": "3",
  "completed": false,
  "stock_item_id": null
}

Delete shopping list item

DELETE /api/shopping-list/1

Mark shopping list item completed

POST /api/shopping-list/1/complete

Home Assistant examples

Replace http://kitchenio.local:8000 with your KitchenIO URL. If you have created an API key in KitchenIO settings, include it in each REST call.

Example header:

headers:
  X-API-Key: !secret kitchenio_api_key

REST sensor for stock

sensor:
  - platform: rest
    name: KitchenIO Stock
    resource: http://kitchenio.local:8000/api/stock
    headers:
      X-API-Key: !secret kitchenio_api_key
    value_template: "{{ value_json | count }}"
    json_attributes:
      - id
      - name
      - description
      - amount

REST command: add item to shopping list

rest_command:
  kitchenio_add_shopping_item:
    url: http://kitchenio.local:8000/api/shopping-list
    method: POST
    headers:
      content-type: application/json
      X-API-Key: !secret kitchenio_api_key
    payload: >
      {
        "item": "{{ item }}",
        "amount": "{{ amount }}"
      }

Call it from an automation or script:

action: rest_command.kitchenio_add_shopping_item
data:
  item: Milk
  amount: "2"

Automation example

alias: Add milk to KitchenIO shopping list from helper
trigger:
  - platform: state
    entity_id: input_button.add_milk_to_shopping_list
action:
  - service: rest_command.kitchenio_add_shopping_item
    data:
      item: Milk
      amount: "1"

Hermes Agent usage examples

KitchenIO's API uses simple JSON, predictable endpoints, and a single API key header, so Hermes Agent can call it directly. Create a key on /settings, store it securely, and send it as X-API-Key.

Examples of commands Hermes Agent can perform:

  • “Add milk to the shopping list”
    • POST /api/shopping-list with {"item":"milk","amount":"1"}
  • “Add 2 bread to the shopping list”
    • POST /api/shopping-list with {"item":"bread","amount":"2"}
  • “Show what is in stock”
    • GET /api/stock
  • “Add coffee to stock with amount 1”
    • POST /api/stock with {"name":"coffee","description":"","amount":"1"}
  • “Move eggs from stock to shopping list”
    • GET /api/stock, find eggs, then POST /api/stock/{id}/add-to-shopping-list

Example curl commands:

curl http://localhost:8000/api/stock \
  -H "X-API-Key: $KITCHENIO_API_KEY"

curl -X POST http://localhost:8000/api/stock \
  -H 'Content-Type: application/json' \
  -H "X-API-Key: $KITCHENIO_API_KEY" \
  -d '{"name":"Coffee","description":"Whole beans","amount":"1"}'

curl -X POST http://localhost:8000/api/shopping-list \
  -H 'Content-Type: application/json' \
  -H "X-API-Key: $KITCHENIO_API_KEY" \
  -d '{"item":"Milk","amount":"2"}'

Error handling

  • Missing or invalid fields return 422 Unprocessable Entity with validation details.
  • Unknown stock items return 404 with Stock item not found.
  • Unknown shopping list items return 404 with Shopping list item not found.

Roadmap boundaries

KitchenIO is intentionally focused. Please do not add Grocy-like extras unless explicitly requested later, such as:

  • recipes
  • chores
  • batteries
  • calendars
  • meal planning
  • barcode scanning

About

Minimal self-hosted stock and shopping list management service

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors