Install
$ agentstack add skill-therocksss-hermes-skills-portfolio-movie-night-calendar ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
movie-night-calendar
Overview
A shared calendar bolted onto a catalogue app: a month grid, one row per scheduled screening, each carrying a host profile, a real title picked from the metadata API, a date and optional time, a description, and an optional chat/voice link. Plus the small things that make it feel finished — a day panel, a past/upcoming distinction, and an "there's something coming up" badge in the nav.
It is a small feature with two disproportionate traps: JavaScript date parsing that silently shifts the day, and permissions on a table anyone can reach.
When to Use
- A catalogue app needs "movie night on Friday" scheduling shared between profiles.
- A watch-party planner, screening schedule, or club calendar over an existing title catalogue.
- Debugging a calendar that renders events one day early or late.
- Deciding who may create, edit, or delete an event.
Do not use it for personal reminders with no shared audience (a notes field on the watchlist row is enough), or for release-date calendars sourced from the metadata API — those are a /discover query with date filters, not stored events.
Workflow
- Add the table and its grants (see Schema). One migration, following the same exposed-view discipline as
watchlist-sync. - Load the month's events once, ordered by date, and render the grid from that array — not one request per cell.
- Build the month grid with the leading blanks maths (see Rendering the Month).
- Parse every date string with an explicit local-midnight suffix (see The Off-By-One-Day Trap). Do this before anything else, or you will chase a rendering bug that is a parsing bug.
- Add the day panel: click a cell, see that day's events, create from there with the date pre-filled.
- Attach a real title by searching the metadata API in the create form and storing the id and poster alongside the free-text title (see Attaching a Title).
- Decide and enforce who can delete (see Permissions), and say the rule in the UI.
- Add the upcoming badge as a bounded range query (see Upcoming Badge).
Schema
CREATE TABLE movie_nights (
id SERIAL PRIMARY KEY,
host_profile_id INTEGER NOT NULL REFERENCES profiles(id) ON DELETE CASCADE,
title TEXT NOT NULL, -- denormalised on purpose, see below
external_id INTEGER, -- TMDB id, nullable: not every night is a catalogued title
media_type TEXT CHECK (media_type IN ('movie','tv')),
poster_url TEXT DEFAULT '',
event_date DATE NOT NULL,
event_time TEXT DEFAULT '', -- free text; see the timezone note
description TEXT DEFAULT '',
chat_url TEXT DEFAULT '', -- Discord/Matrix/Jitsi invite
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX movie_nights_date_idx ON movie_nights (event_date);
ALTER TABLE movie_nights ENABLE ROW LEVEL SECURITY;
NOTIFY pgrst, 'reload schema';
Three deliberate choices:
titleandposter_urlare denormalised. An event must still read correctly when the catalogue row is gone, and a scheduled night is a historical record — it should not silently retitle itself if the metadata changes.event_dateis aDATE, not aTIMESTAMPTZ. A movie night is a calendar day, not an instant. Storing an instant forces a timezone decision on a value that doesn't have one and reintroduces the off-by-one below at the database layer.event_timeis free text. Storing"8pm-ish"honestly beats storing20:00:00+00and then rendering it in a timezone nobody agreed on. If you need a real instant, add a separate nullablestarts_at TIMESTAMPTZand say in the UI which timezone it is displayed in.
The Off-By-One-Day Trap
This is the bug this skill exists for.
new Date('2026-08-02') // parsed as UTC midnight → renders as Aug 1 west of UTC
new Date('2026-08-02T00:00:00') // parsed as LOCAL midnight → correct
A bare YYYY-MM-DD string is parsed by the ECMAScript spec as UTC, while a date-time string without an offset is parsed as local. So every event silently shifts a day for anyone in a negative-offset timezone — and looks perfect on the developer's machine if they happen to be east of UTC.
Two rules, applied everywhere:
// Read: always append the time component.
const dateObj = new Date(dateStr + 'T00:00:00');
// Write: never use toISOString().slice(0,10) — that converts to UTC first
// and shifts the day back for anyone in a negative offset.
function fmtDate(d) {
const y = d.getFullYear();
const m = String(d.getMonth() + 1).padStart(2, '0');
const day = String(d.getDate()).padStart(2, '0');
return `${y}-${m}-${day}`;
}
Compare against a normalised today, or every event dated today counts as past from 00:00:01 onward:
const today = new Date();
today.setHours(0, 0, 0, 0);
const isPast = new Date(dateStr + 'T00:00:00') ` renders as text
- [ ] The delete button appears only for the host and the editor, and the rule is stated in the UI
- [ ] Creating and deleting an event both update the upcoming badge without a reload
- [ ] An empty month and a failed load render differently
- [ ] A past date offers delete but not create
## Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- **Author:** [THEROCKSSS](https://github.com/THEROCKSSS)
- **Source:** [THEROCKSSS/hermes-skills-portfolio](https://github.com/THEROCKSSS/hermes-skills-portfolio)
- **License:** MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.