vibetuner 2.6.1__py3-none-any.whl → 2.7.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of vibetuner might be problematic. Click here for more details.

Files changed (85) hide show
  1. vibetuner/__init__.py +2 -0
  2. vibetuner/__main__.py +4 -0
  3. vibetuner/cli/__init__.py +68 -0
  4. vibetuner/cli/run.py +161 -0
  5. vibetuner/config.py +128 -0
  6. vibetuner/context.py +25 -0
  7. vibetuner/frontend/AGENTS.md +113 -0
  8. vibetuner/frontend/CLAUDE.md +113 -0
  9. vibetuner/frontend/__init__.py +94 -0
  10. vibetuner/frontend/context.py +10 -0
  11. vibetuner/frontend/deps.py +41 -0
  12. vibetuner/frontend/email.py +45 -0
  13. vibetuner/frontend/hotreload.py +13 -0
  14. vibetuner/frontend/lifespan.py +26 -0
  15. vibetuner/frontend/middleware.py +151 -0
  16. vibetuner/frontend/oauth.py +196 -0
  17. vibetuner/frontend/routes/__init__.py +12 -0
  18. vibetuner/frontend/routes/auth.py +150 -0
  19. vibetuner/frontend/routes/debug.py +414 -0
  20. vibetuner/frontend/routes/health.py +33 -0
  21. vibetuner/frontend/routes/language.py +43 -0
  22. vibetuner/frontend/routes/meta.py +55 -0
  23. vibetuner/frontend/routes/user.py +94 -0
  24. vibetuner/frontend/templates.py +176 -0
  25. vibetuner/logging.py +87 -0
  26. vibetuner/models/AGENTS.md +165 -0
  27. vibetuner/models/CLAUDE.md +165 -0
  28. vibetuner/models/__init__.py +14 -0
  29. vibetuner/models/blob.py +89 -0
  30. vibetuner/models/email_verification.py +84 -0
  31. vibetuner/models/mixins.py +76 -0
  32. vibetuner/models/oauth.py +57 -0
  33. vibetuner/models/registry.py +15 -0
  34. vibetuner/models/types.py +16 -0
  35. vibetuner/models/user.py +91 -0
  36. vibetuner/mongo.py +18 -0
  37. vibetuner/paths.py +112 -0
  38. vibetuner/services/AGENTS.md +104 -0
  39. vibetuner/services/CLAUDE.md +104 -0
  40. vibetuner/services/__init__.py +0 -0
  41. vibetuner/services/blob.py +175 -0
  42. vibetuner/services/email.py +50 -0
  43. vibetuner/tasks/AGENTS.md +98 -0
  44. vibetuner/tasks/CLAUDE.md +98 -0
  45. vibetuner/tasks/__init__.py +2 -0
  46. vibetuner/tasks/context.py +34 -0
  47. vibetuner/tasks/worker.py +18 -0
  48. vibetuner/templates/email/AGENTS.md +48 -0
  49. vibetuner/templates/email/CLAUDE.md +48 -0
  50. vibetuner/templates/email/default/magic_link.html.jinja +16 -0
  51. vibetuner/templates/email/default/magic_link.txt.jinja +5 -0
  52. vibetuner/templates/frontend/AGENTS.md +74 -0
  53. vibetuner/templates/frontend/CLAUDE.md +74 -0
  54. vibetuner/templates/frontend/base/favicons.html.jinja +1 -0
  55. vibetuner/templates/frontend/base/footer.html.jinja +3 -0
  56. vibetuner/templates/frontend/base/header.html.jinja +0 -0
  57. vibetuner/templates/frontend/base/opengraph.html.jinja +7 -0
  58. vibetuner/templates/frontend/base/skeleton.html.jinja +42 -0
  59. vibetuner/templates/frontend/debug/collections.html.jinja +103 -0
  60. vibetuner/templates/frontend/debug/components/debug_nav.html.jinja +55 -0
  61. vibetuner/templates/frontend/debug/index.html.jinja +83 -0
  62. vibetuner/templates/frontend/debug/info.html.jinja +256 -0
  63. vibetuner/templates/frontend/debug/users.html.jinja +137 -0
  64. vibetuner/templates/frontend/debug/version.html.jinja +53 -0
  65. vibetuner/templates/frontend/email/magic_link.txt.jinja +5 -0
  66. vibetuner/templates/frontend/email_sent.html.jinja +82 -0
  67. vibetuner/templates/frontend/index.html.jinja +19 -0
  68. vibetuner/templates/frontend/lang/select.html.jinja +4 -0
  69. vibetuner/templates/frontend/login.html.jinja +84 -0
  70. vibetuner/templates/frontend/meta/browserconfig.xml.jinja +10 -0
  71. vibetuner/templates/frontend/meta/robots.txt.jinja +3 -0
  72. vibetuner/templates/frontend/meta/site.webmanifest.jinja +7 -0
  73. vibetuner/templates/frontend/meta/sitemap.xml.jinja +6 -0
  74. vibetuner/templates/frontend/user/edit.html.jinja +85 -0
  75. vibetuner/templates/frontend/user/profile.html.jinja +156 -0
  76. vibetuner/templates/markdown/.placeholder +0 -0
  77. vibetuner/templates/markdown/AGENTS.md +29 -0
  78. vibetuner/templates/markdown/CLAUDE.md +29 -0
  79. vibetuner/templates.py +152 -0
  80. vibetuner/time.py +57 -0
  81. vibetuner/versioning.py +8 -0
  82. {vibetuner-2.6.1.dist-info → vibetuner-2.7.1.dist-info}/METADATA +2 -1
  83. vibetuner-2.7.1.dist-info/RECORD +84 -0
  84. vibetuner-2.6.1.dist-info/RECORD +0 -4
  85. {vibetuner-2.6.1.dist-info → vibetuner-2.7.1.dist-info}/WHEEL +0 -0
@@ -0,0 +1,5 @@
1
+ Sign in to {{ project_name }}
2
+ Copy and paste this link into your browser to sign in:
3
+ {{ login_url }}
4
+ This link will expire in 15 minutes.
5
+ If you didn't request this, you can safely ignore this email.
@@ -0,0 +1,74 @@
1
+ # Core Frontend Templates - DO NOT MODIFY
2
+
3
+ **⚠️ IMPORTANT**: Package-managed files. Changes will be lost on package updates.
4
+
5
+ ## How to Override
6
+
7
+ **NEVER modify files in this directory!** Instead:
8
+
9
+ 1. Copy template to your project's `templates/frontend/`
10
+ 2. Maintain the same directory structure
11
+ 3. Your version overrides automatically
12
+
13
+ ### Example
14
+
15
+ ```bash
16
+ # Core template (DO NOT EDIT, bundled in vibetuner package):
17
+ vibetuner/templates/frontend/base/footer.html.jinja
18
+
19
+ # Your override (CREATE THIS in your project):
20
+ templates/frontend/base/footer.html.jinja
21
+ ```
22
+
23
+ The template system searches in order:
24
+
25
+ 1. `templates/frontend/` (your project overrides)
26
+ 2. `vibetuner/templates/frontend/` (package defaults)
27
+
28
+ ## Template Structure
29
+
30
+ ```text
31
+ vibetuner/frontend/
32
+ ├── base/ # Core layout
33
+ │ ├── skeleton.html.jinja
34
+ │ ├── header.html.jinja
35
+ │ ├── footer.html.jinja
36
+ │ ├── opengraph.html.jinja
37
+ │ └── favicons.html.jinja
38
+ ├── debug/ # Dev tools (DEBUG mode only)
39
+ │ ├── index.html.jinja
40
+ │ ├── info.html.jinja
41
+ │ ├── users.html.jinja
42
+ │ ├── collections.html.jinja
43
+ │ └── version.html.jinja
44
+ ├── email/ # Email-related pages
45
+ │ └── magic_link templates
46
+ ├── lang/ # Language switcher
47
+ │ └── select.html.jinja
48
+ ├── meta/ # SEO and meta files
49
+ │ ├── robots.txt.jinja
50
+ │ ├── sitemap.xml.jinja
51
+ │ ├── site.webmanifest.jinja
52
+ │ └── browserconfig.xml.jinja
53
+ ├── user/ # User account pages
54
+ │ ├── profile.html.jinja
55
+ │ └── edit.html.jinja
56
+ ├── index.html.jinja # Default homepage
57
+ ├── login.html.jinja # Login page
58
+ └── email_sent.html.jinja # Magic link sent confirmation
59
+ ```
60
+
61
+ ## Common Overrides
62
+
63
+ - `base/skeleton.html.jinja` - Add meta tags, global CSS/JS
64
+ - `base/header.html.jinja` - Customize navigation
65
+ - `base/footer.html.jinja` - Custom footer
66
+ - `index.html.jinja` - Custom homepage
67
+
68
+ ## Best Practices
69
+
70
+ 1. Override only what you need
71
+ 2. Document why each override exists
72
+ 3. Test after `just update-scaffolding`
73
+ 4. Use template inheritance and blocks
74
+ 5. Keep overrides minimal to ease updates
@@ -0,0 +1,74 @@
1
+ # Core Frontend Templates - DO NOT MODIFY
2
+
3
+ **⚠️ IMPORTANT**: Package-managed files. Changes will be lost on package updates.
4
+
5
+ ## How to Override
6
+
7
+ **NEVER modify files in this directory!** Instead:
8
+
9
+ 1. Copy template to your project's `templates/frontend/`
10
+ 2. Maintain the same directory structure
11
+ 3. Your version overrides automatically
12
+
13
+ ### Example
14
+
15
+ ```bash
16
+ # Core template (DO NOT EDIT, bundled in vibetuner package):
17
+ vibetuner/templates/frontend/base/footer.html.jinja
18
+
19
+ # Your override (CREATE THIS in your project):
20
+ templates/frontend/base/footer.html.jinja
21
+ ```
22
+
23
+ The template system searches in order:
24
+
25
+ 1. `templates/frontend/` (your project overrides)
26
+ 2. `vibetuner/templates/frontend/` (package defaults)
27
+
28
+ ## Template Structure
29
+
30
+ ```text
31
+ vibetuner/frontend/
32
+ ├── base/ # Core layout
33
+ │ ├── skeleton.html.jinja
34
+ │ ├── header.html.jinja
35
+ │ ├── footer.html.jinja
36
+ │ ├── opengraph.html.jinja
37
+ │ └── favicons.html.jinja
38
+ ├── debug/ # Dev tools (DEBUG mode only)
39
+ │ ├── index.html.jinja
40
+ │ ├── info.html.jinja
41
+ │ ├── users.html.jinja
42
+ │ ├── collections.html.jinja
43
+ │ └── version.html.jinja
44
+ ├── email/ # Email-related pages
45
+ │ └── magic_link templates
46
+ ├── lang/ # Language switcher
47
+ │ └── select.html.jinja
48
+ ├── meta/ # SEO and meta files
49
+ │ ├── robots.txt.jinja
50
+ │ ├── sitemap.xml.jinja
51
+ │ ├── site.webmanifest.jinja
52
+ │ └── browserconfig.xml.jinja
53
+ ├── user/ # User account pages
54
+ │ ├── profile.html.jinja
55
+ │ └── edit.html.jinja
56
+ ├── index.html.jinja # Default homepage
57
+ ├── login.html.jinja # Login page
58
+ └── email_sent.html.jinja # Magic link sent confirmation
59
+ ```
60
+
61
+ ## Common Overrides
62
+
63
+ - `base/skeleton.html.jinja` - Add meta tags, global CSS/JS
64
+ - `base/header.html.jinja` - Customize navigation
65
+ - `base/footer.html.jinja` - Custom footer
66
+ - `index.html.jinja` - Custom homepage
67
+
68
+ ## Best Practices
69
+
70
+ 1. Override only what you need
71
+ 2. Document why each override exists
72
+ 3. Test after `just update-scaffolding`
73
+ 4. Use template inheritance and blocks
74
+ 5. Keep overrides minimal to ease updates
@@ -0,0 +1 @@
1
+ <link rel="manifest" href="{{ url_for("site_webmanifest").path }}" />
@@ -0,0 +1,3 @@
1
+ <footer class="pb-8 text-center">
2
+ <p class="text-sm text-slate-500 font-light tracking-wide">Version: {{ version }}/{{ v_hash }} | {{ copyright }}</p>
3
+ </footer>
File without changes
@@ -0,0 +1,7 @@
1
+ {% set page_title = self.title() if self.title is defined else project_name.title() %}
2
+ <meta name="twitter:card" content="summary" />
3
+ <meta name="twitter:title" content="{{ page_title }}" />
4
+ <meta property="og:type" content="website" />
5
+ <meta property="og:url" content="{{ request.url }}" />
6
+ <meta property="og:description" content="{{ project_description }}" />
7
+ <meta property="og:title" content="{{ page_title }}" />
@@ -0,0 +1,42 @@
1
+ <!DOCTYPE html>
2
+ <html lang="{{ request.state.language }}">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <meta name="description" content="{{ meta_description | default("") }}" />
7
+ <meta name="keywords" content="{{ meta_keywords | default("") }}" />
8
+ <meta name="color-scheme" content="light" />
9
+ <title>
10
+ {% block title %}
11
+ {% endblock title %}
12
+ </title>
13
+ <link rel="stylesheet" href="{{ url_for('css', path='bundle.css').path }}" />
14
+ <script src="{{ url_for('js', path='bundle.js').path }}"></script>
15
+ {% if umami_website_id and not DEBUG %}
16
+ <script defer src="/meta.js" data-website-id="{{ umami_website_id }}"></script>
17
+ {% endif %}
18
+ {% include "base/favicons.html.jinja" %}
19
+ {% include "base/opengraph.html.jinja" %}
20
+ {% block head %}
21
+ {% endblock head %}
22
+ </head>
23
+ <body hx-ext="preload" preload="mousedown" class="{{ BODY_CLASS }}">
24
+ {% block start_of_body %}
25
+ {% endblock start_of_body %}
26
+ {% block header %}
27
+ {% if not SKIP_HEADER %}
28
+ {% include "base/header.html.jinja" %}
29
+ {% endif %}
30
+ {% endblock header %}
31
+ {% block body %}
32
+ {% endblock body %}
33
+ {% block footer %}
34
+ {% if not SKIP_FOOTER %}
35
+ {% include "base/footer.html.jinja" %}
36
+ {% endif %}
37
+ {% endblock footer %}
38
+ {% if DEBUG %}{{ hotreload.script(url_for('hot-reload') ) | safe }}{% endif %}
39
+ {% block end_of_body %}
40
+ {% endblock end_of_body %}
41
+ </body>
42
+ </html>
@@ -0,0 +1,103 @@
1
+ {% extends "base/skeleton.html.jinja" %}
2
+ {% block title %}
3
+ Database Collections Schema - Debug
4
+ {% endblock title %}
5
+ {% block body %}
6
+ <div class="container mx-auto px-4 py-8 max-w-6xl">
7
+ <!-- Header -->
8
+ <header class="mb-8">
9
+ <h1 class="text-4xl font-bold text-base-content mb-2">Database Collections Schema</h1>
10
+ <p class="text-base-content/70">Overview of all MongoDB collections and their field schemas</p>
11
+ </header>
12
+ <!-- Collections Grid -->
13
+ <div class="grid gap-6">
14
+ {% for collection in collections %}
15
+ <div class="card bg-base-100 shadow-xl border border-base-200">
16
+ <div class="card-body">
17
+ <!-- Collection Header -->
18
+ <div class="flex items-center justify-between mb-4">
19
+ <div>
20
+ <h2 class="card-title text-2xl text-primary">{{ collection.name }}</h2>
21
+ <p class="text-sm text-base-content/60">Model: {{ collection.model_name }}</p>
22
+ </div>
23
+ <div class="badge badge-secondary">{{ collection.total_fields }} fields</div>
24
+ </div>
25
+ <!-- Fields Table -->
26
+ <div class="overflow-x-auto">
27
+ <table class="table table-zebra w-full">
28
+ <thead>
29
+ <tr>
30
+ <th class="text-left w-48">Field Name</th>
31
+ <th class="text-left min-w-64">Type</th>
32
+ <th class="text-left">Description</th>
33
+ <th class="text-center w-24">Required</th>
34
+ <th class="text-left w-48">Constraints</th>
35
+ </tr>
36
+ </thead>
37
+ <tbody>
38
+ {% for field in collection.fields %}
39
+ <tr class="align-top">
40
+ <td>
41
+ <code class="text-sm bg-base-200 px-2 py-1 rounded font-mono">{{ field.name }}</code>
42
+ </td>
43
+ <td>
44
+ <div class="font-mono text-xs text-base-content/90 max-w-xs overflow-hidden break-all leading-tight">
45
+ {{ field.type }}
46
+ </div>
47
+ </td>
48
+ <td>
49
+ {% if field.description %}
50
+ <div class="text-xs text-base-content/80 max-w-xs leading-tight">{{ field.description }}</div>
51
+ {% else %}
52
+ <span class="text-xs text-base-content/40 italic">No description</span>
53
+ {% endif %}
54
+ </td>
55
+ <td class="text-center">
56
+ {% if field.required %}
57
+ <span class="badge badge-error badge-xs min-w-fit">Required</span>
58
+ {% else %}
59
+ <span class="badge badge-ghost badge-xs min-w-fit">Optional</span>
60
+ {% endif %}
61
+ </td>
62
+ <td>
63
+ {% if field.extra %}
64
+ <div class="flex flex-wrap gap-1">
65
+ {% for key, value in field.extra.items() %}
66
+ {% if key == "enum" %}
67
+ <div class="tooltip" data-tip="Values: {{ value | join(", ") }}">
68
+ <span class="badge badge-info badge-xs min-w-fit">enum({{ value | length }})</span>
69
+ </div>
70
+ {% elif key == "enum_count" %}
71
+ <span class="badge badge-info badge-xs min-w-fit">enum({{ value }})</span>
72
+ {% elif key == "default" %}
73
+ <div class="tooltip" data-tip="Default: {{ value }}">
74
+ <span class="badge badge-success badge-xs min-w-fit">default</span>
75
+ </div>
76
+ {% elif key == "format" %}
77
+ <span class="badge badge-warning badge-xs min-w-fit">{{ value }}</span>
78
+ {% elif key == "pattern" %}
79
+ <div class="tooltip" data-tip="{{ value }}">
80
+ <span class="badge badge-accent badge-xs min-w-fit">regex</span>
81
+ </div>
82
+ {% elif key in ["min", "max", "min_length", "max_length"] %}
83
+ <span class="badge badge-neutral badge-xs min-w-fit">{{ key.replace('_', ' ') }}: {{ value }}</span>
84
+ {% endif %}
85
+ {% endfor %}
86
+ </div>
87
+ {% else %}
88
+ <span class="text-xs text-base-content/40">-</span>
89
+ {% endif %}
90
+ </td>
91
+ </tr>
92
+ {% endfor %}
93
+ </tbody>
94
+ </table>
95
+ </div>
96
+ </div>
97
+ </div>
98
+ {% endfor %}
99
+ </div>
100
+ <!-- Debug Navigation Footer -->
101
+ {% include "debug/components/debug_nav.html.jinja" %}
102
+ </div>
103
+ {% endblock body %}
@@ -0,0 +1,55 @@
1
+ <!-- Debug Navigation Component -->
2
+ <nav class="mt-8 pt-6 border-t border-base-200">
3
+ <div class="flex flex-wrap gap-4">
4
+ <a href="{{ url_for("debug_index") }}"
5
+ class="btn btn-outline btn-primary gap-2">
6
+ <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
7
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2H5a2 2 0 00-2-2z">
8
+ </path>
9
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 5a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H10a2 2 0 01-2-2V5z">
10
+ </path>
11
+ </svg>
12
+ Debug Home
13
+ </a>
14
+ <a href="{{ url_for("debug_info") }}"
15
+ class="btn btn-outline btn-primary gap-2">
16
+ <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
17
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z">
18
+ </path>
19
+ </svg>
20
+ System Info
21
+ </a>
22
+ <a href="{{ url_for("debug_collections") }}"
23
+ class="btn btn-outline btn-primary gap-2">
24
+ <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
25
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 7v10c0 2.21 3.582 4 8 4s8-1.79 8-4V7M4 7c0 2.21 3.582 4 8 4s8-1.79 8-4M4 7c0-2.21 3.582-4 8-4s8 1.79 8 4">
26
+ </path>
27
+ </svg>
28
+ Collections
29
+ </a>
30
+ <a href="{{ url_for("debug_users") }}"
31
+ class="btn btn-outline btn-warning gap-2">
32
+ <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
33
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z">
34
+ </path>
35
+ </svg>
36
+ User Impersonation
37
+ </a>
38
+ <a href="{{ url_for("debug_version") }}"
39
+ class="btn btn-outline btn-primary gap-2">
40
+ <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
41
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 7h.01M7 3h5c.512 0 1.024.195 1.414.586l7 7a2 2 0 010 2.828l-7 7a2 2 0 01-2.828 0l-7-7A1.994 1.994 0 013 12V7a4 4 0 014-4z">
42
+ </path>
43
+ </svg>
44
+ Version
45
+ </a>
46
+ <a href="{{ url_for("health_ping") }}"
47
+ class="btn btn-outline btn-success gap-2">
48
+ <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
49
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z">
50
+ </path>
51
+ </svg>
52
+ Health Check
53
+ </a>
54
+ </div>
55
+ </nav>
@@ -0,0 +1,83 @@
1
+ {% extends "base/skeleton.html.jinja" %}
2
+ {% block title %}
3
+ Debug Dashboard
4
+ {% endblock title %}
5
+ {% block body %}
6
+ <div class="container mx-auto px-4 py-8 max-w-4xl">
7
+ <!-- Header -->
8
+ <header class="mb-8">
9
+ <h1 class="text-4xl font-bold text-base-content mb-2">Debug Dashboard</h1>
10
+ <p class="text-base-content/70">Development and debugging tools for {{ project_name }}</p>
11
+ </header>
12
+ <!-- Debug Tools Grid -->
13
+ <div class="grid md:grid-cols-2 gap-6">
14
+ <!-- System Information -->
15
+ <div class="card bg-base-100 shadow-xl border border-base-200 hover:shadow-2xl transition-shadow">
16
+ <div class="card-body">
17
+ <h2 class="card-title text-primary flex items-center gap-2">
18
+ <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
19
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z">
20
+ </path>
21
+ </svg>
22
+ System Information
23
+ </h2>
24
+ <p class="text-base-content/70 mb-4">View application configuration, cookies, and runtime information</p>
25
+ <div class="card-actions justify-end">
26
+ <a href="{{ url_for("debug_info") }}" class="btn btn-primary btn-sm">View Details</a>
27
+ </div>
28
+ </div>
29
+ </div>
30
+ <!-- Database Collections -->
31
+ <div class="card bg-base-100 shadow-xl border border-base-200 hover:shadow-2xl transition-shadow">
32
+ <div class="card-body">
33
+ <h2 class="card-title text-primary flex items-center gap-2">
34
+ <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
35
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 7v10c0 2.21 3.582 4 8 4s8-1.79 8-4V7M4 7c0 2.21 3.582 4 8 4s8-1.79 8-4M4 7c0-2.21 3.582-4 8-4s8 1.79 8 4">
36
+ </path>
37
+ </svg>
38
+ Database Collections
39
+ </h2>
40
+ <p class="text-base-content/70 mb-4">Explore MongoDB collections and their field schemas</p>
41
+ <div class="card-actions justify-end">
42
+ <a href="{{ url_for("debug_collections") }}"
43
+ class="btn btn-primary btn-sm">View Schemas</a>
44
+ </div>
45
+ </div>
46
+ </div>
47
+ <!-- Version Information -->
48
+ <div class="card bg-base-100 shadow-xl border border-base-200 hover:shadow-2xl transition-shadow">
49
+ <div class="card-body">
50
+ <h2 class="card-title text-primary flex items-center gap-2">
51
+ <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
52
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 7h.01M7 3h5c.512 0 1.024.195 1.414.586l7 7a2 2 0 010 2.828l-7 7a2 2 0 01-2.828 0l-7-7A1.994 1.994 0 013 12V7a4 4 0 014-4z">
53
+ </path>
54
+ </svg>
55
+ Version Information
56
+ </h2>
57
+ <p class="text-base-content/70 mb-4">Check application version and build information</p>
58
+ <div class="card-actions justify-end">
59
+ <a href="{{ url_for("debug_version") }}" class="btn btn-primary btn-sm">View Version</a>
60
+ </div>
61
+ </div>
62
+ </div>
63
+ <!-- Health Check -->
64
+ <div class="card bg-base-100 shadow-xl border border-base-200 hover:shadow-2xl transition-shadow">
65
+ <div class="card-body">
66
+ <h2 class="card-title text-success flex items-center gap-2">
67
+ <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
68
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z">
69
+ </path>
70
+ </svg>
71
+ Health Check
72
+ </h2>
73
+ <p class="text-base-content/70 mb-4">Verify application health and API endpoint status</p>
74
+ <div class="card-actions justify-end">
75
+ <a href="{{ url_for("health_ping") }}" class="btn btn-success btn-sm">Check Health</a>
76
+ </div>
77
+ </div>
78
+ </div>
79
+ </div>
80
+ <!-- Debug Navigation Footer -->
81
+ {% include "debug/components/debug_nav.html.jinja" %}
82
+ </div>
83
+ {% endblock body %}