iArt.ai
AI 모션 그래픽 소프트웨어, 누구나 사용할 수 있는 After Effects 대안, 텍스트 프롬프트로 몇 분 안에 애니메이션·설명 영상 제작
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
A lightweight RSS reader. Paste a website, a Substack, or an RSS link — or just
type a topic — preview what you'd get, and keep it in a named feed.
No accounts, no database, no AI. Your feeds live in your browser's
localStorage; the server only fetches and parses XML.
Adding a source (lib/discover.ts) resolves whatever you paste:README 전문 보기 ↗A lightweight RSS reader. Paste a website, a Substack, or an RSS link — or just type a topic — preview what you'd get, and keep it in a named feed.
Live: https://super-reader-nathan-kuczmarskis-projects.vercel.app
No accounts, no database, no AI. Your feeds live in your browser's
localStorage; the server only fetches and parses XML.
npm install
npm run dev # http://localhost:3000
npm run build && npm start # production
npm test # parser + discovery tests
Adding a source (lib/discover.ts) resolves whatever you paste:
<link rel="alternate" type="application/rss+xml">
in the page's <head>, then falls back to conventional paths (/feed,
/rss.xml, /index.xml, …) that cover Substack, WordPress, Ghost, Hugo and
Jekyll./feeds page. Those are read too, and the candidates are ranked so press
releases and newsrooms win over comment, podcast and regional feeds. The
index pages are probed directly, since a site can block its HTML homepage
while happily serving both /feeds and the feeds themselves.@OpenAI, x.com/OpenAI, twitter.com/OpenAI) → the
account's posts, via the official X API. See below.lib/scrape.ts). This is how sites like anthropic.com/news,
which never published RSS, become followable.Pasting a section — blog.google/products-and-platforms/products/gemini —
should follow that section, not the entire blog. Section pages routinely
declare the site-wide feed in their <head>, so trusting that link silently
widens the source to everything the publisher posts.
Anything deeper than the domain root is therefore treated as a section, and resolved in this order:
<section>/rss, <section>/feed, …), or a
declared feed whose URL sits under the section path.The preview shows which applied and offers a This section / Whole site switch, so the wider scope is one click away when that is what you want. A bare domain is always site-wide and shows no switch.
A listing page links to its articles many times in a consistent shape
(/news/<slug>), while nav and footer links are one-offs scattered across
unrelated paths. So the scraper strips <nav>/<header>/<footer>, groups
every remaining link by the directory it lives in, and keeps the largest group
— strongly preferring links directly beneath the page being viewed. Titles come
from the card's heading, dates from <time datetime> (or the URL), images from
the card's <img>. If nothing looks like a repeated list, it says so rather
than inventing a feed.
These sources are labelled "built from the page — no RSS" in the preview, and refresh re-reads the page, so they stay up to date like any other source. They are more fragile than real RSS: a site redesign can change the markup.
You always see a preview — the source's real recent articles — before deciding to keep it, and you pick which feed it joins.
Reading merges every source in the selected feed, always newest first (undated items sort last). Click a headline to read the whole article inside the app: the server fetches it, extracts the body with Mozilla's Readability, and sanitizes the HTML — scripts, styles, iframes, event handlers and non-http URLs are stripped before it reaches the page. Cmd/Ctrl-click still opens the original. Click a feed in the sidebar to see everything in it, or a single source to narrow to it. Each source shows its favicon, with a letter avatar as fallback.
Each feed collapses to hide its sources — click the chevron beside the name. Which feeds are collapsed is remembered per device. A collapsed feed still shows its unread count and is still selectable, and collapsing on a phone does not close the drawer.
Each source in the sidebar has a grip on its left. Drag it onto another feed to move it there — with a mouse, or with a finger on a phone. The feed under the pointer is outlined as you go, Escape abandons the drag, and dropping into a collapsed feed opens it so you can see what landed.
It is a move rather than a copy, and dropping a source onto a feed that already follows the same URL merges the two rather than leaving it listed twice.
Settings (bottom of the sidebar) chooses how articles are laid out:
There is also an option to hide articles you have already opened rather than just dimming them.
The choice is stored per device, not synced: a phone and a desktop want different densities, while the feeds themselves are what needs to match.
| Path | What it does |
|---|---|
lib/feed.ts | Fetch + parse RSS 2.0, Atom, and RDF into one article shape |
lib/discover.ts | Turn a pasted topic/URL/site into a feed |
lib/scrape.ts | Build a feed from a page that has no RSS |
lib/enrich.ts | Fill in missing summaries/dates from article metadata |
lib/article.ts | Extract + sanitize an article for the in-app reader |
lib/sort.ts | Newest-first ordering shared by every path |
lib/x.ts | Following an X account through the official API |
lib/offline.ts | Offline store, download schedule, list snapshot |
public/sw.js | Service worker: opens the app with no connection |
lib/sync-code.ts | Sync code generation, normalising and hashing |
lib/sync.ts | Reading and writing a synced feed list |
lib/db.ts | Postgres connection and one-table schema |
lib/store.ts | localStorage persistence for feeds and read state |
app/api/discover | Preview endpoint used by the add dialog |
app/api/feed | Batch feed refresh |
app/api/article | Readable, sanitized article for the reader |
app/api/sync | Create / fetch / save a synced feed list |
app/manifest.ts | Web app manifest for Home Screen installs |
scripts/gen-icons.mjs | Regenerates the PNG app icons from the mark |
components/Reader.tsx | Sidebar, article list, feed management |
components/SettingsDialog.tsx | View mode and reading preferences |
Feeds are fetched server-side, which sidesteps browser CORS restrictions — this is why the app needs a Node server rather than being a static page.
Every dialog closes three ways: the X in its header, the button in its footer, and a tap outside it. Opening one from the sidebar drawer puts the drawer away with it, so closing it returns you to the articles rather than to the drawer.
The layout adapts below 860px: the sidebar becomes an off-canvas drawer behind a menu button (it used to be hidden outright, which left no way to switch feeds or reach sync), touch targets grow, dialogs slide up from the bottom, and safe-area insets keep content clear of the notch and home indicator.
The app ships a web manifest, so it installs as a standalone app with no browser chrome.
Icons are generated from the same lens mark (scripts/gen-icons.mjs): a
maskable variant keeps the mark inside the safe zone so Android can crop it to
any shape, and the Apple touch icon is full-bleed because iOS applies its own
rounded mask.
Not everything worth following publishes RSS. Court opinions, federal rulemaking, SEC filings, clinical trials, preprints — these live behind JSON APIs. Add a source → API directory lists the ones the app knows how to read, with the fields each one takes:
| API | What it follows | Key |
|---|---|---|
| CourtListener | Opinions, PACER filings, oral arguments, by court or search | listing free; text needs a key |
| Federal Register | Rules, proposed rules, notices, by agency or term | — |
| Regulations.gov | Dockets and rulemaking documents | required |
| Congress.gov | Bills and resolutions as they move | required |
| SEC EDGAR | Full-text search across filings (8-K, 10-K, S-1…) | — |
| ClinicalTrials.gov | Registered studies, newest updates first | — |
| openFDA | Drug, device and food recalls | optional |
| arXiv | Preprints by category, author or term | — |
| Crossref | Newly registered journal articles | — |
| Hacker News | Stories matching a query, with a points floor | — |
| GitHub releases | Every release of a repository, with notes | optional |
| NWS alerts | Active weather warnings by state | — |
Fill in the fields, preview, and it joins a feed like any other source.
Refresh, the reader, offline download and sync all treat it identically —
an API source is stored as a single string, api:<provider>?<fields>, so
nothing downstream needed to learn about APIs.
Where an API wants a key, the directory says which environment variable to set
and where to get one; api.data.gov issues one free key that several of the US
government APIs accept. "Optional" above means the API answers without a key
but rate-limits harder. Nothing is stored client-side: keys live only in the
deployment's environment, and the catalogue the browser receives never
contains them.
Settings → API keys takes a key per provider. They are encrypted in the browser with a passphrase you choose, and only the ciphertext syncs, so the server stores bytes it cannot read — which matters because this deployment is public: anything the server could read would be readable by whoever has the URL. A key is sent, in a header, only with the request that calls that API, used once, and never stored server-side.
On another device the vault arrives locked; entering the passphrase there unlocks it. The decrypted keys are then kept on that device, so the passphrase is asked for once per device rather than once per launch. There is no recovery: forgetting the passphrase means entering the keys again.
Keys set in the deployment's environment still work and act as the fallback — but they apply to everyone who opens the URL, which is what the vault exists to avoid.
lib/apis.ts is a list of providers, one object each. A new one needs: what
the catalogue shows (name, category, description, docs link), the fields the
user fills in, a request() that builds the URL and headers, an items() that
finds the records in the response, and an article() that maps one record to a
title, link, date and summary. Set envKey if it needs a credential, and
format: "feed" if the API answers with RSS or Atom rather than JSON — arXiv
does, and is handled by the existing feed parser rather than a mapper.
There is a test asserting every provider is well formed, and each mapper is tested against a recorded response shape rather than the live API.
Paste r/AskHistorians, or any reddit.com URL for a subreddit, and it becomes
a source. A sort comes with it — reddit.com/r/news/top/?t=week follows the
week's top posts.
Reddit's entries need unpicking to read well. A link post is pointed at what it links to, so opening it gives the article rather than Reddit's comments page (which refuses reader view), and its summary and image come from the destination. A self post keeps the text the author wrote. Either way the thread is a Discussion link beside the article, so following a subreddit for the links does not lose the comments.
x.com shows logged-out visitors a login wall with no posts, and the community front-ends that used to expose them (Nitter and friends) were hit with cease-and-desist letters in August 2026 and no longer answer. The only route left is the official API — which is how Feedly does it too, with you supplying your own credentials.
X_BEARER_TOKEN to the project's environment variables in Vercel.Then paste @handle or an x.com/handle URL like any other source. Without
the key, everything else keeps working and the dialog explains what is missing.
Replies are excluded, and posts carry their images and full text.
CourtListener serves an opinion as a single preformatted block: fixed-width text, hard-wrapped by the court, which on a phone is either a sideways-scrolling slab or a column of ragged monospace. The hard wrapping is undone so the paragraphs flow at reader size, citation links intact, and the opinion as filed is offered as a PDF at the top of the reader for reading in a proper viewer.
A page's comment section is removed before the text is extracted. Readability picks whichever container holds the most text, so a short post with a busy thread underneath returns a reader's comment as the article — under the author's name and the post's title. Containers that are, or hold, the page's own article body are left alone, so a post about comments still reads correctly.
Not every link is an article. In order: a Reddit post is read from Reddit's own feed for it, so the post and its replies appear in the reader rather than a page that refuses reader view. A link that is itself a picture is shown as one. A video becomes a card with its real title, channel and thumbnail, from oEmbed. Anything else with no extractable text falls back to what the page says about itself — title, picture, description — labelled as a preview rather than passed off as the article.
Where a publisher syndicates full text in their feed, the reader uses it (see above). Where they do not — the New York Times, for instance, which blocks the page and syndicates only summaries — the reader says so and links to the original.
This app deliberately does not route around paywalls: no archive mirrors, no crawler impersonation, no proxying, and no storing anyone's subscription credentials. Using text a publisher chose to syndicate is fair; defeating an access control they chose to apply is not, and it is also what gets a reader blocked harder.
Note in particular that this deployment is public — Vercel Authentication is off so the app works from a phone. Any subscription cookie held server-side would therefore be usable by anyone who has the URL, which is reason enough on its own not to put one there.
Open on their site. For a subscription source, the headlines, summaries and images still arrive in the feed; only the body needs the publisher. When reader view fails, the error offers "Always open on the site". After that, articles from that host go straight to the browser — where a subscription applies — instead of failing in the reader first. Settings lists those hosts and can put any of them back.
Sources often link a file rather than write the thing itself: the PDF behind a notice, the CSV of the figures. Those arrive as chips under the story, the way an image does — tap one and it expands in place with the file's own text, without leaving the list.
A file appears only where a publication actually links one — an RSS enclosure, or a link in the item's own text. Files are the exception, not a fixture of every story.
Only formats with text in them are read: PDF, plain text, Markdown, CSV (shown as a table) and JSON. An image or a video would need a viewer rather than an extractor, and pretending to read one would be worse than linking it. A scanned PDF with no text layer says so instead of opening blank — that needs OCR, which this does not do.
A file is otherwise an article: Read it all opens it in the reader, Save
puts it in Saved on its own, and a saved file downloads for offline reading like
anything else. That is one mechanism rather than two, because /api/article
reads a file URL into the same shape as an extracted page.
Save on any article puts it in the Saved list in the sidebar, and the reader has the same button. Saved articles are kept whole rather than by reference, so one stays readable long after it has scrolled out of its feed, and they are always included in the offline download — a bookmark is the article most worth having on the device. The list is per-device, like read state and view mode.
Highlight anything in an article and Add to note appears beside the selection. The passage lands in the note you pick as a block quote, bulleted among the others, exactly as the article had it.
When a quote lands, a bubble says which note it went to. Tap it to open that note, or tap Change to send the quote somewhere else — another note, or a new one named on the spot. It waits long enough to be answered and then goes.
Notes work like feeds: they are named, you make as many as you like with New note in the sidebar (or straight from a highlight, with "New note…"), and they can be renamed and deleted there. Each one is a page of its own:
The article behind a quote is bookmarked automatically, so a quote does not end up pointing at a story that has scrolled out of its feed and off the device. That automatic bookmark is released when the last quote of it is deleted, or the note holding it is — but an article you saved yourself with the Save button is never released, whatever you do to the notes.
Notes travel with your sync code, so a quote taken on the phone is on the desktop and the other way round. They merge rather than replace, like bookmarks: a quote taken on one device while the other was closed is not lost when the other syncs, and a quote or note you delete stays deleted instead of being put back by the device that still had it. What each note is called follows whichever device renamed it last, and its contents are kept either way.
Syncing carries roughly 140KB of notes — plenty for hundreds of quotes. Past that the newest are the ones that travel and the rest stay on the device that took them, because half a quote would be worse than none.
Switch the whole thing off under Settings → Notes and selecting text goes back to being just selecting text; the notes you already have stay where they are.
A team feed is a shared list that sits beside Saved in the sidebar. Set one up in Settings → Team feeds: create one with a name, or join an existing one with its connect code. Save to Team on any article — a separate button with a small crowd as its mark — puts it on that list, and everyone holding the code sees it. With more than one team feed the button opens a short picker.
Only the article travels: its title, link, summary, image and publication. Your own feeds, your saved articles, what you have read and your API keys are not shared, and nothing records who added what. Anyone on the feed can take an article back off it.
The connect code has the same shape and the same rules as a sync code: 100 bits of randomness, stored as a SHA-256 hash rather than the code itself, and a bearer secret — whoever holds it can read the list and add to it.
It is deliberately not a second sync. Sync moves one device's whole document and resolves by most recent change, so one copy wins; a team feed is written to by several people, so each save merges a single article into the list in one SQL statement. Two people saving in the same moment both land on the list. Which team feeds you have joined does sync between your own devices — the name and the code, never the shared articles, which are read from the server each time.
Team feeds need the same Postgres database as sync. Without one, Settings says they are unavailable and everything else works as before.
Articles already on the device carry a small sky-blue check in their byline line — the mark appears as each one lands, and is still there on the next visit. Hovering an article warms it too, so a story you were about to open picks up the check on its own.
Anything missing is fetched whenever the app is open — on launch, on returning to it, and when a connection comes back — so a download interrupted by switching apps finishes itself rather than waiting for the next slot. The full refresh, which also prunes what has aged out, still runs on the first visit after 7am and after 4pm ET.
The app also asks the browser to keep this cache rather than evict it. Safari clears site storage after about a week of not visiting unless the app is on your Home Screen; Settings shows which state you are in.
A thin progress bar can sit across the top of the screen while that download runs, filling as each article lands and holding at full for a moment when it finishes, so completing looks different from stopping. It is off by default — the download runs on every visit, and a bar appearing unbidden reads as the app loading something you asked for. Turn it on under Settings → Offline. Settings carries the exact count and the last download time either way.
The newest 15 stories from each source are downloaded to the device — the full extracted text, not just headlines — so they can be read with no connection. The app shell is cached by a service worker, and the article list is saved too, so opening it offline shows the list rather than an empty screen.
When it happens. On the first visit after 7am ET and after 4pm ET. It is deliberately not a timer: iOS will not wake a web app on a schedule, so promising a download at exactly 7am would be a promise the platform cannot keep. Instead each slot is recorded, and the moment the app is opened or focused after a new slot begins, the download runs. Settings shows when it last completed and offers Download now.
Slots are identified by name (2026-07-15-am) rather than by timestamp, which
avoids converting a wall-clock time in a DST-observing zone back to UTC.
Three things, in the order they help:
/api/article sets max-age for the browser and a CDN lifetime via
CDN-Cache-Control. The browser cache is a real win on a repeat open; the
edge cache is unverified — repeat requests still reported
x-vercel-cache: MISS, which may mean dynamic route handlers are not
edge-cached, or simply that the tool used to check bypasses the CDN. The
headers are correct either way and cost nothing, but do not count on the
edge until a HIT is actually observed.Feeds still live in your browser by default. Turning on sync stores them
server-side under a sync code — 100 bits of randomness, shown as
XXXXX-XXXXX-XXXXX-XXXXX. Paste that code on another device and both stay in
step. No account, no email, no password.
The code is a bearer secret: anyone holding it can read and change your feed list, so treat it like a password. Rows are keyed by SHA-256 of the code, never the code itself, so a database leak does not hand out access. Codes are accepted however you paste them — lower case, spaces instead of dashes.
Devices pull on load and whenever the window regains focus, and push changes after a short debounce. Conflicts resolve last-write-wins: two devices editing in the same moment costs one side's change, not the list.
Conflicts resolve by most recent change, not most recent write. Each device records when its data actually changed; a device that has been closed for a week cannot overwrite what happened while it was away, and instead picks up what is current. Nothing is sent until the first pull has answered, so opening a stale device is safe.
Sync needs a Postgres database. Without one the app works exactly as before and the sync dialog says it is unavailable.
POSTGRES_URL to the project's environment variables.Hosted on Vercel, linked to this GitHub repo: every push to
claude/feedly-clone-custom-feeds-laz6ll (the repo's default branch) builds
and deploys to production automatically.
The API routes run on Node — they must, since fetching feeds server-side is what avoids browser CORS limits.
s2/favicons service.anthropic.com/news,
for example, ships ~11 posts in its HTML and paginates client-side, so that
is what a scraper (Feedly included) can see. Fine for following new posts;
it is not a back catalogue.og:description. That costs one extra request
per article, capped and batched.