CleanFrame
A personal home screen for Samsung The Frame. A starting point to fork and adapt.
Meet the makers keeping Japan’s everyday flavours alive. A directory of the producers, farmers and makers Cabi knows by name, with food guides to all 47 prefectures.
LifestyleHTML · TypeScriptGitHub @erzzz3123OnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
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 ↗Directory of the people, producers and places Cabi works with across Japan. Intended home: friends.cabifoods.com
main redeploys on Vercel; pull requests get preview URLs.app.html served through api/page.js with per-page SEO, admin.html) and the serverless API in /api. No build step.Dropbox app folder ──(:05 hourly, Edge Function dropbox-sync)──▶ Storage `producer_images` ──URLs──▶ Airtable "Image URLs"
Airtable ──(every 15 min, Edge Function airtable-sync)──▶ Supabase `friends` + `friend_images`
visitor ──▶ /api/page (app.html + SEO) ──▶ /api/data ──(anon key, RLS: published only)──▶ Supabase
visitor ──▶ Submit form ──▶ /api/submit ──(service key)──▶ submissions table
└──── photos PUT straight to the private `submissions` bucket (signed URLs)
staff ──▶ /admin (magic-link sign-in) ──▶ /api/admin ──▶ approve → producer row + photos copied to public `friends` bucket
The page loads live data from /api/data. If that fails it falls back to the bundled data.js, so the site never shows empty.
| Path | What it is |
|---|---|
app.html | The whole public site (Directory, Map, Profile, Prefecture, About, Get in touch). Real URLs: /friend/:slug, /pref/:slug, ?lang=ja for Japanese |
api/page.js, lib/seo.js | Per-page titles, descriptions, hreflang, Open Graph, JSON-LD, Google Analytics (GA_MEASUREMENT_ID) and server-rendered text; /sitemap.xml from api/sitemap.js |
admin.html | Staff review screen at /admin |
api/data.js | Published producers + prefectures as window.FRIENDS / window.PREFS (60 s CDN cache) |
api/submit.js | Submit a Producer: validation, rate limit, signed photo uploads |
api/admin.js | Approve / decline submissions, edit and publish producers |
api/config.js | Public Supabase URL + anon key for the admin sign-in |
supabase/functions/dropbox-sync/ | Edge Function: Dropbox app folder → Storage producer_images → Airtable Image URLs |
supabase/functions/airtable-sync/ | Edge Function: Airtable → site database (every 15 min, and from /admin) |
supabase/functions/dropbox-connect/ | Edge Function: one-click Dropbox authorisation (token goes straight to Vault) |
supabase/dropbox.sql | Bucket, sync bookkeeping tables, both hourly Cron jobs |
scripts/dropbox-connect-link.sh | Prints a 30-minute Dropbox connect link |
scripts/set-secret.sh | Sets one Edge Function secret with hidden input |
supabase/schema.sql | Tables, constraints, row-level security, storage buckets (re-runnable) |
supabase/seed.sql | 47 prefectures + the current 27 producers and their bundled photos |
Create an empty repo (e.g. cabifoods/cabifriends), then from this folder:
git remote add origin [email protected]:YOUR-ORG/cabifriends.git && git push -u origin main
ap-northeast-1).supabase/schema.sql, then supabase/seed.sql.https://friends.cabifoods.com, and add redirect URLs
https://friends.cabifoods.com/admin, https://*.vercel.app/admin and http://localhost:3000/admin.insert into admins (email) values ('[email protected]');anon public key and the service_role secret key.SUPABASE_URL, SUPABASE_ANON_KEY, SUPABASE_SERVICE_ROLE_KEY
(and optionally SUBMIT_SECRET) for Production and Preview. See .env.example./api/data starts with window.FRIENDS=[{ (not /* api unavailable */).friends.cabifoods.com, then add the CNAME it shows wherever cabifoods.com DNS is managed.npm i -g vercel && npm install && vercel link && vercel env pull .env.local && vercel dev
Or serve the folder with any static server: everything works from data.js except submitting and /admin.
new; photos go to the private bucket.Producers without coordinates are placed at the centre of their prefecture on the map. Photo uploads and
deletions for existing producers are done in Supabase → Storage (friends bucket) + the friend_images table.
This is the beginning of the README. Read the rest at the original. Read the full README ↗