iArt.ai
AI motion graphics software — the After Effects alternative anyone can use. Create animations and explainer videos from a text prompt in minutes.
翻訳待ち
No updates detected yet. GitHub releases will appear here.
An AI chat-session archive set as a newspaper: file a ChatGPT share link and it becomes a story — the summary report as the article, the transcript as the interview, the conversation's own citations restored. Public reads, private writes: Python Workers + D1 behind Cloudflare Access, the reader a Next.js static export.
翻訳待ち
Loading the full README.
Read the full README ↗The AI Digest — archive your AI assistant chat sessions (transcript + markdown
report) into Cloudflare D1 by pasting a ChatGPT share link, and read them back as
a newspaper. See plan.md for the full design.
Sessions laid out as a newspaper front page: two leads above the fold, a third heading the flow beneath, then three columns that each run to their own ragged depth. Public, and the same edition for everyone. The only control in the masthead is Sign in — no import box, and no email address, on a page anyone can read.
/chat-archives/deskWhere a share link becomes a story. Reached by signing in, and gated. The filing form, and under it your own filings with their controls (see Who can see what). It is also the one place your address is shown back to you, on a page that requires signing in.
The generated markdown report, rendered as an article. Inline [n] citation
markers are linked through to their entry in the bibliography at the foot of the
page.
The same session as a verbatim transcript, rendered the way ChatGPT renders it: user turns in a bubble, assistant turns as plain prose, redacted tool calls collapsed into a single counted note. The Report/Chat toggle at the top swaps between the two views.
Inline [n] markers are the conversation's own citations — ChatGPT's source
pills, restored rather than deleted (see docs/sources.md). Each assistant turn
carries the vendor's mark, and the ··· under it opens that reply's sources.
Email → one-time code → verifying → confirmed. In production the identity
provider is Cloudflare Access with a one-time PIN; the OTP screen belongs to
Cloudflare, not this page (see docs/access-limits.md for why Access cannot sit
behind it). Locally a dev server stands in for it.
| One-time code | |
|---|---|
| Verifying | Confirmed |
|---|---|
| Route | Anyone | Signed in |
|---|---|---|
/chat-archives — the edition | every public story | same |
/chat-archives/<share-id> — one story | readable if public; a private one is not found | the same; if you filed it: readable even when private, a Public/Private label with Make private/Make public, Delete this story, and an Images progress link |
/chat-archives/login — sign in | screen | redirects to the desk |
/chat-archives/desk — file copy | redirected to sign in | the filing form, with a Public/Private choice and Delete it on what you just filed; under it, your filings, each row with its Public/Private label and switch and Delete |
/chat-archives/desk/media — your images | redirected to sign in | copy progress per story, Retry failed, Copy now |
One rule, stated once: public reads, private writes. The gated actions
are POST /api/desk/ingest, GET /api/desk/filings, and three on
/api/desk/sessions/<share-id>: GET answers {"yours": bool, "visibility": …}
so a story knows whether to offer its controls, PATCH {"visibility": "public" | "private"}
switches your copy, and DELETE deletes your copy
with its transcript, report, sources and images — its rows in D1 and its files in R2 (each is 404 if you have no copy).
/api/desk/media[/<share-id>[/retry|/copy]] is the media page's API, scoped the
same way. Images are public at GET /api/media/<key> exactly when a public story
shows them.
Public or private. Each filing is one or the other; its filer chooses on the
filing form (public unless they say otherwise) and can switch it later. Filing a
link again without choosing keeps the story as it was, and the form forgets the
choice after each filing, so a private story is never published by a re-file. A private
story is invisible to everyone else, signed in or not: it is left out of
GET /api/sessions, GET /api/sessions/<share-id> answers 404, and so does
GET /api/media/<key> for its images — the Worker asks the database whether a
public story shows the image before it reads the bucket, so knowing or guessing a
key gets nothing. Its filer reads it on two routes under the same Access-covered
prefix: GET /api/desk/stories/<share-id> (your own copy) and
GET /api/desk/image/<key> (an image one of your own stories shows). The story
page tries the public route first and falls back to those. Every story filed
before visibility existed is public (migration 0004).
Ownership is still recorded (conversations.owner_email). It is provenance, not
an access boundary for reading a public story. It is the boundary for three things: you can
only delete what you filed, only switch your own copy between public and private, and only
you can read your private copy. Another filer's copy of the same link stays put, with the
visibility its own filer chose — while one copy is public, the link's permalink and images
stay public. It never leaves the server on a read: it keys the
upsert, scopes the desk's "your recent filings" query, and is returned by exactly
one endpoint — /api/desk/whoami, to the person it belongs to. No listing carries an
address, because /api/sessions answers anonymous visitors and a per-row address
there would publish every filer's email in the JSON. The upsert key remains
(owner_email, external_id), so two people can file the same share link and both
are in the edition.
This is the beginning of the README. Read the rest at the original. Read the full README ↗