Add Sentry error monitoring and fix accessibility issues

Sentry integration:
- Add sentry-sdk[flask] to registry dependencies
- Initialize Sentry with Flask integration (if SENTRY_DSN is set)
- Configure trace/profile sampling rates via environment variables
- Privacy-first: send_default_pii=False

Accessibility fixes (WCAG 2.0 AA compliance):
- Add aria-label to search input
- Add label and aria-label to essential cookies checkbox
- Fix color contrast issues:
  - $ prompt: text-gray-400 → text-gray-600
  - Version numbers: text-gray-400 → text-gray-600
  - Tutorial button: text-cyan-600 → text-cyan-700
  - Step labels: text-indigo-500 → text-indigo-700
  - Footer text: text-gray-500 → text-gray-300 (on dark bg)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
rob 2025-12-31 23:20:11 -04:00
parent 357997dc7d
commit 26ae319815
8 changed files with 28 additions and 7 deletions

View File

@ -46,11 +46,13 @@ dev = [
registry = [ registry = [
"Flask>=2.3", "Flask>=2.3",
"argon2-cffi>=21.0", "argon2-cffi>=21.0",
"sentry-sdk[flask]>=1.0",
] ]
all = [ all = [
"urwid>=2.1.0", "urwid>=2.1.0",
"Flask>=2.3", "Flask>=2.3",
"argon2-cffi>=21.0", "argon2-cffi>=21.0",
"sentry-sdk[flask]>=1.0",
] ]
[project.scripts] [project.scripts]

View File

@ -7,6 +7,24 @@ import secrets
from flask import Flask, render_template, session from flask import Flask, render_template, session
# Initialize Sentry before importing Flask app (if DSN is configured)
_sentry_dsn = os.environ.get("SENTRY_DSN")
if _sentry_dsn:
try:
import sentry_sdk
from sentry_sdk.integrations.flask import FlaskIntegration
sentry_sdk.init(
dsn=_sentry_dsn,
integrations=[FlaskIntegration()],
traces_sample_rate=float(os.environ.get("SENTRY_TRACES_RATE", "0.1")),
profiles_sample_rate=float(os.environ.get("SENTRY_PROFILES_RATE", "0.1")),
environment=os.environ.get("SMARTTOOLS_ENV", "development"),
send_default_pii=False, # Privacy: don't send user IPs, emails, etc.
)
except ImportError:
pass # sentry-sdk not installed
from smarttools.registry import app as registry_app from smarttools.registry import app as registry_app
from . import web_bp from . import web_bp

View File

@ -61,10 +61,10 @@
<!-- Essential cookies (always on) --> <!-- Essential cookies (always on) -->
<div class="flex items-start justify-between p-4 bg-gray-50 rounded-lg"> <div class="flex items-start justify-between p-4 bg-gray-50 rounded-lg">
<div> <div>
<h4 class="text-sm font-medium text-gray-900">Essential cookies</h4> <label for="consent-essential" class="text-sm font-medium text-gray-900">Essential cookies</label>
<p class="mt-1 text-sm text-gray-500">Required for the website to function properly.</p> <p class="mt-1 text-sm text-gray-500">Required for the website to function properly.</p>
</div> </div>
<input type="checkbox" checked disabled class="mt-1 h-4 w-4 text-indigo-600 border-gray-300 rounded"> <input type="checkbox" id="consent-essential" checked disabled aria-label="Essential cookies (always enabled)" class="mt-1 h-4 w-4 text-indigo-600 border-gray-300 rounded">
</div> </div>
<!-- Analytics cookies --> <!-- Analytics cookies -->

View File

@ -51,7 +51,7 @@
<p class="text-gray-400 text-sm"> <p class="text-gray-400 text-sm">
&copy; {{ now().year }} SmartTools. Open source under MIT License. &copy; {{ now().year }} SmartTools. Open source under MIT License.
</p> </p>
<p class="text-gray-500 text-xs mt-2 sm:mt-0"> <p class="text-gray-300 text-xs mt-2 sm:mt-0">
Made with care for the developer community. Made with care for the developer community.
</p> </p>
</div> </div>

View File

@ -166,6 +166,7 @@
<input type="text" <input type="text"
id="search-input" id="search-input"
placeholder="Search tools, docs, tutorials..." placeholder="Search tools, docs, tutorials..."
aria-label="Search tools, documentation, and tutorials"
class="w-full pl-10 pr-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500" class="w-full pl-10 pr-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500"
autocomplete="off"> autocomplete="off">
</div> </div>

View File

@ -47,7 +47,7 @@
</svg> </svg>
{{ tool.downloads|default(0) }} downloads {{ tool.downloads|default(0) }} downloads
</span> </span>
<span class="text-xs text-gray-400">v{{ tool.version }}</span> <span class="text-xs text-gray-600">v{{ tool.version }}</span>
</div> </div>
<!-- Install command --> <!-- Install command -->

View File

@ -30,7 +30,7 @@
<div class="p-4"> <div class="p-4">
{% if step_number %} {% if step_number %}
<p class="text-xs font-semibold uppercase tracking-wide text-indigo-500 mb-2">Step {{ step_number }}</p> <p class="text-xs font-semibold uppercase tracking-wide text-indigo-700 mb-2">Step {{ step_number }}</p>
{% endif %} {% endif %}
<h3 class="text-lg font-semibold text-gray-900"> <h3 class="text-lg font-semibold text-gray-900">
<a href="{{ href or '#' }}" <a href="{{ href or '#' }}"

View File

@ -22,7 +22,7 @@
<!-- Install Command --> <!-- Install Command -->
<div class="mt-10 max-w-xl mx-auto"> <div class="mt-10 max-w-xl mx-auto">
<div class="flex items-center bg-gray-100 rounded-lg p-4 group"> <div class="flex items-center bg-gray-100 rounded-lg p-4 group">
<span class="text-gray-400 mr-2 select-none">$</span> <span class="text-gray-600 mr-2 select-none" aria-hidden="true">$</span>
<code id="install-command" class="flex-1 text-gray-800 font-mono text-sm md:text-base text-left">pip install smarttools && smarttools init</code> <code id="install-command" class="flex-1 text-gray-800 font-mono text-sm md:text-base text-left">pip install smarttools && smarttools init</code>
<button type="button" <button type="button"
onclick="copyInstallCommand()" onclick="copyInstallCommand()"
@ -45,7 +45,7 @@
Get Started Get Started
</a> </a>
<a href="{{ url_for('web.tutorials') }}" <a href="{{ url_for('web.tutorials') }}"
class="w-full sm:w-auto inline-flex justify-center items-center px-8 py-4 text-lg font-medium text-cyan-600 border-2 border-cyan-500 rounded-md hover:bg-cyan-50 transition-colors"> class="w-full sm:w-auto inline-flex justify-center items-center px-8 py-4 text-lg font-medium text-cyan-700 border-2 border-cyan-600 rounded-md hover:bg-cyan-50 transition-colors">
View Tutorials View Tutorials
</a> </a>
</div> </div>