A prototype for identifying lending opportunities from hyperlocal map data. The idea is to put loan demand and supply on a map, so that opportunities can be assessed geographically rather than only from an application form.
Two independent pieces plus design documentation:
| Directory | What it is |
|---|---|
GeoCapital/ |
METX — the mobile client. Expo / React Native, TypeScript, with Mapbox maps and expo-router navigation. |
surfin/ |
the backend. Go 1.24 with Gin, PostgreSQL via sqlc, JWT auth, and generated Swagger docs. |
docs/ |
an SRS, an MVP plan, and UML diagrams — use case, DFD, DDD, component, deployment and loan sequence — plus the Postgres schema in database.sql. |
This is early-stage work, not a product. docs/mvp.md is a task breakdown
with time estimates, which is a fair signal of how far along it is.
Credentials have been removed from this repository.
GeoCapital/app.jsonpreviously carried a Google Maps API key and a Mapbox secret token in plaintext. Those are being rotated and must not be reused. Configuration now comes from the environment — see Configuration.
GeoCapital/ is an Expo app using expo-router, so the files under app/ are
the routes:
| Route | Screen |
|---|---|
index.tsx |
entry / landing |
home.tsx |
main dashboard |
MapView/[id].tsx |
the map view for an opportunity |
Details/[id].tsx |
opportunity detail |
loanScreen.tsx |
loan overview |
loanRequestForm.tsx |
loan application form |
portfolio.tsx |
the user's portfolio |
profile.tsx |
account |
cd GeoCapital
npm install
cp .env.example .env # fill in your own keys — see Configuration
npx expo startA native build additionally needs MAPBOX_DOWNLOAD_TOKEN set, or fetching the
Mapbox SDK fails.
surfin/ is a Go service. It needs libgeos on the host for geospatial
operations:
# macOS
brew install geos
# Debian / Ubuntu
sudo apt install libgeos-devThen:
cd surfin
docker compose up -d # PostgreSQL
make run # or `air` for live reload, see .air.toml
make testDatabase access is generated by sqlc from query.sql into
internal/database/query.sql.go — edit the SQL, then regenerate, rather
than editing the generated Go. Swagger docs are served from
internal/server/docs/.
Both halves read configuration from the environment. Nothing sensitive belongs in a tracked file.
The app's config lives in GeoCapital/app.config.js, which replaced the old
committed app.json. It reads:
| Variable | Purpose |
|---|---|
EXPO_PUBLIC_GOOGLE_MAPS_API_KEY |
Android Google Maps key |
MAPBOX_DOWNLOAD_TOKEN |
Mapbox secret token (sk.*), build-time only |
EXPO_PUBLIC_MAPBOX_PUBLIC_TOKEN |
Mapbox public token (pk.*), runtime |
EXPO_PUBLIC_API_URL |
base URL of the surfin API |
This distinction caused the leak here, so it is worth stating plainly.
EXPO_PUBLIC_* values are inlined into the JavaScript bundle. Anyone can
extract them from a shipped app. That is acceptable for a Mapbox pk.* token or
a Google Maps key, provided each is restricted at the provider — in GCP, to
this app's package name and signing certificate; in Mapbox, by URL. Restriction
is the control, not secrecy.
MAPBOX_DOWNLOAD_TOKEN is different. A Mapbox sk.* token is a secret
token with account-level scopes, used only to download the SDK during a native
build. It must never reach the bundle, which is exactly why it has no
EXPO_PUBLIC_ prefix. The token previously committed here was an sk.*, so it
was genuinely sensitive rather than merely visible.
For CI and EAS builds, set these as EAS secrets rather than putting them in a file.
See CONTRIBUTING.md. Security reports go through SECURITY.md, not public issues.
Released under the MIT License. © Kesowa Infinite Ventures.