No description
  • JavaScript 81.4%
  • Nunjucks 18.6%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Ricardo 7492848232 feat: donation-campaign v2 block + public hardened stats API (v0.1.0-alpha.4)
- get blocks(): donation-campaign entry (source:api, bespoke, main region,
  homepage/standalone, multiple; config: campaignId picker + title)
- stats.json + stats/:campaignId.json moved from admin routes to
  routesPublic (spec: block fetches client-side), rate-limited 60/min/IP
- security-review hardening: dropped per-donation records from the public
  payload (aggregates only); byCampaign 404s hidden/unknown campaigns;
  opaque 500s instead of the stack-including core error handler; 30s
  in-process payload cache; trustProxy validation silenced (topology
  reviewed)
- tests: block contract + sanitization/route-placement regressions
2026-07-24 20:22:32 +02:00
lib feat: donation-campaign v2 block + public hardened stats API (v0.1.0-alpha.4) 2026-07-24 20:22:32 +02:00
locales initial: import @rmdes/indiekit-endpoint-donation source + layout fix to v0.1.0-alpha.3 2026-06-02 18:24:49 +02:00
tests feat: donation-campaign v2 block + public hardened stats API (v0.1.0-alpha.4) 2026-07-24 20:22:32 +02:00
views initial: import @rmdes/indiekit-endpoint-donation source + layout fix to v0.1.0-alpha.3 2026-06-02 18:24:49 +02:00
.gitignore initial: import @rmdes/indiekit-endpoint-donation source + layout fix to v0.1.0-alpha.3 2026-06-02 18:24:49 +02:00
CLAUDE.md feat: donation-campaign v2 block + public hardened stats API (v0.1.0-alpha.4) 2026-07-24 20:22:32 +02:00
index.js feat: donation-campaign v2 block + public hardened stats API (v0.1.0-alpha.4) 2026-07-24 20:22:32 +02:00
package-lock.json initial: import @rmdes/indiekit-endpoint-donation source + layout fix to v0.1.0-alpha.3 2026-06-02 18:24:49 +02:00
package.json feat: donation-campaign v2 block + public hardened stats API (v0.1.0-alpha.4) 2026-07-24 20:22:32 +02:00
README.md docs: update status, deployment context, and version policy 2026-06-10 22:16:06 +02:00

@rmdes/indiekit-endpoint-donation

Stripe-backed donation endpoint for Indiekit. Treats Stripe Products as campaigns, Stripe Checkout Sessions / PaymentIntents as donations, captures donor consent via Stripe Payment Link custom fields, and feeds a static Eleventy site with live JSON + rebuild triggers.

Status

Alpha. Scaffold implemented with routes, views, webhook verification, sync scheduling, and MongoDB storage. Deployed on chardonsbleus (see package.json for version). See CLAUDE.md for architecture, data model, and routes.

Maturity note: Version 0.1.0-alpha.x — API may shift before 1.0.0.

Install

npm install @rmdes/indiekit-endpoint-donation stripe
// indiekit.config.js
import DonationEndpoint from "@rmdes/indiekit-endpoint-donation";

export default {
  plugins: [
    "@indiekit/endpoint-auth",
    new DonationEndpoint({
      mountPath: "/donation",
      // siteDir + rebuildTrigger usually picked up from env vars
    }),
    // ...
  ],
};

Environment

STRIPE_SECRET_KEY=sk_live_…
STRIPE_WEBHOOK_SECRET=whsec_…
INDIEKIT_DONATION_SITE_DIR=/app/data/eleventy-site
INDIEKIT_DONATION_REBUILD_TRIGGER=/app/data/eleventy-site/.rebuild-trigger
INDIEKIT_DONATION_CURRENCY=EUR

Stripe setup (one-time)

  1. Create a Product per campaign in Stripe Dashboard. Set product metadata: goal_cents, subtitle, campaign_starts, campaign_ends, display_order.
  2. Create a Payment Link for each Product. Add 3 custom fields:
    • consent — dropdown: "Oui, avec mon nom" / "Oui, anonymement" / "Non, garder privé" (required)
    • display_name — text, optional (≤60 chars)
    • message — text, optional (≤200 chars)
  3. Create a Webhook endpoint in Stripe pointing at https://yoursite.example/donation/webhook. Subscribe to:
    • checkout.session.completed
    • checkout.session.async_payment_succeeded
    • invoice.paid
    • charge.refunded
  4. Copy the webhook signing secret (whsec_…) into STRIPE_WEBHOOK_SECRET.

Admin UI

  • /donation — dashboard (lifetime stats, recent donations, active campaigns)
  • /donation/donations — full donation list with filters
  • /donation/donations/:id — edit a single donation (display name, message, consent)
  • /donation/campaigns — cached campaign list (synced from Stripe)
  • /donation/manual — record an offline donation (cash, bank transfer)
  • POST /donation/sync — trigger an immediate Stripe Product sync
  • POST /donation/rebuild — touch the rebuild trigger file

Public API

  • GET /donation/stats.json — full live state (campaigns + recent donations, donor names hidden if consent is false). Cache-Control: 60s.
  • GET /donation/stats/:campaignId.json — single-campaign totals.
  • POST /donation/webhook — Stripe webhook receiver (rejects without signature).

Plugin Origin

ORIGINAL plugin — no upstream @indiekit/* equivalent. Developed for chardonsbleus fundraising campaigns.

Registry status: Endpoints tier in indiekit-cloudron — optional, deployed only on chardonsbleus.

License

MIT