Fujimod
Try your camera firmware in the browser and build Fujimod SD boot files.
Archiwum przepisów udostępnianych z mediów społecznościowych.
Translation pending
LifestyleTypeScript · HTMLGitHub @spokospaceOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
ZapiszPrzepis — archive-first PWA for saving recipes shared from social media
Taken from the repository README
Loading the full README.
Read the full README ↗An archive-first PWA for saving recipes shared from social media. Every URL arrives via the system Share gesture and is transformed into a permanent, Polish-language copy of the recipe — independent of the original source.
Stack: Next.js 16 (App Router) · TypeScript · Tailwind v4 · Supabase (auth + Postgres + storage) · Inngest (async jobs) · PWA (offline + Web Share Target) · Cloudflare Workers
Live app: https://zapiszprzepis.pl
Registration is gated by an invite code. The code is a runtime secret (INVITE_CODE),
never committed — open an issue
if you would like one to try the app.
Every shared link goes through the same pipeline — fetch the source, extract the recipe with an LLM into a Polish-language copy, archive the image — and only the fetch step differs per source.
| Source | How the recipe text is obtained | Limits |
|---|---|---|
Facebook Reels and videos — facebook.com/reel/…, …/videos/…, app share links facebook.com/share/r/…, fb.watch | The post caption, read from Facebook's embedded-video plugin (plugins/video.php?show_text=true) — no Facebook session needed, and the part hidden behind "See more" is included. The cover frame becomes the recipe image and is archived right away, because Facebook's image links expire within days. | A recipe that exists only in the video, with no caption, cannot be extracted. Text and photo posts are not supported — Facebook's post plugin refuses them. |
YouTube — watch links, youtu.be, Shorts | The video description, scraped with Firecrawl. | The player is embedded on the recipe page. |
| Blogs and recipe sites — any other URL | Firecrawl main-content scrape, retried on the full page for classic blog templates; Blogspot posts come straight from the Blogger JSON feed. | An embedded YouTube player on the post is detected and embedded on the recipe page. |
A share that cannot be turned into a recipe lands in the header bell with the reason, and can be retried from there.
Requirements: Node ≥ 20.6, pnpm (Corepack-managed — version pinned in package.json#packageManager), Supabase account, Cloudflare account.
Clone and install:
git clone https://github.com/spokospace/zapiszprzepis.git
cd zapiszprzepis
corepack enable # one-time — activates the pinned pnpm version
pnpm install
Create a Supabase project at https://supabase.com/dashboard:
zapiszprzepis, Region: Central EU (Frankfurt), Plan: Freehttps://<ref>.supabase.co)anon public JWT)Configure redirect URLs in Supabase Authentication → URL Configuration:
https://zapiszprzepis.plhttp://localhost:3000/auth/callbackhttps://zapiszprzepis.pl/auth/callbackLocal .env.local:
cp .env.local.example .env.local
# fill in NEXT_PUBLIC_SUPABASE_URL and NEXT_PUBLIC_SUPABASE_ANON_KEY
Link Supabase CLI and push migrations:
pnpm exec supabase login
pnpm exec supabase link --project-ref <ref>
pnpm exec supabase db push --linked
Recipe extraction (scraping + LLM) runs asynchronously via Inngest, outside the Cloudflare Worker request path (NFR p95 ≤ 3 min). Locally:
Start the Inngest Dev Server (separate terminal):
npx inngest-cli@latest dev
# → listens on http://localhost:8288
Start Next.js dev:
pnpm dev
Local dashboard: http://localhost:8288 — "Runs" tab shows execution history
Local secrets (.env.local):
INNGEST_EVENT_KEY=... # Inngest Dashboard → Event Keys
INNGEST_SIGNING_KEY=... # Inngest Dashboard → Signing Keys
Deployment:
pnpm run deploy # deploys the Worker to Cloudflare (Inngest connects via /api/inngest)
# `run` is required: bare `pnpm deploy` is pnpm's own workspace-deploy command, not this script
Two cron triggers run in the deployed Worker, declared in wrangler.jsonc and
dispatched by custom-worker.ts.
| Cron (UTC) | Job | Why |
|---|---|---|
30 3 * * * | Dump recipes + recipe_shares to R2 as recipes/<YYYY-MM-DD>.json | The free Supabase plan includes no backups |
0 4 * * * | SELECT one row through PostgREST | The free plan pauses a project after a week without database activity |
One-time setup — the backup silently logs backup: skipped until both exist:
npx wrangler r2 bucket create zapiszprzepis-backups
npx wrangler secret put SUPABASE_SERVICE_ROLE_KEY # paste the key when prompted
The dump needs the service role because RLS would otherwise hand it an empty array. It covers table rows only — archived images live in Supabase Storage and are not copied.
Restore is manual: fetch the object, then feed the arrays back through PostgREST or the SQL editor.
npx wrangler r2 object get zapiszprzepis-backups/recipes/2026-09-05.json --file backup.json
Nothing prunes old objects. At a few hundred kB a day that stays far inside R2's free tier for years, but it does grow without bound.
Installable on Android (Chrome/Edge), Windows, and macOS. Offline-capable with Web Share Target API.
Installation:
Web Share Target (system Share gesture):
text/plain, text/uri-list/share → processes URL → recipe appears in listService Worker & Offline (public/sw.js, tests in src/lib/sw.test.ts):
/_next/static/*, content-hashed): cache-first/api/*, and every non-GET request (Server Actions, Web Share Target): network only, never cached/), then an „Offline” response/sw.js?v=<build>: the new worker gets fresh caches and waits until every app window is closed, so open tabs are never reloadedpnpm dev # http://localhost:3000
pnpm build # production build
pnpm lint # ESLint
pnpm test # Vitest unit tests
pnpm check:auth # smoke test: ping Supabase auth/v1/health
src/middleware.ts — checks the session on every request with supabase.auth.getClaims() (the JWT is verified locally; an expiring session is refreshed); redirects unauthenticated users to /login.src/lib/supabase/{server,client,proxy}.ts — three Supabase client helpers with getAll/setAll cookie adapter.src/app/login/ — Server Component + Server Action (signInWithEmail — magic-link OTP).src/app/rejestracja/ — invite-code gated registration (/signup redirects here).src/app/auth/callback/ — Route Handler (exchangeCodeForSession with error mapping).supabase/migrations/ — baseline: pg_trgm + public.current_user_id() + RLS policies.Full PRD, roadmap, and implementation plans live in context/:
context/foundation/prd.md — Product Requirements Documentcontext/foundation/roadmap.md — feature map F-01 … S-09context/foundation/tech-stack.md — stack rationalecontext/foundation/test-plan.md — risk-based quality contractcontext/changes/<change-id>/ — per-change folder with plan and progress