Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

130 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

MicroMatch — Make a big impact in a few minutes.

License: MIT SvelteKit Appwrite Bun Tests


A micro-volunteering marketplace pairing NGOs with volunteers for bite-sized, skill-building tasks. Volunteers browse a feed of 5-30 minute missions, claim what fits their skills, and earn badges for approved work. NGOs post tasks, review submissions, and build a verified presence on the platform.

✨ Features

  • Bite-sized task feed — filter by ≤15 / ≤20 / ≤30 min, hashtag, or sort by shortest first.
  • Volunteer side — claim tasks, submit proof (link or upload), track status, earn badges, level up.
  • NGO side — post tasks with deadline + max-volunteers caps, review submissions, manage org-owned badge definitions.
  • NGO verification — soft-gate trust system. NGOs submit a tax/charity ID, admins review with ProPublica lookup enrichment, approval back-fills the Verified chip on every existing task.
  • Custom badge definitions — NGOs define their own awards (label, color, icon, criteria); the engine auto-awards on claim approval.
  • Role mobility — users can flip between Volunteer and NGO; downgrading from NGO triggers a clean transactional teardown of verification + tasks.
  • Auto-translate — task title + description translate to the viewer's language via Microsoft Azure Translator.
  • Email notifications — verification approve/reject sends Mailgun-backed transactional emails to the NGO.

🎬 In motion

These are real Playwright recordings of the app — captured by the test suite at e2e/demo/, post-processed to GIF for embedding here. Nothing is mocked or sped up: every click is a real session against a real Appwrite backend.

The closed loop — claim → submit proof → NGO approves → badge lands

The whole product in one take. A volunteer claims a task and submits their work, the NGO reviews that submission and approves it, and the badge lands in the volunteer's vault. It all happens on-platform, without the handoff to email that a directory would leave you to. The sign-out in the middle is real: the volunteer and the org are two different accounts.

The closed loop

Landing page tour — hero → How it works → Featured tasks → Track your impact

Landing page tour

Signup flow — role picker → fill the form (no real account is created)

Signup flow

Feed UX — search, time filters, and hashtag chips

Feed UX

NGO badge tooling — define a badge, then read the analytics

Badges are org-owned definitions rather than a hardcoded list: an NGO picks a template or builds its own, and the awarder mints it on claim approval.

NGO badge tooling

Mobile nav — the hamburger menu at phone width

Mobile nav

Run bun run demo to regenerate: it reseeds, records fresh MP4s, and converts them to GIFs. The reseed is not optional. Demo tasks auto-archive after 30 days of no activity, and the closed-loop recording needs its claim and badge state reset or the badge never appears. See CONTRIBUTING.md for the one-time setup, e2e/demo/ for the specs, and playwright.demo.config.ts for the recording configuration.

🔄 How it works

The core loop, end-to-end:

sequenceDiagram
  autonumber
  actor V as Volunteer
  actor N as NGO
  participant App as MicroMatch
  participant DB as Appwrite
  participant Mail as Mailgun

  N->>App: Post task
  App->>DB: tasks.create (isVerified ← NGO's verification status)

  V->>App: Browse feed, claim task
  App->>DB: claims.create (status=pending)

  V->>App: Submit proof (URL or file)
  App->>DB: claims.update (proofUrl, notes)

  N->>App: Approve claim
  App->>DB: claims.update (status=approved)
  App->>DB: badges.create (matching BadgeDefinitions for org)
  App-->>V: Dashboard updates, badge appears in vault

  Note over N,Mail: Verification flow (parallel)
  N->>App: Submit verification (tax ID + doc)
  App->>DB: ngoVerifications.create (status=pending)
  Note over App: Admin reviews queue with ProPublica enrichment
  App->>DB: status=approved, back-fill tasks.isVerified
  App->>Mail: Send "you're verified" email
  Mail-->>N: 📧
Loading

🚀 Tech stack

Framework SvelteKit on Vercel (adapter-vercel, nodejs22.x runtime)
Runtime + package manager Bun
Backend Appwrite Cloud — Database (TablesDB), Auth, Storage, Teams
Email Mailgun (HTTP API, no SDK dep)
NGO verification ProPublica Nonprofit Explorer API for US 501(c)(3) lookups
i18n Azure Translator
UI Plus Jakarta Sans + Inter, custom CSS (warm cream palette + coral accents), Iconify, Lottie
Testing Vitest (unit + API + components) and Playwright (e2e)

🏁 Getting started

Quick path:

git clone https://github.com/Builder106/micro-match.git
cd MicroMatch
bun install
cp .env.example .env
# Fill in Appwrite + Mailgun + ProPublica keys
bun run dev

The app runs at http://localhost:5173. Full setup (Appwrite resources, environment variables, project layout, conventions) lives in CONTRIBUTING.md.

Common scripts

bun run dev             # dev server with HMR
bun run build           # production build (uses adapter-vercel)
bun run check           # svelte-check + tsc
bun run test            # vitest (459 tests across server / API / components)
bun run test:e2e        # Playwright (run `bunx playwright install chromium` once)
bun run seed            # (re)seed the demo NGO + tasks — run before any demo recording
bun run demo            # seed, record the demo suite, convert to GIFs
bun run render-media    # regenerate the README banners + social preview from /static/*.html

🧪 Testing

Three layers of coverage:

  • Server modules (vitest, node) — pure-ish helpers and DB CRUD: tagColors, propublica, email, verifications, badgeDefs, badgeCriteria, badgeAwarder. Mock fetch + Appwrite at the module boundary.
  • API endpoints (vitest, node) — /api/verifications, /api/verifications/[userId]/approve, /api/verifications/[userId]/reject, /api/profile/role, /api/badges/manage. Auth gates, validation, multi-step side effects.
  • Components (vitest, jsdom) — BadgeChip, EmptyState, ProgressBar, VerificationCard (all four state branches via mocked fetch).
  • End-to-end (Playwright, chromium) — public-facing flows: landing, feed, login/signup multi-step, forgot-password, protected route redirect.

bun run test:coverage writes an HTML report to coverage/.

The demo suite in e2e/demo/ is deliberately not part of this. It shares Playwright but exists to record the GIFs above, so it's slow by design (slowMo, dwell beats), needs seeded fixtures, and never runs in CI.

📦 Data model & Provisioning

Stored in Appwrite TablesDB (see docs/appwrite-schema.md for full schema details):

Table Holds
tasks Mission cards posted by NGOs (title, tags, time estimate, deadline, status, isVerified)
claims Volunteer submissions for tasks (proofUrl, notes, status: pending / approved / rejected)
badges Awarded badge instances (userId, taskId, label, color)
badgeDefinitions Org-owned badge templates (orgId, label, criteria, taskId for task-specific)
ngoVerifications Verification queue (orgName, country, taxId, docFileId, status, reason)

Plus three Appwrite Teams (volunteers, ngos, admins) for role + moderation gating. Storage is one bucket with file-level permissions for both avatars and verification docs. To automatically provision the database tables, attributes, and storage buckets:

bun scripts/setup-appwrite.ts

📝 Documentation

📜 License

MIT — see LICENSE.

About

A micro-volunteering marketplace pairing NGOs with volunteers for bite-sized, skill-building tasks. SvelteKit + Appwrite.

Topics

Resources

Contributing

Stars

Watchers

Forks

Contributors

Languages