Social Income

Fighting global poverty with the help of everyday people and your coding skills.
https://github.com/socialincome-san/public

Category: Sustainable Development
Sub Category: Population and Poverty

Keywords

css firebase firestore open-source opensourceforgood react storybook vite

Keywords from Contributors

measur archiving optimize transforms projection productivity generic compose observation animals

Last synced: about 21 hours ago
JSON representation

Repository metadata

Fighting global poverty with the help of everyday people and your coding skills. Public repository of the NGO and global initiative Social Income.

README.md

Social Income

#Tech4Good   #OpenSource   #Solidarity

Social Income Logo

Social Income is a radically simple solution in the fight against poverty.
The open-source initiative converts donations into an unconditional basic
income, sent directly to the mobile phones of people living in poverty in the
Global South.

https://user-images.githubusercontent.com/6095849/191377786-10cdb4a1-5b25-4512-ade9-2cc0e153d947.mp4

What Is In This Repository?

This repository contains the public website, internal tools, local development
seed data, infrastructure code, and the recipient mobile app.

/
├─ recipients_app/        Mobile app for Social Income recipients
├─ seed/                  Firebase emulator seed data
└─ website/               Next.js app, APIs, database, infra, and tests

website/

The main Next.js application. It contains:

  • Public website: the public Social Income website. Parts are still hardcoded,
    while more content is being moved to Storyblok CMS.
  • Portal: internal operations tool for program management, payments,
    recipients, contributors, and admin functionality.
  • Dashboard: contributor self-service area for payments, subscriptions, and
    personal details.
  • Partner Space: local partner self-service area for recipients, candidates,
    and partner profile data.
  • API routes: backend endpoints used by the website and the recipient mobile
    app.
  • Database layer: Prisma ORM with PostgreSQL.
  • Infrastructure: Terraform configuration under website/infra.
  • Tests: unit tests and Playwright end-to-end tests.

recipients_app/

Mobile app for recipients. Recipients can log in, view payment history, and
complete surveys. See recipients_app/README.md for mobile setup details.

seed/

Seed data for the local Firebase emulators. Firebase Auth users are imported
automatically when the local development environment starts.

Local Development Setup

Requirements

Install these tools before starting:

  • mise
  • Docker
  • Node.js and npm through mise

On macOS, install mise with:

brew install mise

1. Install Tool Versions And Dependencies

cd website
mise install
npm ci

The web app keeps its Node dependencies, mise tasks, formatting config, Prisma
setup, and most local tooling inside website/.

2. Prepare Environment Variables

Copy the local env template:

cd website
cp .env.local.sample .env.local

For most external contributors, the only required CMS value is:

STORYBLOK_PREVIEW_TOKEN="<public-content-delivery-api-token>"

Despite the name, STORYBLOK_PREVIEW_TOKEN is used by the website to load
Storyblok content through the Content Delivery API. A public token is enough
for frontend and UI work against published content.

If you need this token, ask a maintainer or contact
support@socialincome.org. Do not commit real API keys or secrets.

Maintainers may also need these Storyblok values for preview mode, webhooks,
or schema/type generation:

  • STORYBLOK_PREVIEW_SECRET
  • STORYBLOK_WEBHOOK_SECRET
  • STORYBLOK_PERSONAL_ACCESS_TOKEN
  • STORYBLOK_SPACE_ID

3. Start The Local Environment

cd website
mise dev

This starts:

  • PostgreSQL in Docker
  • Firebase emulators for Auth and Firestore
  • Next.js at http://localhost:3000
  • Storybook at http://localhost:6006

We use Storybook for reusable website UI components. It is started locally by
mise dev and is available on staging and production at
https://staging.socialincome.org/storybook and
https://socialincome.org/storybook.

The Firebase emulator UI is available at:

http://localhost:4000

Auth users can be inspected at:

http://localhost:4000/auth

4. Seed The Local Database

Firebase Auth users are imported automatically from seed/auth_export when
the emulator starts. The PostgreSQL database needs to be seeded once manually:

cd website
npm run db:seed

This fills the local database with representative test data from
website/src/lib/database/seed.

Local Login

Open the website at:

http://localhost:3000

Click Login in the top navigation and enter one of these local test users:

Area Purpose Email
Portal Internal operations and admin tool power@portal.test
Dashboard Contributor self-service area coreh@dashboard.test
Partner Space Local partner self-service area sl@partner.test

In staging and production, login sends a magic link by email. Locally, the
Firebase emulator logs the magic link instead. Copy it from the terminal
running mise dev, or open:

http://localhost:4000/logs

Development Flow

The main integration branch for active development is main.

  1. Create your feature branch from main.
  2. Keep your changes focused on one issue or feature.
  3. Run the relevant checks locally.
  4. Open a pull request back into main.
  5. Wait for CI and review.

Example:

git checkout main
git pull
git checkout -b fix/issue-2064-short-description

Website checks run for pull requests and for pushes to main.
Staging deployment is connected to main; production releases are handled
by maintainers.

Useful local checks for website changes:

cd website
npm run lint
npm run typecheck
npm run test:unit
npm run test:e2e

For many small UI or content changes, lint and typecheck are a good
minimum before opening a PR. Run the broader test suite when touching shared
logic, authentication, database behavior, or user flows.

Storyblok Development

We use Storyblok as CMS for parts of the
public website.

For normal local development, set the public Content Delivery API token in
website/.env.local:

STORYBLOK_PREVIEW_TOKEN="<public-content-delivery-api-token>"

Use local HTTPS if you are working with Storyblok live preview:

cd website
mise run dev-ssl

Storyblok Type Generation

If you changed the Storyblok schema, regenerate the generated TypeScript
types. This requires maintainer-level Storyblok credentials:

cd website
npm run storyblok:generate

The command logs into Storyblok, pulls component schemas, and writes generated
types to website/src/generated/storyblok/types.

Anonymous Campaign Submissions

Visitors can submit campaigns from the public /campaigns page. Submissions:

  • create an inactive, non-public database Campaign with a server-generated slug
  • upload a primary image and create an unpublished Storyblok Campaign story
  • link database and CMS entries through Campaign.slugStoryblok.content.portalSlug

Publication happens manually in Storyblok. Published Storyblok stories are the
sole public visibility gate for campaign pages (detail load and overview join).

Public active vs inactive is derived from campaign end date and goal
progress (not the database isActive flag): a campaign is inactive when its
finish date has passed or its goal amount has been reached. The overview filter
and card linkability use that derived state; deep links to published stories
still work after a campaign becomes inactive.

Server-only configuration lives in
website/src/lib/config/campaign-submission.config.ts. Set the Management API
token in website/.env.local:

STORYBLOK_MANAGEMENT_TOKEN="<storyblok-personal-access-token>"

The token must be able to create draft stories under pages/campaigns and
upload assets in the configured asset folder. If a submission fails after partial
progress, the API attempts compensating cleanup of the created Storyblok asset,
Storyblok story, and database row.

Future hardening (not part of the first version): Cloudflare Turnstile and
distributed rate limiting on POST /api/campaign-submissions.

Mobile API

The recipients_app communicates with the Next.js API routes. The public API
documentation is available at:

https://socialincome.org/v1/api-docs

Troubleshooting

Translations Or Generated Content Look Stale

rm -rf website/.next
cd website
mise dev

Firebase Seed Data Did Not Update

The Firebase emulators load seed data from seed/. If you changed the seed
data and want a fresh start:

docker compose -f website/docker-compose.yml down --remove-orphans --volumes
cd website
mise dev

Docker Or Database State Looks Broken

If Prisma migrations fail, old containers are hanging around, or the local DB
is in a strange state, reset the website Docker environment:

docker compose -f website/docker-compose.yml down --remove-orphans --volumes

This removes the website Docker containers and named volumes, including local
PostgreSQL data. Run mise dev and npm run db:seed again afterwards.

E2E Checks Look Stuck

The Playwright CI job may update screenshots and commit them back into a PR.
That creates a new commit. GitHub sometimes does not start a fresh workflow
run for commits made by github-actions, so checks can appear stale even
though the previous run passed. Ask a maintainer if this happens.

Useful Commands

Database

cd website
npm run db:seed
npm run db:studio
npm run db:migrate:dev

Dump Local Database

pg_dump -Fc --no-owner "postgresql://social-income:social-income@localhost:5432/social-income" > local.dump

Restore A Dump

pg_restore --clean --if-exists --no-owner -d "<database-url>" local.dump

Financial Contributions

Become a contributor of Social
Income. Donations are tax-deductible in Switzerland.

Become a sponsor and help
build open-source software for more equality and less poverty. Donations
through the GitHub Sponsor program support the developer community.

Social Income NGO

Non-Profit Organization

Social Income is a non-profit association
(CHE-289.611.695)
based in Zurich, Switzerland. Connect with us on
X,
Instagram,
LinkedIn,
Facebook, or by
email.

Radical Transparency

We believe that transparency builds trust and trust builds solidarity. This is
why we disclose our
finances to the public.

Open Source Community

Open source is made by people like you. These individuals, among many others,
have contributed to Social Income:

Contributors

Software And IP Contributions

We receive in-kind donations from
Google Nonprofit,
GitHub,
Codemagic,
Linktree,
Twilio,
Algolia,
JetBrains,
Storyblok,
1Password,
Mux,
Sentry, and
Lineto. Our tools also use open-source technologies
such as FireCMS,
Storybook, and
Tailwind CSS.

License

This project is licensed under MIT, with the exception of the
Unica77 font, which is exclusively
licensed to Social Income.


Owner metadata


GitHub Events

Total
Last Year

Committers metadata

Last synced: 2 days ago

Total Commits: 1,843
Total Committers: 47
Avg Commits per committer: 39.213
Development Distribution Score (DDS): 0.848

Commits in past year: 869
Committers in past year: 23
Avg Commits per committer in past year: 37.783
Development Distribution Score (DDS) in past year: 0.685

Name Email Commits
Raphael Wirth 3****6 281
renovate[bot] 2****] 274
Michael Kündig m****l@s****g 233
Sandino Scheidegger s****o@s****g 225
Mikolaj m****w@g****m 134
András Heé a****e 94
Verena Zaiser d****t@v****e 89
fabricem90 f****e@s****h 83
Karin Berg K****g 67
PM 3****K 55
ManuM m****r@g****m 39
dependabot[bot] 4****] 34
René Stalder r****e@s****g 32
Nando Schär 1****2 26
Kevin Walker k****n@s****h 24
Pranav Chatur p****r@g****m 18
Marco Bohler t****o@g****m 14
Gavriil g****s@g****m 13
hashbot h****t@n****m 11
Cheryl Oberholzer c****r@g****h 8
Copilot 1****t 8
brennerthomas t****r@g****t 8
Social Income Dev 6****v 8
Michael Kündig m****l@c****o 7
Nhan Doan 2****n 6
Alexey Shestakov s****x@g****m 5
Anthony Reinette a****y 5
levi499 l****i@s****h 5
mdumond 4****d 5
Debajyoti Karmakar d****7@g****m 4
and 17 more...

Committer domains:


Issue and Pull Request metadata

Last synced: 2 days ago

Total issues: 294
Total pull requests: 852
Average time to close issues: 7 months
Average time to close pull requests: 8 days
Total issue authors: 21
Total pull request authors: 42
Average comments per issue: 0.97
Average comments per pull request: 1.87
Merged pull request: 612
Bot issues: 1
Bot pull requests: 165

Past year issues: 55
Past year pull requests: 193
Past year average time to close issues: 7 days
Past year average time to close pull requests: 2 days
Past year issue authors: 9
Past year pull request authors: 20
Past year average comments per issue: 0.45
Past year average comments per pull request: 0.73
Past year merged pull request: 135
Past year bot issues: 1
Past year bot pull requests: 96

More stats: https://issues.ecosyste.ms/repositories/lookup?url=https://github.com/socialincome-san/public

Top Issue Authors

  • ssandino (190)
  • rawi96 (30)
  • mkue (19)
  • novas1r1 (13)
  • KarinBerg (9)
  • andrashee (8)
  • renestalder (7)
  • triggertoo (4)
  • fabricem90 (2)
  • levi499 (1)
  • renovate[bot] (1)
  • kerrrin (1)
  • alphachart (1)
  • chojuninengu (1)
  • almsh (1)

Top Pull Request Authors

  • ssandino (196)
  • dependabot[bot] (87)
  • mkue (85)
  • renovate[bot] (78)
  • CluEleSsUK (72)
  • KarinBerg (57)
  • rawi96 (43)
  • andrashee (29)
  • DarkMenacer (24)
  • triggertoo (21)
  • novas1r1 (18)
  • Gavriil-Tzortzakis (16)
  • dnhn (14)
  • mdumond (10)
  • MDikkii (9)

Top Issue Labels

  • website (73)
  • feature (57)
  • admintool (40)
  • mobileapp (24)
  • flutter (20)
  • bug (19)
  • Website (17)
  • admin tool (17)
  • mobile (16)
  • Portal (13)
  • Help wanted (8)
  • longlist (6)
  • hacktoberfest (5)
  • Longlist (4)
  • surveys (4)
  • good first issue (4)
  • Good first issue (4)
  • help wanted (3)
  • Weekend (3)
  • Journal (2)
  • ui (2)
  • devop (2)
  • github dpg (2)
  • survey (2)
  • admin (1)
  • dependencies (1)
  • documentation (1)
  • Dependencies (1)
  • setup (1)

Top Pull Request Labels

  • javascript (82)
  • dependencies (76)
  • mobile (24)
  • website (22)
  • Dependencies (13)
  • feature (8)
  • mobileapp (7)
  • ui (4)
  • fundraisers (3)
  • Mobile (3)
  • flutter (2)
  • GitHub DPG (2)
  • surveys (1)

Dependencies

recipients_app/pubspec.lock pub
  • animations 2.0.2
  • args 2.3.0
  • asn1lib 1.1.0
  • async 2.8.2
  • boolean_selector 2.1.0
  • characters 1.2.0
  • charcode 1.3.1
  • clock 1.1.0
  • cloud_firestore 2.5.4
  • cloud_firestore_platform_interface 5.4.13
  • cloud_firestore_web 2.6.8
  • collection 1.16.0
  • convert 3.0.1
  • crypto 3.0.1
  • cupertino_icons 1.0.4
  • encrypt 5.0.1
  • equatable 2.0.3
  • fake_async 1.3.0
  • ffi 1.1.2
  • file 6.1.2
  • firebase 9.0.2
  • firebase_auth 1.4.1
  • firebase_auth_platform_interface 4.3.1
  • firebase_auth_web 1.3.1
  • firebase_core 1.12.0
  • firebase_core_platform_interface 4.2.4
  • firebase_core_web 1.5.4
  • firebase_database 6.1.2
  • flutter 0.0.0
  • flutter_page_indicator 0.0.3
  • flutter_swiper 1.1.6
  • flutter_test 0.0.0
  • flutter_web_plugins 0.0.0
  • http 0.13.4
  • http_parser 4.0.0
  • intl 0.17.0
  • intl_phone_number_input 0.7.0+2
  • js 0.6.4
  • libphonenumber 2.0.2
  • libphonenumber_platform_interface 0.3.1
  • libphonenumber_plugin 0.2.3
  • libphonenumber_web 0.2.0+1
  • matcher 0.12.11
  • material_color_utilities 0.1.4
  • menu_button 1.4.2+1
  • meta 1.7.0
  • nested 1.0.0
  • password_strength 0.2.0
  • path 1.8.1
  • path_provider_linux 2.1.5
  • path_provider_platform_interface 2.0.3
  • path_provider_windows 2.0.5
  • platform 3.1.0
  • plugin_platform_interface 2.1.2
  • pointycastle 3.5.1
  • process 4.2.4
  • provider 5.0.0
  • rounded_loading_button 2.1.0
  • rxdart 0.27.3
  • shared_preferences 2.0.13
  • shared_preferences_android 2.0.11
  • shared_preferences_ios 2.1.0
  • shared_preferences_linux 2.1.0
  • shared_preferences_macos 2.0.3
  • shared_preferences_platform_interface 2.0.0
  • shared_preferences_web 2.0.3
  • shared_preferences_windows 2.1.0
  • sky_engine 0.0.99
  • source_span 1.8.2
  • stack_trace 1.10.0
  • step_progress_indicator 1.0.2
  • stream_channel 2.1.0
  • string_scanner 1.1.0
  • term_glyph 1.2.0
  • test_api 0.4.9
  • transformer_page_view 0.1.6
  • typed_data 1.3.0
  • url_launcher 6.0.20
  • url_launcher_android 6.0.15
  • url_launcher_ios 6.0.15
  • url_launcher_linux 3.0.0
  • url_launcher_macos 3.0.0
  • url_launcher_platform_interface 2.0.5
  • url_launcher_web 2.0.9
  • url_launcher_windows 3.0.0
  • vector_math 2.1.2
  • webview_flutter 3.0.0
  • webview_flutter_android 2.8.3
  • webview_flutter_platform_interface 1.8.1
  • webview_flutter_wkwebview 2.7.1
  • win32 2.4.1
  • xdg_directories 0.2.0+1
recipients_app/pubspec.yaml pub
  • flutter_test --- !ruby/hash:ActiveSupport::HashWithIndifferentAccess sdk: flutter development
  • animations ^2.0.0
  • cloud_firestore ^2.2.0
  • cupertino_icons ^1.0.2
  • encrypt ^5.0.0
  • firebase ^9.0.1
  • firebase_auth ^1.3.0
  • firebase_core ^1.2.0
  • firebase_database ^6.1.2
  • flutter --- !ruby/hash:ActiveSupport::HashWithIndifferentAccess sdk: flutter
  • flutter_swiper ^1.1.6
  • intl ^0.17.0
  • intl_phone_number_input ^0.7.0+2
  • menu_button ^1.4.2+1
  • password_strength ^0.2.0
  • provider ^5.0.0
  • rounded_loading_button ^2.0.8
  • shared_preferences ^2.0.6
  • step_progress_indicator ^1.0.0
  • url_launcher ^6.0.20
  • webview_flutter ^3.0.0
.github/workflows/auto-approve-renovate.yml actions
.github/workflows/deploy-terraform-to-gcp-prod.yml actions
  • actions/checkout 9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 composite
  • google-github-actions/auth 7c6bc770dae815cd3e89ee6cdf493a5fab2cc093 composite
  • hashicorp/setup-terraform dfe3c3f87815947d99a8997f908cb6525fc44e9e composite
website/Dockerfile docker
  • base latest build
  • node 24-alpine@sha256 build
website/docker-compose.yml docker
  • postgres 18-alpine@sha256
.github/workflows/aikido-scan.yml actions
  • actions/checkout 9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 composite
.github/workflows/deploy-terraform-to-gcp-staging.yml actions
  • actions/checkout 9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 composite
  • google-github-actions/auth 7c6bc770dae815cd3e89ee6cdf493a5fab2cc093 composite
  • hashicorp/setup-terraform dfe3c3f87815947d99a8997f908cb6525fc44e9e composite
recipients_app/android/app/build.gradle.kts maven
recipients_app/android/build.gradle.kts maven
website/package-lock.json npm
.github/workflows/codeql-analysis.yml actions
  • actions/checkout v3 composite
  • github/codeql-action/analyze v2 composite
  • github/codeql-action/autobuild v2 composite
  • github/codeql-action/init v2 composite
.github/workflows/rules.yml actions
  • actions/checkout v2 composite
  • fkirc/skip-duplicate-actions v5 composite
.github/workflows/website.yml actions
  • actions/checkout v2 composite
  • fkirc/skip-duplicate-actions v5 composite
  • rossjrw/pr-preview-action v1 composite
website/package.json npm
  • @playwright/test ^1.30.0 development
  • @testing-library/jest-dom ^5.16.5 development
  • @testing-library/react ^13.4.0 development
  • i18next-parser ^7.6.0 development
  • isomorphic-fetch ^3.0.0 development
  • jest ^29.4.1 development
  • jest-environment-jsdom ^29.4.1 development
  • ts-mockito ^2.6.1 development
  • @socialincome/shared ^0.1.0
  • @types/node 18.11.9
  • @types/react 18.0.25
  • @types/react-dom 18.0.9
  • eslint 8.28.0
  • eslint-config-next 13.0.4
  • firebase-admin ^11.5.0
  • firebase-functions ^4.1.0
  • i18next ^22.4.9
  • next 13.0.4
  • next-i18next ^13.1.4
  • next-transpile-modules ^10.0.0
  • react 18.2.0
  • react-cookie ^4.1.1
  • react-dom 18.2.0
  • react-i18next ^12.1.5
  • typescript 4.9.3
.github/workflows/actions/init/action.yml actions
  • actions/setup-node v3 composite
  • jsdaniell/create-json v1.2.2 composite
.github/workflows/deployment.yml actions
  • ./.github/workflows/actions/init * composite
  • FirebaseExtended/action-hosting-deploy v0 composite
  • actions/checkout v3 composite
.github/workflows/production-deployment.yml actions
  • ./.github/workflows/actions/init * composite
  • actions/checkout v3 composite
recipients_app/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved swiftpm
  • github.com/GoogleCloudPlatform/recaptcha-enterprise-mobile-sdk 18.9.1
  • github.com/firebase/firebase-ios-sdk 12.15.0
  • github.com/firebase/leveldb 1.22.5
  • github.com/firebase/nanopb 2.30910.1
  • github.com/getsentry/sentry-cocoa 8.58.3
  • github.com/google/GoogleAppMeasurement 12.15.0
  • github.com/google/GoogleDataTransport 10.1.0
  • github.com/google/GoogleUtilities 8.1.1
  • github.com/google/abseil-cpp-binary 1.2024072200.0
  • github.com/google/app-check 11.3.0
  • github.com/google/grpc-binary 1.69.1
  • github.com/google/gtm-session-fetcher 5.3.0
  • github.com/google/interop-ios-for-google-sdks 101.0.0
  • github.com/google/promises 2.4.1
  • github.com/googleads/google-ads-on-device-conversion-ios-sdk 3.6.0
recipients_app/ios/Runner.xcworkspace/xcshareddata/swiftpm/Package.resolved swiftpm
  • github.com/GoogleCloudPlatform/recaptcha-enterprise-mobile-sdk 18.9.1
  • github.com/firebase/firebase-ios-sdk 12.15.0
  • github.com/firebase/leveldb 1.22.5
  • github.com/firebase/nanopb 2.30910.1
  • github.com/getsentry/sentry-cocoa 8.58.3
  • github.com/google/GoogleAppMeasurement 12.15.0
  • github.com/google/GoogleDataTransport 10.1.0
  • github.com/google/GoogleUtilities 8.1.1
  • github.com/google/abseil-cpp-binary 1.2024072200.0
  • github.com/google/app-check 11.3.0
  • github.com/google/grpc-binary 1.69.1
  • github.com/google/gtm-session-fetcher 5.3.0
  • github.com/google/interop-ios-for-google-sdks 101.0.0
  • github.com/google/promises 2.4.1
  • github.com/googleads/google-ads-on-device-conversion-ios-sdk 3.6.0

Score: 9.55393007636626