Source & license
Upstream license: MIT
License TL;DR
You can use it, change it, self-host it and sell it. Keep the original copyright and license notice with copies of the code. You don’t have to publish your changes. The authors don’t promise it will work.
Explain MIT in plain English →Summary of the main license. Separate packages and assets can have different terms.
Inspect repository ↗Read this project’s actual license ↗Repository owner
See the upstream repository for the original creator and contributors.
Maintain this project? Maintainer verification →Cloudflare hosting
Free tier eligible within limits
The documented Larafeed deployment can use Cloudflare Free allowances for a small workload under the request, CPU and service-specific quotas below. This is conditional eligibility, not a measured zero-cost deployment; optional features, domains and external providers can add costs.
Hosting requirements
- Workers Free allows 100,000 requests per day shared across the account and 10 ms CPU per invocation; measure CPU-heavy authentication, parsing and rendering before assuming it fits.
- Keep aggregate D1 use below 5 million rows read/day, 100,000 rows written/day and 5 GB total storage; a request can touch many rows.
- Keep KV below 100,000 reads/day, 1,000 writes, deletes and list operations/day each, and 1 GB; cache refreshes and backups consume writes.
- Keep total queue operations within 10,000/day, counting writes, reads, deletes, retries and each 64 KB chunk; Free retention is 24 hours.
- Use a small personal or team workload; domain registration and optional third-party providers are separate costs. Provision your own IDs, secrets and migrations.
Sources checked 01/10/2026
Repository snapshot: eedbc8b. Hosting eligibility reflects the deployment documentation and listed assumptions.
- feedly ↗
```mermaid flowchart LR Browser["React + Mantine<br/>React Router + TanStack Query"] Worker["Cloudflare Worker<br/>Hono + Effect"] D1[(D1)] Queues[Cloudflare Queues] Cron[Cron Triggers] Images[Cloudflare Images] AI[AI Gateway] WorkersAI[Workers
- inoreader ↗
```mermaid flowchart LR Browser["React + Mantine<br/>React Router + TanStack Query"] Worker["Cloudflare Worker<br/>Hono + Effect"] D1[(D1)] Queues[Cloudflare Queues] Cron[Cron Triggers] Images[Cloudflare Images] AI[AI Gateway] WorkersAI[Workers
- workers ↗
{ "$schema": "./node_modules/wrangler/config-schema.json", "name": "larafeed-template", "main": "./src/worker/index.ts", "compatibility_date": "2026-07-18", "compatibility_flags": ["nodejs_compat"], "workers_dev": true, "preview_urls": true, "placement": { "mode": "smart" }, "secrets": { "required": ["AUTH_OPERATOR_SECRET"] }, "vars": { "AUTH_ENVIRONMENT": "production", "AUTH_ORIGIN": "https://la
- d1 ↗
ng": "FULL_CONTENT_KV", "id": "00000000000000000000000000000010" } ], "d1_databases": [ { "binding": "DB", "database_name": "larafeed-template", "database_id": "00000000-0000-0000-0000-000000000010", "migrations_dir": "migrations" } ], "ratelimits": [ { "name": "AUTH_RATE_LIMITER", "namespace_id": "9001", "simple": { "limit": 20, "period": 60 } },
- kv ↗
un_worker_first": ["/api/*", "/export", "/up"] }, "images": { "binding": "IMAGES" }, "kv_namespaces": [ { "binding": "FULL_CONTENT_KV", "id": "00000000000000000000000000000010" } ], "d1_databases": [ { "binding": "DB", "database_name": "larafeed-template", "database_id": "00000000-0000-0000-0000-000000000010", "migrations_dir": "migrations" } ], "ratelimits": [ {
- queues ↗
FRESH_DUE_LIMIT": "5", "OPML_IMPORT_ENABLED": "true", "FAVICON_REFRESH_ENABLED": "false", "IMAGES_ENABLED": "false", "FEED_REFRESH_QUEUE_NAME": "larafeed-template-feed-refresh", "OPML_IMPORT_QUEUE_NAME": "larafeed-template-opml-import", "FAVICON_REFRESH_QUEUE_NAME": "larafeed-template-favicon-refresh" }, "assets": { "not_found_handling": "single-page-application", "run_worker_first": ["/api/*", "/export", "/up"] }, "images": { "bindin
- free-tier-eligible ↗
{ "$schema": "./node_modules/wrangler/config-schema.json", "name": "larafeed-template", "main": "./src/worker/index.ts", "compatibility_date": "2026-07-18", "compatibility_flags": ["nodejs_compat"], "workers_dev": true, "preview_urls": true, "placement": { "mode": "smart" }, "secrets": { "required": ["AUTH_OPERATOR_SECRET"] }, "vars": { "AUTH_ENVIRONMENT": "production", "AUTH_ORIGIN": "https://la
- free-tier-eligible ↗
ng": "FULL_CONTENT_KV", "id": "00000000000000000000000000000010" } ], "d1_databases": [ { "binding": "DB", "database_name": "larafeed-template", "database_id": "00000000-0000-0000-0000-000000000010", "migrations_dir": "migrations" } ], "ratelimits": [ { "name": "AUTH_RATE_LIMITER", "namespace_id": "9001", "simple": { "limit": 20, "period": 60 } },
- free-tier-eligible ↗
un_worker_first": ["/api/*", "/export", "/up"] }, "images": { "binding": "IMAGES" }, "kv_namespaces": [ { "binding": "FULL_CONTENT_KV", "id": "00000000000000000000000000000010" } ], "d1_databases": [ { "binding": "DB", "database_name": "larafeed-template", "database_id": "00000000-0000-0000-0000-000000000010", "migrations_dir": "migrations" } ], "ratelimits": [ {
- free-tier-eligible ↗
up>1, 2, 3, 4</sup> | Duration | CPU time | | --- | --- | --- | --- | | **Free** | 100,000 per day | No charge for duration | 10 milliseconds of CPU time per invocation | | **Standard** | 10 million included per month <br> +$0.30 per additional million | No charge or limit for duration | 30 million CPU milliseconds included per month<br> +$0.02 per additional million CPU milliseconds<br><br> Max of [5 minutes of CPU time](https://developers.cloudflare.com/workers/platform/limits/#account-plan-limits) per invocation (default: 30 seconds)<br> Max of 15 minutes of CPU time per [Cron Trigger](https://developers.cloudflare.com/workers/configuration/cron-triggers/) or [Queue Consumer](https://developers.cloudflare.co
- free-tier-eligible ↗
oudflare.com/workers/platform/pricing/#workers) | | --- | --- | --- | | Rows read | 5 million / day | First 25 billion / month included + $0.001 / million rows | | Rows written | 100,000 / day | First 50 million / month included + $1.00 / million rows | | Storage (per GB stored) | 5 GB (total) | First 5 GB included + $0.75 / GB-mo | Track your D1 usage To accurately track your usage, use the [meta object](https://developers.cloudflare.com/d1/worker-api/return-object/), [GraphQL Analytics API](https://developers.cloudflare.com/d1/observability/metrics-analytics/#query-via-the-graphql-api), or the [Cloudflare dashboard ↗︎](https://dash.cloudflare.com/?to=/:account/workers/d1/). Select your D1 database, then vie
- free-tier-eligible ↗
cing/). | | Free plan<sup>1</sup> | Paid plan | | --- | --- | --- | | Keys read | 100,000 / day | 10 million/month, + $0.50/million | | Keys written | 1,000 / day | 1 million/month, + $5.00/million | | Keys deleted | 1,000 / day | 1 million/month, + $5.00/million | | List requests | 1,000 / day | 1 million/month, + $5.00/million | | Stored data | 1 GB | 1 GB, + $0.50/ GB-month | <sup>1</sup> The Workers Free plan includes limited Workers KV usage. All limits reset daily at 00:00 UTC. If you exceed any one of these limits, further operations of that type will fail with an error. Note Workers KV pricing for read, write and delete operations is on a per-key basis. Bulk read operations are billed by the amount
- free-tier-eligible ↗
dth) charges. | | Workers Free | Workers Paid | | --- | --- | --- | | Standard operations | 10,000 operations/day included | 1,000,000 operations/month included + $0.40/million operations | | Message retention | 24 hours (non-configurable) | 4 days default, configurable up to 14 days | In most cases, it takes 3 operations to deliver a message: 1 write, 1 read, and 1 delete. Therefore, you can use the following formula to estimate your monthly bill: ```txt ((Number of Messages * 3) - 1,000,000) / 1,000,000 * $0.40 ``` Additionally: - Each retry incurs a read operation. A batch of 10 messages that is retried would incur 10 operations for each retry. - Messages that reach the maximum retries and that are wr
- MIT ↗
MIT License Copyright (c) 2023 https://github.com/angristan Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PUR
- architecture ↗
{ "$schema": "./node_modules/wrangler/config-schema.json", "name": "larafeed-template", "main": "./src/worker/index.ts", "compatibility_date": "2026-07-18", "compatibility_flags": ["nodejs_compat"], "workers_dev": true, "preview_urls": true, "placement": { "mode": "smart" }, "secrets": { "required": ["AUTH_OPERATOR_SECRET"] }, "vars": { "AUTH_ENVIRONMENT": "production", "AUTH_ORIGIN": "https://la
- architecture ↗
ng": "FULL_CONTENT_KV", "id": "00000000000000000000000000000010" } ], "d1_databases": [ { "binding": "DB", "database_name": "larafeed-template", "database_id": "00000000-0000-0000-0000-000000000010", "migrations_dir": "migrations" } ], "ratelimits": [ { "name": "AUTH_RATE_LIMITER", "namespace_id": "9001", "simple": { "limit": 20, "period": 60 } },
- architecture ↗
un_worker_first": ["/api/*", "/export", "/up"] }, "images": { "binding": "IMAGES" }, "kv_namespaces": [ { "binding": "FULL_CONTENT_KV", "id": "00000000000000000000000000000010" } ], "d1_databases": [ { "binding": "DB", "database_name": "larafeed-template", "database_id": "00000000-0000-0000-0000-000000000010", "migrations_dir": "migrations" } ], "ratelimits": [ {
- architecture ↗
FRESH_DUE_LIMIT": "5", "OPML_IMPORT_ENABLED": "true", "FAVICON_REFRESH_ENABLED": "false", "IMAGES_ENABLED": "false", "FEED_REFRESH_QUEUE_NAME": "larafeed-template-feed-refresh", "OPML_IMPORT_QUEUE_NAME": "larafeed-template-opml-import", "FAVICON_REFRESH_QUEUE_NAME": "larafeed-template-favicon-refresh" }, "assets": { "not_found_handling": "single-page-application", "run_worker_first": ["/api/*", "/export", "/up"] }, "images": { "bindin
Upstream screenshot · angristan/larafeed repository contributors ↗. Depicts the upstream project. We have not deployed and tested a fresh installation here.
What it can replace
Compare the workflow you need. These mappings describe overlap; full feature parity requires a separate comparison.
Private RSS/Atom/JSON feed reading and organization, OPML import and read/star state; full enterprise connectors and AI knowledge tools are excluded.
See supporting source ↗Private RSS/Atom/JSON feed reading and organization, OPML import and read/star state; full enterprise connectors and AI knowledge tools are excluded.
See supporting source ↗How it works
The shape of Larafeed on Cloudflare, and how it stacks up against the rented tools it replaces.
Architecture
Diagram of deployment declarations at the reviewed commit. Each app has its own entrypoint; declared resources do not prove runtime calls. Follow file and line sources below.
View upstream source ↗Configuration and workflow sources
Reviewed commit eedbc8b9f6ec. Files were read as data; upstream applications and CI jobs were not executed.
Partial source coverage: 94 files outside collection bounds; 0 collection or parsing issues. Dynamic imports and generated entrypoints may need manual review.
Deployment configuration · 1 files
Cloudflare Workers · compatibility 2026-07-18
larafeed-template · default
Entrypoint: ./src/worker/index.ts
Static assets: directory not declared · single-page-application · Worker first: ["/api/*","/export","/up"]
Cron triggers (UTC): */10 * * * *
DB→ D1FULL_CONTENT_KV→ KVIMAGES→ ImagesFEED_REFRESH_QUEUE→ Queues (producer) · queue larafeed-template-feed-refreshOPML_IMPORT_QUEUE→ Queues (producer) · queue larafeed-template-opml-importFAVICON_REFRESH_QUEUE→ Queues (producer) · queue larafeed-template-favicon-refreshlarafeed-template-feed-refresh→ Queues (consumer) · queue larafeed-template-feed-refreshlarafeed-template-opml-import→ Queues (consumer) · queue larafeed-template-opml-importlarafeed-template-favicon-refresh→ Queues (consumer) · queue larafeed-template-favicon-refreshStatic assets→ Static assets
larafeed · env.production
Inherited from default: main, compatibility_date, compatibility_flags
Entrypoint: ./src/worker/index.ts
Cron triggers (UTC): */5 * * * *
Configured route patterns: larafeed.stanislas.cloud
DB→ D1FULL_CONTENT_KV→ KVAI→ Workers AIIMAGES→ ImagesFEED_REFRESH_QUEUE→ Queues (producer) · queue larafeed-feed-refreshOPML_IMPORT_QUEUE→ Queues (producer) · queue larafeed-opml-importFAVICON_REFRESH_QUEUE→ Queues (producer) · queue larafeed-favicon-refreshlarafeed-feed-refresh→ Queues (consumer) · queue larafeed-feed-refreshlarafeed-opml-import→ Queues (consumer) · queue larafeed-opml-importlarafeed-favicon-refresh→ Queues (consumer) · queue larafeed-favicon-refresh
larafeed-template · env.vitest
Inherited from default: main, triggers, compatibility_date, compatibility_flags
Entrypoint: ./src/worker/index.ts
Cron triggers (UTC): */10 * * * *
DB→ D1FULL_CONTENT_KV→ KVIMAGES→ ImagesFEED_REFRESH_QUEUE→ Queues (producer) · queue larafeed-test-feed-refreshOPML_IMPORT_QUEUE→ Queues (producer) · queue larafeed-test-opml-importFAVICON_REFRESH_QUEUE→ Queues (producer) · queue larafeed-test-favicon-refreshlarafeed-test-feed-refresh→ Queues (consumer) · queue larafeed-test-feed-refreshlarafeed-test-opml-import→ Queues (consumer) · queue larafeed-test-opml-importlarafeed-test-favicon-refresh→ Queues (consumer) · queue larafeed-test-favicon-refresh
Named environments are separate deployments. Bindings are shown only where declared. Configured routes are URL patterns, not verified application endpoints.
Runtime source · handlers, binding usage and workflow steps
Observed TypeScript/JavaScript declarations from Worker entrypoints and resolved relative imports. Calls and workflow steps may run conditionally; their listed order is not a proven end-to-end request flow. Router declarations may be mounted under a prefix or may not be registered. This shows code wiring, not a successful deployment or runtime test. Dynamic wiring, aliases and generated code may not resolve.
- L20 · fetch handler exported
- L21 · queue handler exported · references FEED_REFRESH_QUEUE_NAME, OPML_IMPORT_QUEUE_NAME, FAVICON_REFRESH_QUEUE_NAME · calls queueNames.some, name.trim, traceOperation, handleFaviconQueue, handleOpmlQueue, makeDefaultOpmlOrchestrator, handleRefreshQueue
- L65 · scheduled handler exported · calls runScheduledSubsystems, traceOperation, handleRefreshCron, handleOpmlCron, makeDefaultOpmlOrchestrator, opmlImportEnabled, handleFaviconCron
Environment references: env.FEED_REFRESH_QUEUE_NAME · env.OPML_IMPORT_QUEUE_NAME · env.FAVICON_REFRESH_QUEUE_NAME
Environment references: env.DB · env.AUTH_RATE_LIMITER · context.env.DB
Environment references: env.DB · env.OPML_IMPORT_ENABLED · env.AUTH_RATE_LIMITER
Build and deployment pipeline · 2 GitHub Actions workflows
Repository CI declarations, separate from runtime request processing. Job dependencies and conditions are shown as written; long commands are shortened with an ellipsis; a workflow file does not prove a recent successful run.
Triggers: push, pull_request
lint · no job dependencies declared
- actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803
actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 - actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38
actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 - oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6
oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 - Install JavaScript dependencies
bun install --frozen-lockfile - Biome
bun run lint-check - TypeScript
bun run typecheck - Generated Worker bindings
bun run types:check:cloudflare
Triggers: push, pull_request
test · no job dependencies declared
- actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803
actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 - actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38
actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 - oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6
oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 - Install JavaScript dependencies
bun install --frozen-lockfile - Install browser test runtime
bunx --no-install playwright install --with-deps chromium - Repository release gate
bun run validate:release
build: CLOUDFLARE_LOAD_DEV_VARS_FROM_DOT_ENV=false bun scripts/cloudflare-build.tsbuild:production: CLOUDFLARE_ENV=production CLOUDFLARE_LOAD_DEV_VARS_FROM_DOT_ENV=false bun scripts/cloudflare-build.tsbuild:cloudflare: bun run builddeploy:artifact: CLOUDFLARE_LOAD_DEV_VARS_FROM_DOT_ENV=false wrangler deploydeploy:artifact:check: CLOUDFLARE_LOAD_DEV_VARS_FROM_DOT_ENV=false wrangler deploy --dry-rundeploy: bun run build && bun run deploy:artifact:check && bun run d1:migrate && bun run deploy:artifactdeploy:production: bun run build:production && bun run deploy:artifact:check && bun run d1:migrate:production && bun run deploy:artifactdeploy:check: bun run build && bun run deploy:artifact:checkdeploy:check:production: bun run build:production && bun run deploy:artifact:checkdeploy:check:cloudflare: bun run deploy:checkrelease:production: bun run validate:release && bun run deploy:production
Repository README
View original on GitHub ↗Full upstream document by @angristan · README.md · snapshot eedbc8b
Larafeed

Larafeed is a simple feed reader.
Features
- A pleasant and snappy UI
- Entries are marked as read when you view them
- Entry links open in a new tab
- Keyboard shortcuts and quick feed navigation
- RSS, Atom, RDF, and JSON Feed support
- Website feed discovery with a choice when several feeds are available
- Background feed updates
- Failures are stored and displayed in the UI
- Custom feed names and categories
- Entry filtering per subscription by title, content, or author
- Read, starred, and archived entries
- AI-generated summaries
- Favicon display with automatic dark-mode styling
- OPML import and export
- Google Reader and Fever API support with revocable app tokens
- Support is partial, but works with Reeder Classic
- Passkey-only private access
- Estimated reading time for each entry
Screenshots & demo
Reader view

Demo of the LLM summary generation
https://github.com/user-attachments/assets/0553f893-cc5a-4efa-b098-1b1e10545698
Demo of the feed refreshing UX
https://github.com/user-attachments/assets/a420f8cd-d306-4a0d-afe3-d391852055ad
Demo of the quick add feed from a bookmark
https://github.com/user-attachments/assets/bb266745-5d16-4d06-9534-653df38212bc
Technical overview
flowchart LR
Browser["React + Mantine<br/>React Router + TanStack Query"]
Worker["Cloudflare Worker<br/>Hono + Effect"]
D1[(D1)]
Queues[Cloudflare Queues]
Cron[Cron Triggers]
Images[Cloudflare Images]
AI[AI Gateway]
WorkersAI[Workers AI]
Feeds[Feed publishers]
Browser <--> Worker
Worker <--> D1
Worker <--> Queues
Cron --> Worker
Worker --> Images
Worker --> AI --> WorkersAI
Worker --> Feeds
- The TypeScript backend runs on Cloudflare Workers with Hono for routing and Effect for application logic.
- The frontend uses React with the amazing Mantine components and hooks, React Router, and TanStack Query.
- D1 stores users, subscriptions, entries, sessions, and durable job state.
- Queues process feed discovery, refreshes, and favicons one feed at a time.
- Feed requests use conditional HTTP headers to avoid downloading unchanged content, then adapt their next refresh from observed changes and publisher cache hints.
- Cloudflare Images proxies article images for privacy and performance.
- AI summaries use Workers AI through Cloudflare AI Gateway and are cached in D1.
- Google Reader and Fever APIs are implemented from scratch.
- I relied heavily on the implementations in FreshRSS and Miniflux.
- Using Reeder Classic with Miniflux as a backend, I inspected the API calls with mitmproxy to reverse-engineer the protocols.
Deploy to Cloudflare
The installer provisions the Worker, D1 database, KV namespace, and Queues, then applies all D1 migrations. It asks for the public HTTPS origin and a private operator secret used to create the first administrator enrollment link.
See the deployment guide for administrator enrollment and optional integrations. Operational and reader-client details are in the operations and compatibility API guides.
Development
Requirements: Node.js 24 and Bun 1.3.14.
bun install --frozen-lockfile
bunx --no-install playwright install chromium
cp .dev.vars.local.example .dev.vars
bun run d1:migrate:local
bun run dev
Run the complete validation suite with bun run validate.
License
Larafeed is licensed under the MIT license.
Frequently asked about Larafeed
What is Larafeed?+
Larafeed is a self-hosted Feedly/Inoreader alternative built on the Cloudflare developer platform. Read and organize RSS, Atom and JSON feeds in a private Cloudflare-hosted reader.
What does Larafeed replace?+
Larafeed is listed as an alternative to Feedly, Inoreader. Compare the features and tradeoffs before migrating.
What Cloudflare primitives does Larafeed use?+
Larafeed is built on D1, KV, Queues, Workers.
How much does Larafeed cost to run?+
The documented Larafeed deployment can use Cloudflare Free allowances for a small workload under the request, CPU and service-specific quotas below. This is conditional eligibility, not a measured zero-cost deployment; optional features, domains and external providers can add costs. Workers Free allows 100,000 requests per day shared across the account and 10 ms CPU per invocation; measure CPU-heavy authentication, parsing and rendering before assuming it fits. Keep aggregate D1 use below 5 million rows read/day, 100,000 rows written/day and 5 GB total storage; a request can touch many rows. Keep KV below 100,000 reads/day, 1,000 writes, deletes and list operations/day each, and 1 GB; cache refreshes and backups consume writes. Keep total queue operations within 10,000/day, counting writes, reads, deletes, retries and each 64 KB chunk; Free retention is 24 hours. Use a small personal or team workload; domain registration and optional third-party providers are separate costs. Provision your own IDs, secrets and migrations. Check current Cloudflare pricing before deploying.
Is Larafeed open source?+
The upstream repository declares the MIT license. Read its terms at https://raw.githubusercontent.com/angristan/larafeed/eedbc8b9f6ec44229a8ed75efd0e6a1dc3945266/LICENSE. Source code and contributor credit are available at https://github.com/angristan/larafeed.



Discussion · 0
sign in to comment →