Intercepts form submit via fetch and stores failed submissions in
IndexedDB when offline. Replays queued entries on the online event and
on each page load. Shows an offline banner on the form page and a
sync-pending message on the thank-you page.
Service worker bumped to guestbook-v2 to pre-cache offline-queue.js
so the script is available when the kiosk has no network.
Displays total entries, this week, this month, and newsletter opt-in
count and percentage at the top of the admin view. Week/month
boundaries are computed in America/Denver time and converted to UTC
for SQLite comparison, handling DST correctly.
Redirects to /thank-you?name=<first_name> on successful submission
instead of back to the blank form. Shows a 4-second countdown with
meta-refresh fallback before returning to the form. Includes the
scrolling guest marquee so the page feels consistent with the kiosk.
Adds FIELD_MAX constants and server-side length checks in the index
route. Adds matching maxlength attributes on all form inputs so the
browser enforces limits before submission.
Installs Flask-WTF and enables CSRFProtect globally. Adds csrf_token
hidden fields to all four POST forms (login, delete entry, add user,
delete user, and the public guestbook form). Exempts the API endpoint
which uses header-based key auth instead.
Convert UTC timestamps from SQLite to Mountain Time (America/Denver)
using a Jinja2 template filter backed by zoneinfo; add tzdata dependency
for IANA timezone data in the slim Docker image.
Replaces browser-cached Basic Auth credentials with proper server-side
session management. Logout now fully invalidates the session. Adds an
HTML login form at /admin/login, SECRET_KEY env var support, and updates
README with key generation instructions and role table.
- entrypoint.sh: use GUNICORN_WORKERS to match example.env (#17)
- guestbook_export.py: read DATABASE_PATH from env instead of
hardcoded relative path (#18)
- Scrolling marquee: duplicate guest list for seamless loop,
animate translateX(0) to translateX(-50%), increase font to
1.25rem, fix JS speed calc to use half content width (#20)
- Fixed scrolling marquee to use a fixed px/s speed via JS instead of
a fixed duration, preventing it from speeding up as entries are added
- Added inline TODO comments throughout codebase to track known issues
(rate limiting, CSRF, unbounded queries, deprecated Flask decorator,
PII logging, schema versioning, Docker non-root user, etc.)
- Added todo-to-issue GitHub Action to auto-create Issues from TODOs on push to main
- Added .claude/ to .gitignore
- Fixed port variable interpolation to use ${PORT:-8000} for a default value.
- Updated volume configuration to use a named volume (guestbook_data) mounted at /data.
- Improved YAML formatting for clarity.
- Hide comment field by default.
- Add JavaScript to reveal comment field when first name, last name, and location have at least 3 characters.
- Update form instructions to inform users about the comment field.
- Display brief instructions above the guestbook form.
- Update validation: require first name, last name, and location; make email optional.
- Remove the 'required' attribute from the email input field.
- Provide context in the UI so users understand why email is optional.
- Update index.html to include a fixed, horizontally scrolling marquee at the bottom.
- Use CSS keyframes to animate guest entries, showing first name and location.
- Enhance user interface by providing a dynamic display of entries.
- Validate that first_name, last_name, email, and location are provided
- Add regex-based email format validation in app.py
- Display error messages on the guestbook form if validation fails
These changes help ensure that only properly formatted data is stored.