Free weekly Ethiopian meal plans sized for your goal: lose weight, build muscle or both. Injera, wot, tibs and shiro, plus fasting days, a food log and workouts.
HealthJavaScript · TypeScriptGitHub @biniyaminrOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
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
The maker's introduction consists of the line above. Read the repository README for more details. Repository README ↗
Loading the full README.
Read the full README ↗A free meal, workout and progress app built on Ethiopian food, named after
Ethiopia’s everyday flatbread. Anyone can create an account. New users answer a
short setup (goal, sex, age, height, weight, activity, fasting days) and get
daily targets (Mifflin-St Jeor) plus a seven-day Ethiopian meal plan scaled to
them, with meat-, egg- and dairy-free meals on their fasting days
(public/plate/plans.js). Accounts that already had history before this
(Benji’s) keep the original hand-written plan until they choose a goal.
The app includes the meal plan, a five-day training schedule with two recovery days, a food log with macro totals, weigh-ins, and walking and sleep check-ins.
It also works out, from what is logged (nothing extra is stored):
claude-opus-5-5,
lib/food/claude.ts) estimates each food, its portion and its macros. The person checks and
edits the estimate before anything is added. Photos are shrunk in the browser, sent once for
analysis and not stored. Each account gets 20 analyses a day (use_ai_quota() in
supabase/migrations/20261028000000_ai_usage.sql).Built with Next.js on Vercel, with Supabase for the database (PostgreSQL) and for email/password accounts. The public home page describes the site only. Every log, weigh-in and backup is private to the signed-in account.
| Part | Where |
|---|---|
| Public home page and account pages (sign in, sign up, reset password) | app/ (Next.js App Router) |
| The meal and workout app: the original pages, kept as they were | shell/index.html, shell/nutrition.html, served only to signed-in users by app/app/route.ts and app/app/nutrition/route.ts |
| App scripts and styles | public/plate/ (fitness.js, plans.js, insights.js, app.js, visuals.js, merge.js, sync.js, importer.js, dates.js, fitness.css, extra.css) |
| Records API | app/api/progress/route.ts (GET/PUT), app/api/progress/validate/route.ts (checks a backup without saving) |
| Validation and save rules | lib/progress/schema.ts, lib/progress/handler.ts |
| Database | supabase/migrations/20261026000000_progress.sql |
| Session refresh and route protection | proxy.ts, lib/supabase/ |
Records. Each account has two records, fitness (profile, daily logs, weigh-ins)
and nutrition (targets and weighed food entries). Both use the same JSON shape as the original site, so old
backups import directly.
Privacy.
Cache-Control: private, no-store.No silent overwrites. Every save is a compare-and-swap on a revision number
(save_progress() in the migration). If another tab or device saved first, the
save is refused with HTTP 409 and the page offers two choices:
In both cases a copy of this tab's version downloads first.
Saving states. The bar at the top of the app shows one of: saving, saved, offline, error, signed out, or conflict. "Saved" appears only after the server confirms the write. Unsaved edits are kept in this browser, per account, until they reach the server.
Version history. Every update copies the previous version into
progress_history (the last 50 per record). This is a safety net for undoing a
mistaken import (see Recovering an earlier version below).
Dates. Calendar days follow Africa/Addis_Ababa, whatever timezone the
device uses. public/plate/dates.js does date maths on plain YYYY-MM-DD
strings so days never shift.
Needs Node 22.13+ and pnpm 11 (corepack enable or npx [email protected]).
pnpm-workspace.yaml only installs package versions that have been public for at
least 7 days.
pnpm install
cp .env.example .env.local # fill in your Supabase URL and publishable key
pnpm dev # http://localhost:3000
Create a project. On supabase.com, create a new project (the free plan is fine). Pick a region close to Addis Ababa, such as Frankfurt (eu-central-1).
Create the tables. Open SQL Editor, paste in all of supabase/migrations/20261026000000_progress.sql, and run it.
Set the sign-in URLs. Go to Authentication → URL Configuration:
https://www.biniyam.site (the bare domain redirects to www)https://biniyam.site/**https://www.biniyam.site/**http://localhost:3000/**https://daily-plate-sooty.vercel.app/**https://*-biniyaminrs-projects.vercel.app/** (Vercel preview deployments)Turn on sign-up. Go to Authentication → Sign In / Providers → Email and keep "Confirm email" on.
Make email links work on any device. In Authentication → Emails → Templates, replace the link in these two templates:
<a href="{{ .RedirectTo }}&token_hash={{ .TokenHash }}&type=email">Confirm your email</a><a href="{{ .RedirectTo }}&token_hash={{ .TokenHash }}&type=recovery">Choose a new password</a>The app already puts ?next=… in the redirect address, which is why these links start with &. Unchanged default templates also work, but only when the link is opened in the same browser that asked for it.
Copy the keys. In Project Settings → API keys, copy the Project URL and the publishable key into Vercel (see below). Never copy the secret or service-role key.
Photo food log (optional).
supabase/migrations/20261028000000_ai_usage.sql (the daily limit).ANTHROPIC_API_KEY (from console.anthropic.com → API keys) for Production, then redeploy. It is read only on the server.Required for public sign-ups: Supabase’s built-in email sender only sends a few emails per hour, so new people would not receive confirmation emails. Set up custom SMTP (for example Resend, Brevo or Amazon SES) under Authentication → Emails → SMTP Settings.
biniyaminr/daily-plate into Vercel. The framework is detected as Next.js and the defaults are fine.NEXT_PUBLIC_SUPABASE_URLNEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEYbiniyam.site and www.biniyam.site. Set one to redirect to the other, then add the DNS records Vercel shows at your registrar. Leave any other DNS records alone.pnpm test # unit: merge, import preview, dates, insights, reports, meal plans and targets
pnpm test:db # PostgreSQL: the real migration + RLS + API handler
pnpm typecheck && pnpm lint && pnpm build
pnpm test:db starts a throwaway local PostgreSQL (15 or newer; set PGBIN if
it isn't on your PATH). It applies a small stand-in for Supabase's auth
schema (tests/db/supabase-stub.sql) and then the real migration. It checks:
For browser testing without Supabase, run
node --experimental-strip-types tests/e2e/local-server.mjs. It serves the real
pages and the real API handler with an in-memory store and a fixed test user.
The old site kept data either in its own database (signed in with ChatGPT) or in that browser only. Neither carries over automatically: a browser keeps saved data separately for each website, so biniyam.site cannot see the old site's.
On the old site, open My progress and choose Download backup. If you used it without signing in, use Download browser backup on the device where you logged things.
Sign in on biniyam.site. Import before logging anything new. Otherwise the new account creates its own profile (with today's start date), and the import keeps the account's values where they differ.
Choose Import backup, either in the top bar or under My progress, and pick the file. It is checked on the server and nothing is saved yet.
Read the preview. It shows how many weigh-ins, logged days and food entries are new, and lists each value that differs from your account.
Keep Add missing records selected (the default) and choose Import. This never removes or changes what is already in your account, and importing the same file again adds nothing.
Replace my account records is only for starting over. You must type REPLACE to confirm, and your current records download first.
The confirmation lists exactly what was added. Check your other devices: the records are there after a refresh.
Keep the old site and its data until you have checked everything on biniyam.site.
In the Supabase SQL Editor (which runs as the project owner):
select id, kind, revision, replaced_at
from progress_history
where user_id = '<your user id>'
order by id desc;
To restore one, copy its payload out to a JSON file shaped like
{ "version": 1, "fitness": … } and import it with Replace.
Keep sign-ups on. The app is open to the public, so leave Allow new users to sign up enabled.