Skip to content

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Sadaqa

A single-page donation tracker backed by a Google Sheet. No backend, no build step, no database. You edit a spreadsheet; the page updates within minutes.

Built for صدقة جارية campaigns run by a few friends in a WhatsApp group — the money is pooled, spent on one project at a time, and everyone can see where it went.

  • Live total, share count, progress bar toward the current goal
  • Milestones with real delivery states — funds collected is not work done
  • Photos of past examples while collecting, receipts and proof once finished
  • InstaPay, e-wallets and bank transfer, each tap-to-copy
  • Arabic, RTL, mobile first, dark

1. The sheet

Create a Google Sheet with five tabs. The names below are just labels for you — the page finds each tab by its gid, so call them whatever you like:

Tab Columns What it is
donations date · channel · amount one row per donation received
milestones name · target · note · status · link · images · proof the projects, in spending order
payments type · name · provider · number · iban · link how people can give
content text · style the paragraphs at the top of the page
settings key · value numbers and wording

Starter CSVs for all five are in examples/. Create each tab, then File → Import → Upload → Replace current sheet for that tab.

Only the header row matters — column order is free, and extra columns are ignored.

content and settings are optional: leave their gids as PASTE-GID and the page runs on its built-in Arabic wording. The donations and milestones tabs are what make it useful.

donations

Only amount is read. 1,250, ١٢٥٠, ج.م ٣٠٠ and 1 500 all parse. Do not add a totals row; it would be counted twice.

milestones

Order is spending order. Money is one pool: a project is only funded once everything above it is paid for.

  • target — cost in your currency. Leave empty if not confirmed yet; the page then shows note instead of a number and skips it in the arithmetic.

  • status — leave empty while collecting. Then, by hand, as things happen:

    value badge effect
    (empty) الهدف الحالي / التالي / لاحقًا / اكتمل جمع المبلغ worked out from the money
    transferred تم تحويل المبلغ إلى الجهة subtracted from the headline figure
    working جارٍ التنفيذ subtracted
    done ✓ تم بحمد الله subtracted

    The headline number is money still in hand — collected minus everything already handed over. Only mark a milestone once the transfer has really happened.

  • link — an outward link, shown as اعرف المزيد.

  • images — photos of comparable past work, shown while still collecting.

  • proof — receipts and photos of the finished work, shown only when status is done, replacing images.

Separate multiple images with commas: img/a.jpg, img/b.jpg.

payments

One row per method. type groups them under a heading:

type uses shows
instapay name, number, link a transfer button beside a tap-to-copy username
ewallet name, provider, number provider name and a tap-to-copy number
bank name, provider, number, iban account number and IBAN, both tap-to-copy

Any other type gets its own section too — add label_<type> in settings to title it. Adding a wallet is a row, never a code change.

content

Each row is a paragraph at the top of the page, in order. style is text, quote (muted, for a hadith or citation) or prayer. Alt+Enter makes a line break inside a cell.

settings

key / value. Everything here is optional — each key has a sensible Arabic default, so an empty tab still renders a correct page. Common ones:

title            العنوان أعلى الصفحة
currency         جنيه مصري
share_value      200          ← one "سهم" is worth this much
fallback_total   0            ← shown only if the donations tab cannot be read
projects_note    a line above the milestone list

Every visible string can be overridden: label_current, label_done, label_instapay, label_copy, label_offline … see examples/settings.csv and DEFAULTS in src/model.js for the full list.


2. Publish the sheet

File → Share → Publish to web → Entire document → Comma-separated values (.csv) → Publish.

Make sure "Automatically republish when changes are made" is ticked, or your edits will never reach the page.

Google gives you a URL containing a long id starting 2PACX-. Copy that id.

Then click each tab and read its gid from the address bar:

https://docs.google.com/spreadsheets/d/…/edit#gid=1295809989
                                                  └─ this

Put both into config.js — the only file you edit. You can paste the whole published URL or just the id, and either the bare gid or the whole address-bar URL; both are recognised:

export const SHEET = {
  publishedId: "2PACX-1vS…",
  tabs: {
    donations:  "0",
    milestones: "1295809989",
    payments:   "…",
    content:    "…",
    settings:   "…",
  },
};

Published CSV is the only Google endpoint that sends CORS headers, which is why this needs gids rather than tab names.

Edits appear on the page within a few minutes — Google's publish cache lags a little behind the editor.

If the sheet cannot be reached at all, the page says so rather than showing a zero. Open the browser console for the specific tab that failed.


3. Deploy free on Cloudflare Pages

Dashboard — Workers & Pages → Create → Pages → Upload assets → drag the whole folder in. Or:

npx wrangler pages deploy . --project-name=my-sadaqa

You get https://my-sadaqa.pages.dev. Then, once, open index.html and replace YOUR-PROJECT.pages.dev in the four og: / twitter: meta tags with your real domain, and deploy again — chat apps need absolute URLs or the link preview shows nothing.

Test the preview at developers.facebook.com/tools/debugScrape Again before sharing. WhatsApp caches a link's preview the first time it is sent and will not refresh it.

Keep the preview text and og.png free of amounts and goals — they are static and would go stale. The live numbers are on the page.


4. Images

Put them in img/ and deploy them with the site, then reference them relatively:

milestone images →  img/well-1.jpg, img/well-2.jpg

Facebook and Google Drive links do not work as images — they block hotlinking and the photo silently disappears. Files must be uploaded with the site, or served from somewhere that allows direct linking.

Adding photos therefore needs a redeploy. Everything else — text, amounts, milestones, statuses, payment methods — is sheet-only.

Regenerate og.png after editing og-template.html:

"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" \
  --headless --disable-gpu --window-size=1200,630 \
  --screenshot=og.png --virtual-time-budget=4000 og-template.html

Local preview

python3 -m http.server 8000

then open http://localhost:8000. Opening index.html by double-clicking will not work: browsers block both ES modules and cross-origin fetches on file://, so the page falls back to its offline state.


How it is put together

index.html      markup only
styles.css      all styling; change --accent to re-skin
config.js       your sheet id and gids — the only file you must edit
src/csv.js      CSV, number and URL parsing
src/sheet.js    fetching tabs, turning rows into objects
src/model.js    the arithmetic and rules; DEFAULTS lives here
src/render.js   everything that touches the DOM
src/main.js     wiring
examples/       starter CSV for each tab

Plain ES modules, no bundler, no dependencies except a Google font.

Safety. The sheet is treated as untrusted input: text is inserted as textContent, never HTML, and any URL whose scheme is not http(s) is dropped, so a javascript: link in a cell cannot execute. Several people usually share edit access — this matters.

Never renders zero or a broken page. If the donations tab fails, times out (8s), or returns nothing usable, the page shows fallback_total with a quiet note. Any tab can fail independently without taking the others down.


Licence

MIT — see LICENSE.

About

Arabic donation tracker backed by a Google Sheet. No backend, no build step, no database.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages