# Heimdall Dashboard — Direct SQLite Management

Adding, updating, and removing tiles by directly editing Heimdall's `app.sqlite` database instead of the web UI. Useful for bulk operations, or when the UI isn't accessible.

## Database Location

```
/var/lib/docker/volumes/heimdall_config/_data/www/app.sqlite
```

Access requires sudo (Docker volume data is root-owned).

## Table Structure

### `items` table — the dashboard tiles

Key columns:
| Column | Type | Notes |
|--------|------|-------|
| `id` | INTEGER | Auto-increment PK |
| `title` | TEXT | Display name on tile |
| `url` | TEXT | Link target |
| `colour` | TEXT | Hex color (e.g. `#d48c3c`) |
| `icon` | TEXT | Empty string for no custom icon |
| `description` | TEXT | Optional subtitle |
| `pinned` | INTEGER | 0 = no, 1 = yes |
| `order` | INTEGER | Sort order — **must be 0** like all other items |
| `type` | INTEGER | **Must be 0** (not string "0") |
| `user_id` | INTEGER | Usually 1 |
| `class` | TEXT | **Must be NULL** for custom items (not a class name) |
| `appid` | TEXT | NULL for custom items |
| `deleted_at` | TEXT | NULL = active, timestamp = soft-deleted |
| `created_at` | TEXT | Can be NULL |
| `updated_at` | TEXT | Can be NULL |

### `item_tag` table — required for visibility

**Every item MUST have a corresponding entry in `item_tag`** or it won't appear on the dashboard!

```sql
INSERT INTO item_tag (item_id, tag_id) VALUES (<item_id>, 0);
```

All items use `tag_id=0`.

## Adding a Tile

```python
import sqlite3
db = "/var/lib/docker/volumes/heimdall_config/_data/www/app.sqlite"
conn = sqlite3.connect(db)

# Step 1: Insert the item
conn.execute("""
    INSERT INTO items (title, colour, url, description, pinned, "order", type, user_id, class)
    VALUES (?, ?, ?, ?, 0, 0, 0, 1, NULL)
""", ("Service Name", "#hexcolor", "http://192.168.50.98:PORT", "Optional description"))

# Step 2: Add the tag entry (MANDATORY — without this, tile won't show)
conn.execute("""
    INSERT INTO item_tag (item_id, tag_id)
    VALUES ((SELECT id FROM items WHERE title='Service Name'), 0)
""")

conn.commit()
conn.close()
```

## Updating URLs (Bulk)

```sql
-- Change all IPs at once
UPDATE items SET url = REPLACE(url, '192.168.50.150', '192.168.50.98');
```

## Deleting the Cache

Heimdall uses Laravel caching — after DB changes, clear it:

```sql
DELETE FROM cache;
DELETE FROM cache_locks;
```

## Common Issues

### Tile not appearing after insert
1. **Missing `item_tag` entry** — most common cause. Check with: `SELECT * FROM item_tag WHERE item_id=<id>;`
2. **Wrong `class` value** — custom items need `class=NULL`, not a string like "Audiobookshelf". Heimdall tries to load a PHP class from that name.
3. **`order` != 0** — items with non-zero order may be hidden. All working items use `order=0`.
4. **`type` is string "0" not integer 0** — set type to integer 0.
