{"id":50769625,"url":"https://github.com/muringi21/kijani","last_synced_at":"2026-06-11T17:00:54.610Z","repository":{"id":362136678,"uuid":"1133827487","full_name":"muringi21/kijani","owner":"muringi21","description":"Full-stack leather traceability platform: Fastify REST API + offline-first Expo mobile app","archived":false,"fork":false,"pushed_at":"2026-06-02T20:02:11.000Z","size":20,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-02T21:28:27.406Z","etag":null,"topics":["expo","fastify","monorepo","react-native","typescript"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/muringi21.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-01-13T21:46:50.000Z","updated_at":"2026-06-02T20:02:15.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/muringi21/kijani","commit_stats":null,"previous_names":["muringi21/kijani"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/muringi21/kijani","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/muringi21%2Fkijani","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/muringi21%2Fkijani/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/muringi21%2Fkijani/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/muringi21%2Fkijani/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/muringi21","download_url":"https://codeload.github.com/muringi21/kijani/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/muringi21%2Fkijani/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34208761,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-11T02:00:06.485Z","response_time":57,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["expo","fastify","monorepo","react-native","typescript"],"created_at":"2026-06-11T17:00:53.744Z","updated_at":"2026-06-11T17:00:54.604Z","avatar_url":"https://github.com/muringi21.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Kijani Traceability\n\nKijani is a leather supply chain traceability platform I've been building for the Kenyan market. Field agents use the mobile app to scan QR-tagged hides, log weight/grade/species, and batch-upload records to the API — even offline. Tanneries can then look up any hide's provenance by scanning its QR code.\n\nThis repo is the MVP monorepo: a Fastify REST API backed by SQLite, and an Expo React Native agent app.\n\n## Status\n\nActive development — core batch upload and offline queue are working. Next: multi-tenant auth and Postgres migration.\n\n## Packages\n\n| Package | Tech | Purpose |\n|---|---|---|\n| `apps/api` | Fastify + SQLite | REST API — batch upload, list, single-batch lookup |\n| `apps/mobile` | Expo React Native | Agent app — QR scan, offline queue, GPS, batched uploads |\n| `packages/shared` | Zod | Shared `BatchSchema` used by both API and mobile |\n\n## Prerequisites\n\n- Node.js 18+\n- npm 9+ (workspaces)\n- Expo Go on your phone (for mobile dev), or an iOS/Android simulator\n\n## Quick Start\n\n```bash\n# 1. Install all workspaces\nnpm install\n\n# 2. Copy \u0026 edit the API env file\ncp apps/api/.env.example apps/api/.env\n\n# 3. Start the API (Terminal 1)\nnpm run dev:api\n\n# 4. Start Expo (Terminal 2)\nnpm run dev:mobile\n```\n\n**Physical device?** Edit `apps/mobile/src/config.js` and set `API_BASE_URL` to your laptop's local IP (e.g. `http://192.168.1.50:3333`).\n\n## API Endpoints\n\nAll endpoints except `/health` require the `x-api-key` header.\n\n| Method | Path | Description |\n|---|---|---|\n| GET | `/health` | Liveness check (no auth) |\n| POST | `/v1/batches` | Upload one batch or array of batches |\n| GET | `/v1/batches?limit=50` | List recent batches |\n| GET | `/v1/batches/:id` | Single batch + hides (QR provenance lookup) |\n\n**Example — upload a batch:**\n\n```bash\ncurl -X POST http://localhost:3333/v1/batches \\\n  -H \"Content-Type: application/json\" \\\n  -H \"x-api-key: dev-key-change-me\" \\\n  -d '{\n    \"id\": \"550e8400-e29b-41d4-a716-446655440000\",\n    \"tenantId\": \"demo-tenant\",\n    \"agentId\": \"agent-01\",\n    \"productType\": \"hides\",\n    \"hides\": [\n      { \"qrCode\": \"KJ-001\", \"weight\": 12.5, \"grade\": \"A\", \"species\": \"cattle\" }\n    ],\n    \"capturedAt\": \"2026-03-19T10:00:00.000Z\"\n  }'\n```\n\n## Mobile App Screens\n\n- **Main (Agent)** — Scan QR tags, enter weight/grade/species, build a batch, save offline, upload when connected\n- **Scan** — Camera-based QR/barcode scanner (capture mode for agents, lookup mode for tanneries)\n- **Batch Detail** — Provenance view: all hide records, GPS coords, timestamps\n\n## Architecture Notes\n\n- **SQLite** (`better-sqlite3`): zero-config for MVP. Plan to migrate to Postgres/Supabase before scaling to multiple tenants\n- **API key auth**: simple `x-api-key` header for the pilot. Will swap to JWT when multi-tenant support is added\n- **Offline-first**: batches saved to AsyncStorage immediately on the device. Auto-flush every 5 min + manual \"Upload Now\"\n- **Partial-success uploads**: if some batches in an array fail validation, valid ones still save. Failed indices are returned so the client retries only those\n- **Duplicate protection**: batch IDs are UUIDs generated on the phone; the DB rejects duplicate inserts gracefully\n\n## Project Structure\nkijani/\n├── package.json\n├── apps/\n│ ├── api/\n│ │ ├── server.js # Fastify routes + auth hook\n│ │ ├── db.js # SQLite schema + queries\n│ │ ├── .env.example\n│ │ └── package.json\n│ └── mobile/\n│ ├── App.js\n│ ├── index.js\n│ ├── app.json\n│ ├── metro.config.js\n│ └── src/\n│ ├── config.js\n│ ├── lib/\n│ │ ├── queue.js\n│ │ └── api.js\n│ └── screens/\n│ ├── MainScreen.js\n│ ├── ScanScreen.js\n│ └── BatchDetailScreen.js\n└── packages/\n└── shared/\n└── src/index.js","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmuringi21%2Fkijani","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmuringi21%2Fkijani","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmuringi21%2Fkijani/lists"}