AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified MIT Self-run

Movie Night Calendar

skill-therocksss-hermes-skills-portfolio-movie-night-calendar · by THEROCKSSS

Use when a media catalogue app needs shared scheduling — a movie-night calendar, watch-party planner, a month grid of events with a host and a title attached, an upcoming-event badge, or a "who's picking this Friday" feature. Also use when calendar dates render one day off, when past events need distinguishing from upcoming, or when deciding who may delete an event.

No reviews yet
0 installs
16 views
0.0% view→install

Install

$ agentstack add skill-therocksss-hermes-skills-portfolio-movie-night-calendar

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No 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.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-therocksss-hermes-skills-portfolio-movie-night-calendar)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
1mo ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

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 →
Are you the author of Movie Night Calendar? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

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

  1. Add the table and its grants (see Schema). One migration, following the same exposed-view discipline as watchlist-sync.
  2. Load the month's events once, ordered by date, and render the grid from that array — not one request per cell.
  3. Build the month grid with the leading blanks maths (see Rendering the Month).
  4. 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.
  5. Add the day panel: click a cell, see that day's events, create from there with the date pre-filled.
  6. 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).
  7. Decide and enforce who can delete (see Permissions), and say the rule in the UI.
  8. 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:

  • title and poster_url are 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_date is a DATE, not a TIMESTAMPTZ. 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_time is free text. Storing "8pm-ish" honestly beats storing 20:00:00+00 and then rendering it in a timezone nobody agreed on. If you need a real instant, add a separate nullable starts_at TIMESTAMPTZ and 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.

Versions

  • v0.1.0 Imported from the upstream source.