https://github.com/local-loop-io/localloop-backend
Backend API for LocalLoop expressions of interest
https://github.com/local-loop-io/localloop-backend
api backend express interest-form sqlite
Last synced: about 2 months ago
JSON representation
Backend API for LocalLoop expressions of interest
- Host: GitHub
- URL: https://github.com/local-loop-io/localloop-backend
- Owner: local-loop-io
- License: mit
- Created: 2025-12-19T10:50:09.000Z (6 months ago)
- Default Branch: main
- Last Pushed: 2025-12-21T13:44:54.000Z (6 months ago)
- Last Synced: 2025-12-24T01:59:15.949Z (6 months ago)
- Topics: api, backend, express, interest-form, sqlite
- Language: TypeScript
- Size: 135 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
- Code of conduct: CODE_OF_CONDUCT.md
- Security: SECURITY.md
Awesome Lists containing this project
README
# localLOOP Backend
Backend service for the localLOOP lab demo — interest registry, city data, and minimal LOOP protocol interop flows.
> This project is an early, low-TRL concept. There are no public pilots or deployments. Lab demo only.
## At a glance
| Item | Details |
| --- | --- |
| Runtime | Bun + Fastify |
| Data | PostgreSQL (PostGIS), Redis, MinIO |
| API base | https://loop-api.urbnia.com |
| Docs | Live OpenAPI at `/openapi.json`, Redoc at `/docs` |
## Quickstart (local)
```bash
bun install
cp .env.example .env # adjust values as needed
docker compose up -d # start Postgres, Redis, MinIO
bun run dev # API on :8088
bun test # run all tests
```
## API
### Health
| Method | Path | Description |
| --- | --- | --- |
| `GET` | `/health` | Service + DB status. Returns `503` if DB unreachable. |
### Interest
| Method | Path | Description |
| --- | --- | --- |
| `POST` | `/api/interest` | Submit an Expression of Interest |
| `GET` | `/api/interest` | List Expressions of Interest |
| `GET` | `/api/interest/stream` | SSE stream for new interest events |
### Loop demo (MaterialDNA → Offer → Match → Transfer)
| Method | Path | Description |
| --- | --- | --- |
| `POST` | `/api/v1/material` | Register a MaterialDNA record |
| `GET` | `/api/v1/material/:id` | Retrieve a material by ID |
| `GET` | `/api/v1/material` | List materials (`limit`, `category`) |
| `GET` | `/api/v1/node/info` | Return local node metadata for the lab backend |
| `POST` | `/api/v1/product` | Register a ProductDNA record |
| `GET` | `/api/v1/product/:id` | Retrieve a product by ID |
| `GET` | `/api/v1/product` | List products (`limit`, `category`) |
| `POST` | `/api/v1/offer` | Create an Offer |
| `GET` | `/api/v1/offer/:id` | Retrieve an offer by ID |
| `GET` | `/api/v1/offer` | List offers (`limit`, `status`) |
| `POST` | `/api/v1/match` | Record a Match |
| `GET` | `/api/v1/match/:id` | Retrieve a match by ID |
| `GET` | `/api/v1/match` | List matches (`limit`) |
| `POST` | `/api/v1/transfer` | Record a Transfer |
| `GET` | `/api/v1/transfer/:id` | Retrieve a transfer by ID |
| `GET` | `/api/v1/transfer` | List transfers (`limit`) |
| `POST` | `/api/v1/material-status` | Record a material status update |
| `GET` | `/api/v1/events` | List loop events (`limit`) |
| `GET` | `/api/v1/stream` | SSE stream for loop events |
| `POST` | `/api/v1/relay` | Relay a supported lab loop event from another node |
### Federation
| Method | Path | Description |
| --- | --- | --- |
| `GET` | `/api/v1/federation/nodes` | List known federation nodes |
| `POST` | `/api/v1/federation/handshake` | Register a federation node (lab-only handshake) |
### Cities
| Method | Path | Description |
| --- | --- | --- |
| `GET` | `/api/cities` | List demo cities |
| `GET` | `/api/cities/:slug` | City detail |
| `GET` | `/api/cities/geojson` | GeoJSON FeatureCollection |
### Other
| Method | Path | Description |
| --- | --- | --- |
| `GET` | `/api/metrics` | In-memory service metrics snapshot |
| `GET` | `/api/privacy` | Privacy notice |
| `GET` | `/openapi.json` | OpenAPI spec (auto-generated) |
| `GET` | `/docs` | Redoc UI |
LOOP write routes accept both `application/json` and `application/ld+json`.
The backend also serves `GET /api/v1/node/info` as a minimal lab-only node metadata endpoint.
Spec endpoints that remain unimplemented in this repo are `/api/v1/material/search`, `/api/v1/signals`, `/api/v1/transaction`, `/api/v1/federate/announce`, and `/api/v1/federate/offer`.
## Environment variables
See `.env.example` for the full list with descriptions. Key variables:
| Variable | Default | Description |
| --- | --- | --- |
| `DATABASE_URL` | — | Postgres connection string (required) |
| `DATABASE_SSL` | `false` | Enable TLS for Postgres |
| `DB_POOL_SIZE` | `20` | Max pool connections |
| `DB_IDLE_TIMEOUT_MS` | `30000` | Close idle connections after ms |
| `DB_CONNECTION_TIMEOUT_MS` | `5000` | Fail if no pool slot in ms |
| `REDIS_URL` | — | Redis connection string |
| `MINIO_SECRET_KEY` | — | MinIO secret (required) |
| `ALLOWED_ORIGINS` | `https://local-loop-io.github.io` | CORS allowlist (comma-separated) |
| `RATE_LIMIT_MAX` | `60` | Global rate limit per window |
| `RATE_LIMIT_WRITE_MAX` | `20` | Write route rate limit per window |
| `REQUEST_TIMEOUT_MS` | `30000` | Server connection timeout |
| `AUTH_ENABLED` | `false` | Enable BetterAuth |
| `API_KEY_ENABLED` | `false` | Require `X-API-Key` on write routes |
| `RUN_MIGRATIONS` | `true` | Auto-run DB migrations on startup |
In `NODE_ENV=production` the server refuses to start with missing or weak secrets.
## Repo layout
```
src/
config.ts env validation (Zod)
server.ts Fastify app setup
routes/ one file per route group
db/
pool.ts pg connection pool
migrations/ numbered .sql files
loop.ts loop entity queries
realtime/ SSE stream handlers
security/ API key middleware
scripts/ lab demo + federation scripts
deploy/ systemd service + nginx example
tests/ Bun test suite
```
## Notes
- Lab demo only. No public pilots or deployments.
- The normative protocol reference is [loop-protocol](https://github.com/local-loop-io/loop-protocol).
## Links
- Protocol spec: https://github.com/local-loop-io/loop-protocol
- Docs hub: https://local-loop-io.github.io