Files
backend/docs/typescript-frontend-integration.md
Andriy Oblivantsev c2aa716ed8
CI / test (push) Successful in 5s
Switch local API port to 8122 and keep DB internal.
Update runtime defaults, compose mappings, frontend defaults, and developer docs to use port 8122 while keeping PostGIS reachable only via the internal compose network.

Made-with: Cursor
2026-03-01 12:12:44 +00:00

3.1 KiB

TypeScript Frontend Integration Guide

This document explains how frontend developers should integrate with the backend through the reusable TypeScript client at libs/geo-api-client.

Primary backend URL for integration:

  • https://momswap.produktor.duckdns.org/

Goals

  • Keep cryptographic signing logic in one place.
  • Avoid duplicating API request code in frontend apps.
  • Use a consistent local key storage format across projects.

Client package location

  • Source: libs/geo-api-client/src
  • Entry point: libs/geo-api-client/src/index.ts
  • Build output (browser ESM): libs/geo-api-client/dist/index.js

Build and test the client

cd libs/geo-api-client
bun install
bun test
bun run build

Public API (current)

Class: GeoApiClient

Constructor:

  • new GeoApiClient(baseUrl, storage, storageKey?)

Key methods:

  • ensureKeysInStorage()
  • getStoredKeys()
  • importKeys(keys)
  • exportKeys()
  • setAccessToken(token)
  • createChallenge(publicKey)
  • loginWithSignature(publicKey, privateKey)
  • createInvitation(payload, inviterPrivateKey)
  • registerWithInvitation(...)
  • listCollections()
  • createCollection(name)
  • listFeatures(collectionId)
  • createPointFeature(collectionId, lon, lat, properties)
  1. Create one GeoApiClient instance per backend base URL.
  2. Call ensureKeysInStorage() when app initializes.
  3. Use loginWithSignature() to obtain and set a bearer token.
  4. Call collection/feature methods after authentication.
  5. Use importKeys/exportKeys in profile settings UX.

Example (TypeScript app)

import { GeoApiClient } from "../libs/geo-api-client/dist/index.js";

const storage = window.localStorage;

const storageLike = {
  getItem: (key: string) => storage.getItem(key),
  setItem: (key: string, value: string) => storage.setItem(key, value),
  removeItem: (key: string) => storage.removeItem(key),
};

const client = new GeoApiClient("https://momswap.produktor.duckdns.org", storageLike);

const keys = await client.ensureKeysInStorage();
await client.loginWithSignature(keys.publicKey, keys.privateKey);

const created = await client.createCollection("My Places");
await client.createPointFeature(created.id, -16.6291, 28.4636, { name: "Santa Cruz" });
const features = await client.listFeatures(created.id);
console.log(features);

Security notes

  • Private keys are currently stored in browser storage via the selected storage adapter.
  • If your frontend has stronger security requirements, wrap the storage adapter with your own encryption/decryption layer before calling setItem/getItem.
  • Never send private keys to the backend.

No-build frontend compatibility

For no-bundler apps, import the built ESM file:

<script type="module">
  import { GeoApiClient } from "../libs/geo-api-client/dist/index.js";
  // use client...
</script>

The backend itself serves static UI at /web/, but this library can be consumed by any frontend runtime that supports fetch, TextEncoder, and ES modules.

For local development you can switch the client base URL to http://localhost:8122.