App platform project

This is a project to build an app platform for charities and voluntary organisations. There is an API available.

A growing platform

7 Organisations
34 Apps
8 Categories

SpotTheSplat Apps

Modular apps for clubs, charities, and community organisations. Each app installs as a WordPress plugin with a simple shortcode.

Core

Sign In

Public

A centralised sign-in page with three provider buttons: Google (server-side OAuth), Apple (via Sign in with Apple web flow), and Facebook (greyed out, coming soon). All three buttons are equal size. Apple Hide-My-Email users are guided through a link-your-account email verification flow. Protected plugins redirect here when no session exists.

  • Google Sign-In
  • Apple Sign-In with Hide-My-Email support
  • Facebook (coming soon)
  • Centralised sign-in for all plugins
[sts_sign_in]
Get Started

Member-Only Content

Members only

A general-purpose content gate. Wrap any HTML, text, images, or other shortcodes between [sts_member_only]...[/sts_member_only] and only signed-in SpotTheSplat members will see it. Non-members see the standard sign-in card. Provided by the Members plugin from v1.6.0 onwards. Optional attributes heading="..." and subheading="..." customise the sign-in card. Inner content can include other shortcodes (e.g. wrap [my_account] or [club_calendar] to gate them on a custom page).

  • Wraps any WordPress content
  • Inner shortcodes still work
  • Customisable sign-in card heading
  • Same SSO session as all other gated plugins
  • No extra plugin to install—ships with Members v1.6.0
[sts_member_only]
Get Started

Member Dashboard

Members only

One shortcode, [my_dashboard], renders a Hi <first-name> greeting, the org name, optional photo, and a tile grid showing this member's relevant signals: open notices, future events, breakfast booking status (your choice if you've booked, 'Not booked in' if you haven't), recycle items available across the community, open borrow requests, and so on. Tiles are server-side and registered per-app via a `dashboard_tile.py` module — when a new app ships, its tile appears automatically without touching the dashboard plugin. Tiles auto-skip when the count is zero (so a tenant that doesn't run breakfast events doesn't see a breakfast tile). Status pill on tiles that warrant attention (warn / alert / ok). Place on a Members-only page that visitors land on after sign-in.

  • Per-tenant — tiles only appear for apps the org has installed
  • Auto-discovery — new apps appear without dashboard code changes
  • Personalised greeting with name + member photo
  • Status pills (e.g. 'Not booked in' for breakfast)
  • Members-only, fail-CLOSED on missing Members plugin
  • Single shortcode, drop-on-any-page
[my_dashboard]
Get Started

Members Directory

Members only

A searchable member directory with name, email, mobile, and member type. Protected by Google SSO — only registered members can view the directory. Provides the shared SSO authentication session used by all other member-only plugins.

  • Google SSO authentication
  • Searchable table
  • Mobile number support
  • Shared SSO session for all apps
[members_directory]
Get Started

My Account

Members only

Members-only self-service profile page. Members can view and edit their first/last name, mobile, alternative email, address (with UK county dropdown), partner details (name, email, phone, photo, dietary requirements), and their own profile photo. Email is read-only. Same data is also editable in the SpotTheSplat mobile app.

  • Profile photo upload
  • UK county dropdown for address
  • Partner section with photo
  • Dietary requirements
  • Mirrored on the iOS app
  • Same backend as Django admin
[my_account]
Get Started

API Documentation

Public

Displays the full API documentation fetched live from the platform. Automatically updates when endpoints are added or changed. Interactive expandable endpoint details with parameter tables.

  • Auto-updating from API
  • Interactive endpoint details
  • Parameter documentation
  • No manual updates needed
[api_docs]
Get Started

App Store

Public

Displays a catalogue of all available apps with descriptions, features, access levels, and shortcodes. Managed from Django admin — add, edit, or reorder apps without code changes.

  • Managed from Django admin
  • Grouped by category
  • Feature lists
  • Responsive grid layout
[app_store]
Get Started

Audit Logs

Members only

Two-tabbed audit log viewer: Action Logs shows sign-ins, page views, and connections with colour-coded badges. Change Logs shows model-level create/update/delete with field-level old-to-new diffs. Member Access shortcode shows a table of all members with Web, iOS, Android, and Accessed columns with tick/cross marks and footer totals. Restricted to admin and global_admin roles.

  • Action log with colour badges
  • Model change log with field diffs
  • Member platform access table
  • Pagination
  • Admin-only access
  • Per-org data isolation
[audit_logs org="<id>"] and [member_access org="<id>"]
Get Started

Visitor Stats

Members only

Server-side WordPress tracker plus an admin-only [club_stats] dashboard with daily timeseries chart, top pages, top referrers, and member vs guest split. IPs are hashed (no PII), bots filtered, no third-party services. Restricted to admin and global_admin roles.

  • Server-side tracking (no JS, no cookies)
  • Hashed IP for privacy
  • Member vs guest split
  • Top pages and referrers
  • Daily Chart.js timeseries
  • Bot filtering
  • Admin-only access
[club_stats]
Get Started

Platform Documentation

Members only

A WordPress plugin that renders the platform documentation HTML inline on a WP page. Access is granted by the Membership.can_view_platform_docs flag, which is independent of which organisation a member belongs to. Use to share platform docs with select people across multiple tenants.

  • Cross-org access
  • Per-member opt-in via Django admin
  • Always serves the latest docs HTML from the platform
[platform_docs]
Get Started

Courses

Members only

Deliver YouTube-hosted training courses to your members. Each course has lessons released on a configurable drip-feed schedule (default 7 days between lessons; set to 0 for immediate access to all lessons). Members track their progress, and on completion a personalised PDF certificate is generated automatically.

  • YouTube-hosted lesson videos
  • Configurable drip-feed (per course)
  • Per-lesson completion tracking
  • Automatic PDF certificate on course completion
  • Course catalogue + single-course player shortcodes
  • Member sign-in gate (shared with members plugin)
[course_catalogue] / [course course="<slug>"]
Get Started

Platform Health

Configurable

Daily polling of every third-party service the platform depends on. Each card shows the latest reading, a 30-day sparkline, last-poll status, and a percentage bar against the provider's quota where one applies (e.g. 3000 emails/month on Resend free tier, 10 GB on R2, 0.5 GB on Neon free tier). Lets you spot quota exhaustion or runaway usage weeks before billing alerts hit. Polled by a daily Fly cron machine; metrics are kept at full daily fidelity for 90 days then thinned to one snapshot per month.

  • 7 providers polled daily (Resend, FCM, R2, Stripe, Fly, Neon, QBO)
  • Per-card 30-day sparklines (Chart.js)
  • Quota % bars with warn/crit colour states
  • Last-poll status badge + on-error message
  • 'Poll now' button per provider in Django admin
  • API endpoint mirrored as a WP shortcode for off-platform viewing
  • Pluggable adapter framework — new providers = one new file
[platform_health]
Get Started

Compliance (DSAR)

Configurable

End-to-end Data Subject Access Request workflow: public submission form (logged-in members get a fresh-SSO short-circuit; email-only requesters go through HMAC-signed magic-link plus exact last-name + UK postcode), cross-tenant DPO dashboard with deep links to Django admin, three artefacts per bundle (WeasyPrint PDF + JSON + ZIP including binary contributions), automated third-party PII redaction (UK GDPR Art. 15(4)), 30-day R2 bundle expiry with nightly purge cron, and per-app PII registry covering 11 modules. Repeat requests within 12 months attract a fee per ICO/regulator guidance — currency + amount adapts per jurisdiction. Plus public-facing Privacy Notice (Art. 13/14) and Cookies Notice (PECR / GDPR / UAE PDPL / India DPDP) generators with three-button consent banner (Accept all / Reject non-essential / Customise). Includes a 7-article DPO User Guide and an ISO/IEC 27001:2022 Annex A control mapping.

  • Public DSAR submission form
  • Three-tier identity verification (fresh SSO / magic link / manual callback)
  • Cross-tenant DPO queue
  • Bundle PDF + JSON + ZIP
  • Third-party PII redaction with counter on cover
  • Right to erasure + portability
  • Per-jurisdiction repeat-fee plumbing (UK / UAE / Oman / India)
  • Nightly R2 bundle purge
  • Re-issue command
  • Privacy Notice generator with regulator-aware closing
  • Cookies Notice + three-button consent banner with audit log
  • Per-tenant additions for tenant-installed analytics cookies
  • DPO User Guide audience
  • ISO 27001 Annex A control mapping
[dsar_request], [dsar_status], [dpo_dashboard], [privacy_notice], [cookies_policy], [cookies_banner]
Get Started

Document Library

Members only

A per-tenant document library with a tree of folders, drag-drop upload, soft check-out / check-in, and full version history. Files live in Cloudflare R2 under a per-tenant key prefix. Default 10 GB quota per tenant (free); pay only above that. Office files preview inline via Microsoft Office Online (no Microsoft account needed for viewing). Every download, upload, check-out, release and admin action is logged to a member-attributable audit table. Folder-level permissions via MemberGroup with inheritance down the tree.

  • Per-tenant 10 GB free quota with soft warn / hard block
  • Folder tree (max depth 5) with breadcrumb navigation
  • Soft check-out with configurable due date (default 7 days)
  • Full version history — uploads never overwrite
  • Inline preview for Office docs via Office Online
  • Folder-level group restrictions with inheritance
  • Soft-delete with 30-day trash before hard-delete
  • Member-attributable audit log
  • Storage backend escape hatch: link to Drive / Dropbox per document
[document_library]
Get Started

Administration

Members only

A members-only landing page for club secretaries with one-click links to add notices, events, members, breakfast events, and manage the calendar. Mirrors the /admin/administration/ page in Django admin so the same tile layout works whether the secretary is browsing on the WordPress site or the Django admin directly. Admin / global_admin only.

  • Five quick-action tiles (Notices, Events, Members, Breakfast, Calendar)
  • Each tile has primary + secondary buttons (e.g. Add / View all)
  • Members-only gate with admin / global_admin role check
  • Mirrors the /admin/administration/ Django page
[administration]
Get Started

Boards

Members only

Tenant-scoped task boards with per-board owner / member rosters. Each board has columns (buckets) and cards (tasks); drag a card between columns to update its position and column. Tasks carry priority (low/medium/high/urgent), status (Not started / In progress / Completed), 0–100% progress, optional due date, free-form colour-coded labels, a checklist, multi-assignee, and a comment thread. Status drives auto-stamping: Completed snaps progress to 100% and timestamps completion; Not started zeroes progress. Three shortcodes: [boards] picker, [board plan="<id>"] kanban, [boards_admin] admin. Members-only via the SpotTheSplat Members plugin; cross-tenant access is refused. Skipped from v1 (configurable later): file attachments, email/push notifications, mobile screen.

  • Drag-and-drop between columns
  • Owner / Member rosters per board
  • Status auto-stamp + completed-at timestamp
  • 0–100% progress with auto-clamp by status
  • Multi-assign from any tenant member
  • Free-form colour-coded labels
  • Checklist + comments per card
  • Default 3 starter columns on new boards
  • Tenant-scoped, fail-CLOSED on missing Members plugin
[boards], [board plan="<id>"], [boards_admin]
Get Started

Borrowers

Members only

Two shortcodes. [borrow_request] is a form: pre-filled requester name from the signed-in member, fields for what you want to borrow (e.g. trailer, drill, stepladder), a description, and start + end dates and times. [borrow_list] is the board: every request for the tenant, sorted by start date ascending, with status (open / matched / cancelled), the requester's name, and — once a fellow member clicks 'Lend this' — the lender's name plus any note they left. Tenant-scoped via the Members plugin. Self-lending is blocked. Past-dated requests refused. The lender's name + comments are stored on the row so the requester sees them in the table; the requester can cancel (which clears any match) any time before the date.

  • Per-tenant board (no cross-tenant leakage)
  • Pre-filled requester name from signed-in member
  • Start + end date/time fields
  • One-click 'Lend this' for other members
  • Lender records name + optional comments
  • Requester can cancel (clears match)
  • Sortable board, soonest-first
  • Status pill (open / matched / cancelled)
  • Members-only, fail-CLOSED on missing Members plugin
[borrow_request], [borrow_list]
Get Started

Recycle

Members only

Three shortcodes. [recycle_donate] is the donor form: photo upload + item name + description. [recycle_list] is the board of available items (most recent first); other members click 'Apply' with an optional message; the donor sees the applications inline on their own row and clicks Approve / Reject for each. Approving auto-rejects every other pending application on that listing and flips the row to 'Promised'. [recycle_my_applications] is a recipient-side view of the requests they've made and their status. Privacy: non-donor viewers only see their OWN application on a listing — they don't see who else applied. Self-application is blocked. Donor can withdraw at any time (auto-rejects pending applications). Photo stored on the platform's media volume; included in the daily backup.

  • Photo upload (one per listing, JPG/PNG/HEIC)
  • Pre-filled donor name from signed-in member
  • One-click 'Apply' for other members with optional message
  • Donor inline approve / reject panel
  • Auto-rejects rivals on approval
  • Status pill (available / promised / collected / withdrawn)
  • Recipient privacy — only the donor sees the full applicant list
  • Self-application blocked
  • Members-only, fail-CLOSED on missing Members plugin
[recycle_donate], [recycle_list], [recycle_my_applications]
Get Started

Photo Folders

Members only

Single shortcode [photo_gallery]. Admins create a named folder, optionally credit an originator (member who ran the event — display label only) and link the folder to an event. Bulk multi-photo upload with EXIF stripped + auto-rotated + thumbnailed server-side; originals capped at 4MP, thumbs at 600px. Photos stored in a per-tenant prefix on Cloudflare R2 (separate bucket from the document library). Shortcode UI: top filter row picks Folder OR Event, default view is the grid of folder tiles, click drills into the per-folder grid → click a thumb opens a lightbox with download. Admin-only delete (soft, 30-day grace).

  • Bulk multi-photo upload
  • Folder linked to one event (past or future)
  • EXIF stripped on upload (member privacy)
  • Auto-rotation + thumbnail at 600px
  • Per-tenant R2 prefix; signed URLs with 1-hour TTL
  • Folder + Event filter on the gallery
  • Lightbox preview with original-size download
  • Admin-only edit and delete; 30-day soft-delete grace
  • Members-only, fail-CLOSED on missing Members plugin
[photo_gallery]
Get Started

Governance

Leadership Team

Members only

Shows the members of a named group (e.g. Council) along with their positions for a selected year. Members are sorted by position display order. Includes a year picker to view past and future year assignments. Requires the SpotTheSplat Members plugin for sign-in.

  • Position-based member listing
  • Year picker dropdown
  • Automatic from position assignments
  • Sorted by display order
[club_leadership group="<id>" title="Club Council"]
Get Started

Club Committees

Members only

Lists every active group for the organisation (Council, Club Service, Community Service, etc.), each with a heading and a table showing Position, Name, Email, and Mobile. Groups are ordered by display_order. Members within each group are sorted by their position's display_order, then alphabetically by last name. Includes a year picker.

  • All groups in one view
  • Configurable group order
  • Position-based member sorting
  • Year picker dropdown
[club_committees title="Club Committees" org="<id>"]
Get Started

Directory

Charities & Funders

Public

A searchable directory of charities and grant funders. Includes Charity Commission registration data, income figures, contact details, and tags. Tabbed view with category filtering. Data shared across organisations by UK county. Pre-filter to a single tag and county with [charities_directory tag="anxiety" county="national"].

  • Charities and Funders tabs
  • Search and category filter
  • Charity Commission data
  • Income figures
  • County-based data sharing
  • Tag + county pre-filter via shortcode attributes
[charities_directory]
Get Started

Link Library

Public

Drop a curated link library on any page via [link_library] (all groups) or [link_library group="UK guidelines"] (one group). Tenants manage groups + links via the Django admin Links Library section; both have sort_order fields for editorial control. Useful for reading lists, member resources, or supplier directories.

  • Group + link sort_order in Django admin
  • Per-group shortcode filter
  • Auto-styled cards with platform blue accent
  • Per-org API key scoped
[link_library]
Get Started

Furniture Inventory

Public

Searchable, paginated grid of donated furniture items. Each item shows photo, category, condition, and a click-through detail card with full description, dimensions, and damage notes. Backed by a Django inventory the lead person manages from admin or the mobile app.

  • Multiple photos per item
  • 23 furniture categories
  • Search + category filter
  • Detail modal with all photos
  • Lifecycle status tracking
[furniture_inventory org="<id>"]
Get Started

Furniture Deliveries

Members only

Manage Recipients (with vulnerability flag and referring charity), schedule Deliveries with date/time/notes, and pick which inventory items go on each delivery. Status changes (out for delivery, delivered, cancelled) automatically update the linked items. Repeat customers detected via delivery history.

  • Recipient model — repeat customers tracked
  • Vulnerability flag
  • Referring charity FK or Other freeform
  • Multi-item picker per delivery
  • Auto status sync to inventory items
  • Mobile app + Django admin parity
Get Started

Communications

Notices Board

Configurable

A notice board for announcements and events. Each notice has a title, description, date, price, contact details, and website link. Notices have configurable visibility windows (start/end dates). QR codes are auto-generated for notice website links. Compact homepage widget via [notices_titles limit="5" link_to="/notices/"] — renders just the titles of currently-active public notices, each deep-linking to its card on the board page.

  • Date-ranged visibility
  • Contact details
  • Website links
  • Public or members-only access
  • [notices_titles] homepage teaser widget
[notices_board]
Get Started

Social Media

Members only

Designated Social Manager role per tenant (set the is_social_manager flag on a Membership; admins always pass). Per-tenant OAuth credentials, encrypted at rest. Two shortcodes: [social_compose] shows a channel-connection panel + compose form (text + per-channel checkboxes filtered to connected-only) with inline posted/partial/failed feedback; [social_history] is a read-only table of the last 50 posts with per-channel tick-or-cross status. LinkedIn live in v1 (personal-mode by default; flips to Company-Page mode via a Fly secret toggle once LinkedIn Marketing Developer Platform / Community Management API approval lands). Facebook + Instagram pending Meta App Review — channel rows render as 'Coming once Meta App Review approves the app' until the approval lands, then no plugin update is needed; the backend adapters wire up automatically.

  • Per-tenant OAuth credentials (encrypted)
  • Compose-once, fan-out to multiple channels
  • Per-channel result tracking + history log
  • Designated Social Manager role per tenant
  • LinkedIn personal-timeline mode (no LinkedIn approval needed)
  • LinkedIn Company Page mode (gated on Marketing Developer Platform approval)
  • Facebook + Instagram pending Meta App Review
  • Status pills + per-channel error messages on failure
[social_compose], [social_history]
Get Started

Events

Club Calendar

Configurable

Displays events from your existing ICS calendar feed as a monthly grid with an upcoming events list. Supports any iCal-compatible calendar (Google Calendar, Apple Calendar, Outlook, etc.).

  • Monthly grid view
  • Upcoming events list
  • Month navigation
  • ICS feed integration
  • Public or members-only access
[club_calendar]
Get Started

Events

Configurable

Create and display events with date, time, location, description, and website links. Includes interactive maps and QR codes. Each event can be set as public or members-only.

  • Interactive OpenStreetMap
  • QR codes for event websites
  • Per-event access control
  • Google Maps link
[events_listing]
Get Started

Attendance

Breakfast RSVP

Members only

Breakfast meeting RSVP system. Members select their breakfast choice, optionally add a guest, and can change their selection until the booking deadline. Generates attendance reports with summary statistics.

  • 5 breakfast choices
  • Guest bookings
  • Change until deadline
  • Attendance reports
[breakfast_rsvp]
Get Started

Finance

Alpaca Portfolio

Members only

Displays an Alpaca trading portfolio for a club activity: account summary (equity, cash, buying power), intraday portfolio value chart (Chart.js), open positions table, and recent orders. Data is server-cached for 5 minutes. Supports per-member access control via ActivityMemberAccess and ActivityGroupAccess.

  • Account summary cards
  • Intraday portfolio chart
  • Open positions table
  • Recent orders
  • 5-minute server cache
  • Per-member access control
  • Paper and live account support
[alpaca_portfolio activity="<id>"]
Get Started

Club Finance (QuickBooks)

Members only

Connects to a QuickBooks Online company via OAuth2 and displays bank account balances with totals and a simplified balance sheet (one level deep). Data is server-cached for 5 minutes. Each organisation connects their own QBO company — credentials are managed in Django admin.

  • Bank account balances
  • Simplified balance sheet
  • QuickBooks OAuth2 connection
  • 5-minute server cache
  • UK chart of accounts support
  • Auto token refresh
[club_finance org="<id>"]
Get Started

Games

Spot The Splat

Public

Public-facing fundraiser. The club marks an area on a map and overlays a grid of squares (e.g. 20x20 = 400 squares). Anyone can buy a square through Stripe Checkout. After the splat event, the club declares the winning square in Django admin and the buyer is announced. Each club uses its own Stripe Connect account so funds settle directly with them.

  • OpenStreetMap with grid overlay
  • Anonymous purchases
  • Stripe Checkout (no card data on our servers)
  • Per-club Stripe Connect account
  • 10-min soft reservations
  • Live availability counters
  • Winner declared in Django admin
[spot_the_splat activity="<id>"]
Get Started

Duck Race

Public

Run a numbered-duck race fundraiser end-to-end. Buyers pick a duck number on a live grid (taken numbers display a yellow rubber-duck graphic) and pay through Stripe Checkout. The prize pot is a configurable percentage of gross ticket revenue (default 25%) split between 1st, 2nd and 3rd place using a configurable ratio (default 4:2:1). On race day, an admin enters the three winning duck numbers — the system validates that all three were paid and forces a redraw if any were unsold. Reuses the platform's Stripe Connect Express layer so funds settle directly to the club's connected account.

  • Configurable per-race: total ducks, price, prize pot %, 1st/2nd/3rd ratio
  • Buyer-picks numbered duck grid with yellow-duck graphic on taken slots
  • 10-minute soft reservations during checkout
  • Live prize-pot widget that grows as tickets sell
  • Three-winner declaration with redraw enforcement on unpaid ducks
  • Race-day photo upload for the post-race podium
  • Stripe Connect — funds go straight to the club's connected account
[duck_race race="<id>"]
Get Started