Skip to content

Commit f00614c

Browse files
committed
added stats endpoint for dashboards
1 parent b7052a1 commit f00614c

File tree

2 files changed

+115
-0
lines changed

2 files changed

+115
-0
lines changed

backend/main.py

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1499,6 +1499,67 @@ async def toggle_plugin(request: Request, plugin_name: str, enabled: dict):
14991499
raise HTTPException(status_code=500, detail=safe_error_message(e, "Failed to toggle plugin"))
15001500

15011501

1502+
# ============================================================================
1503+
# Stats Endpoint (for dashboards)
1504+
# ============================================================================
1505+
1506+
@api_router.get("/stats", tags=["Stats"])
1507+
@limiter.limit("30/minute")
1508+
async def get_stats(request: Request):
1509+
"""
1510+
Get application statistics at a glance.
1511+
1512+
Designed for dashboard widgets (e.g., Homepage) - lightweight and cached.
1513+
Returns counts of notes, folders, tags, templates, media, and other metadata.
1514+
"""
1515+
try:
1516+
notes_dir = config['storage']['notes_dir']
1517+
1518+
# Get notes and folders (cached)
1519+
notes, folders = scan_notes_fast_walk(notes_dir, include_media=True)
1520+
1521+
# Separate notes from media
1522+
note_items = [n for n in notes if n.get('type') == 'note']
1523+
media_items = [n for n in notes if n.get('type') != 'note']
1524+
1525+
# Count unique tags
1526+
all_tags = set()
1527+
for note in note_items:
1528+
all_tags.update(note.get('tags', []))
1529+
1530+
# Get templates count
1531+
templates = get_templates(notes_dir)
1532+
1533+
# Calculate total size
1534+
total_size = sum(n.get('size', 0) for n in notes)
1535+
1536+
# Get last modified (notes are already sorted by modified desc)
1537+
last_modified = note_items[0].get('modified') if note_items else None
1538+
1539+
# Count enabled plugins
1540+
enabled_plugins = sum(1 for p in plugin_manager.plugins.values() if p.enabled)
1541+
1542+
# Read version
1543+
version = "unknown"
1544+
version_file = Path(__file__).parent.parent / "VERSION"
1545+
if version_file.exists():
1546+
version = version_file.read_text().strip()
1547+
1548+
return {
1549+
"notes_count": len(note_items),
1550+
"folders_count": len(folders),
1551+
"tags_count": len(all_tags),
1552+
"templates_count": len(templates),
1553+
"media_count": len(media_items),
1554+
"total_size_bytes": total_size,
1555+
"last_modified": last_modified,
1556+
"plugins_enabled": enabled_plugins,
1557+
"version": version
1558+
}
1559+
except Exception as e:
1560+
raise HTTPException(status_code=500, detail=safe_error_message(e, "Failed to get stats"))
1561+
1562+
15021563
# ============================================================================
15031564
# Share Token Endpoints (authenticated)
15041565
# ============================================================================

documentation/API.md

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,60 @@ GET /api/config
452452
```
453453
Returns application configuration.
454454

455+
### Get Stats
456+
```http
457+
GET /api/stats
458+
```
459+
Returns application statistics at a glance. Designed for dashboard widgets (e.g., Homepage) - lightweight and uses cached data.
460+
461+
**Response:**
462+
```json
463+
{
464+
"notes_count": 142,
465+
"folders_count": 12,
466+
"tags_count": 37,
467+
"templates_count": 5,
468+
"media_count": 23,
469+
"total_size_bytes": 2458624,
470+
"last_modified": "2026-03-17T14:32:00Z",
471+
"plugins_enabled": 3,
472+
"version": "0.19.1"
473+
}
474+
```
475+
476+
| Field | Description |
477+
|-------|-------------|
478+
| `notes_count` | Total number of markdown notes |
479+
| `folders_count` | Total number of folders |
480+
| `tags_count` | Number of unique tags across all notes |
481+
| `templates_count` | Number of templates in `_templates` folder |
482+
| `media_count` | Number of media files (images, etc.) |
483+
| `total_size_bytes` | Total size of all files in bytes |
484+
| `last_modified` | ISO timestamp of most recently modified note |
485+
| `plugins_enabled` | Number of enabled plugins |
486+
| `version` | Application version |
487+
488+
**Example ([Homepage](https://gethomepage.dev/) dashboard widget):**
489+
```yaml
490+
- NoteDiscovery:
491+
href: https://notediscovery.homelab.local
492+
icon: notediscovery
493+
container: homelab-notediscovery
494+
widget:
495+
type: customapi
496+
url: http://notediscovery:8000/api/stats
497+
refreshInterval: 60000
498+
mappings:
499+
- field: notes_count
500+
label: Notes
501+
- field: tags_count
502+
label: Tags
503+
- field: folders_count
504+
label: Folders
505+
- field: version
506+
label: Version
507+
```
508+
455509
### Health Check
456510
```http
457511
GET /health

0 commit comments

Comments
 (0)