Nikhil Sachdeva Photography
All documentation

Product

Product Specification

Status: Living document · Owner: Studio · Last reviewed: 2026-07-07

NIKSAC is a single-operator photography platform: a public, viewing-only gallery backed by an authenticated "Studio" console that ingests photos from OneDrive and Google Drive, curates and captions them with AI agents, and publishes selected work to Instagram.


1. Vision

Give one photographer a calm, high-craft surface to show their work and a powerful back office to run it — ingestion, curation, scheduling, and publishing — without touching a spreadsheet, a CMS, or a third-party scheduler.

2. Personas

PersonaNeedsSurface
VisitorBrowse and admire photography; enquire about licensingPublic gallery, collections, about
Operator (the photographer)Ingest, curate, caption, schedule, publishStudio console (/studio)
Automated jobsRenew tokens, sync OneDrive, keep the site freshCron + webhooks (no UI)

3. Core capabilities

3.1 Public gallery (viewing only)

  • Server-rendered React 19 gallery and collection pages.
  • Read-only by design — no downloads; licensing enquiries go through email.
  • Revalidates when the Studio publishes new curated work.

3.2 Studio console (authenticated)

  • Operator dashboard for the full lifecycle of a photo.
  • Two sign-in paths (see Identity below); all Studio routes are guarded.

3.3 Photo ingestion (OneDrive & Google Drive)

  • A watched OneDrive or Google Drive folder is the source of truth for raw photos.
  • Provider change notifications (webhooks) trigger a delta sync; a daily cron sweep catches anything a missed notification left behind.
  • On each new file we download the bytes once, parse EXIF, and derive downscaled renditions into the private Blob store. The full-resolution original is never permanently stored on our side — it stays in the photographer's own drive (see ADR-009). The briefly-staged original is deleted once AI + renditions complete.
  • The public gallery serves only our renditions via an edge-cached proxy, so it never depends on a short-lived provider URL.

3.4 AI curation pipeline

The pipeline runs in two stages. Every call goes through the Vercel AI Gateway (google/gemini-2.5-flash) using the AI SDK's generateObject with a Zod schema — structured output is enforced; there is no free-text fallback.

Stage 1 — Vision model (Curator)

The Curator is the only agent that sees the photograph. It receives the image inlined as base64 bytes (never via URL — the Gateway cannot reach our private renditions) plus EXIF and any operator emphasis themes. It returns a ContentIndex — subjects, scene, mood, colors, aesthetic score, postability score, collection, and symbolism (2-3 sentences about what image elements mean in relation to each other). The symbolism field is the interpretive spine for every downstream agent.

Stage 2 — Text LLM agents (work from ContentIndex, not the raw image)

  • Editor — crop ratio and conservative tonal adjustments informed by the Curator's scene/mood/symbolism read.
  • Copywriter — three voice variants (Photographer / Quote / Reader) for tagline, site caption, and Instagram caption. Also receives the image inline to ground copy in what is literally visible. The operator can switch voice in Approvals, and re-run with new emphasis themes.
  • Scheduler — proposes an Instagram slot based on postability score, season affinity, operator settings, and special days.
  • Hashtag Strategist — 22 hashtags (broad / mid / location / niche) amplifying the Copywriter's vocabulary and GPS coordinates.

All five agents are cached by a SHA-256 of (agent + prompt + input + imageUrl) so a photo is only processed once. Results are never mocked or silently degraded — a model failure propagates as an error.

Site-only path (showcase folder): only Curator + Copywriter run. The three voices are stored on the photos row (siteVoices) since there is no IgPost. Editor, Scheduler, and Hashtag Strategist are skipped.

See the System Architecture document for the full pipeline diagram and data flow.

3.5 Publishing (Instagram Graph)

  • Approved posts create an Instagram media container, then publish.
  • Non-idempotent calls (publish) never retry; a permalink is stored on success.

4. Identity & access (summary)

  • Studio session: signed, HTTP-only HMAC cookie, 12-hour lifetime, constant-time verification.
  • Microsoft Entra ID: OAuth 2.0 authorization-code flow with a signed CSRF state nonce. MFA is enforced by Entra ID — the app never handles a second factor itself.
  • Email allowlist: the authenticated identity must match the authorized operator allowlist.
  • See the System Architecture diagram for the full request path.

5. Non-goals

  • Not a multi-tenant SaaS — one operator, one studio.
  • Not a general DAM or file host — the photographer's OneDrive / Google Drive remains the source of truth and the permanent home for full-res originals.
  • No public user accounts, comments, or e-commerce checkout (licensing is manual).

6. Success signals

  • Zero manual file wrangling between OneDrive and the live gallery.
  • Every published post traceable end-to-end (ingest → curate → publish → permalink).
  • The public gallery stays fast and always reflects the latest curated set.