Skip to content

Architecture ​

edtech4good is four repositories that together deliver a learning management system: a central cloud API, a classroom edge API that runs on a Raspberry Pi or any Linux box on the school network, an Angular admin and teacher web UI, and a learner app built with Expo for Android, iOS and the web.

Repository roles ​

RepositoryRole
edtech-lms-apiCentral NestJS API. Schools, curriculum, users, object storage for media, /sync/* to package curriculum for a classroom server, /log/import to ingest a classroom activity log (off by default), JWT auth, and POST /auth/school/login for teacher and staff login.
edtech-lms-uiAngular 21 admin, teacher and student web UI. Talks to the central API via environment.API_URL.
edtech-lms-rpi-apiClassroom NestJS API. Local MySQL, lessons, progress and quizzes, GET /export/log, PUT /import/master to receive a curriculum package, and student and teacher auth.
edtech-expoExpo app (React Native and web). Two HTTP bases: EXPO_PUBLIC_BASE_URL, usually the classroom server, and EXPO_PUBLIC_SYNC_URL, usually the central API.

A legacy native Android app and a duplicate reporting UI were retired and are not part of the current stack.

End-to-end diagram ​

End-to-end architecture: online central services and classroom LAN services, linked by sync and login callsOnline / centralClassroom LANedtech-lms-uiedtech-lms-api Object storage(S3-compatible)edtech-lms-rpi-api Tablets / webclients POST /sync/cloudpushes zip BASE_URL: auth,lessons, import,export SYNC_URL: /sync/content,auth/school/login

Runtime dependencies ​

ComponentDepends on
Central APIMySQL, an S3-compatible object store for media, SMTP (optional), configured via FORTYKAPICONFIG or plain env vars in src/config.ts
Admin/teacher/student UIThe central API reachable from the browser; API_URL and SCHEMA in environment.*.ts point at it
Classroom APIMySQL, configured via FORTYKAPIRPICONFIG or RPI_* env vars in src/config.ts
Learner appNetwork reachability to the configured classroom and central hosts

Ports and API docs ​

ServiceDefault HTTP portSwagger / OpenAPI UI
Central API3000 (PORT)/docs, see src/server.ts
Classroom API3000 (RPI_PORT)/docs, see src/server.ts
Admin/teacher/student UI (dev)4200none

Both APIs default to port 3000 because they normally run on separate machines: the central API in the cloud, the classroom API on the Pi.

Both APIs mount Swagger only when NODE_ENV is development or test. In any other environment /docs is not served.

Expo environment matrix ​

VariableTypical classroom useTypical online / sync use
EXPO_PUBLIC_BASE_URLClassroom server URLSame classroom URL, or the central API if the deployment is unified
EXPO_PUBLIC_SYNC_URLCentral API base URLCentral API base URL
EXPO_PUBLIC_RESOURCE_URL / EXPO_PUBLIC_RESOURCE_PATHLocal or remote media location used by useResourceSame
EXPO_PUBLIC_ACCESS_TYPEoffline or online, read by useResource and isOnlineOnly() to switch resource loadingSame

HTTP clients live in src/services/api/Api.ts: one instance is built against EXPO_PUBLIC_BASE_URL, the other against EXPO_PUBLIC_SYNC_URL.

Sync and data flow ​

A. Cloud to classroom: curriculum and master content ​

  1. An admin on the central UI prepares content.
  2. Server-side push: the central API's POST /sync/cloud builds a zip and PUTs it to the classroom server's /import/master, authenticated with SERVER_SYNC_KEY. See sync.controller.ts.
  3. Client-side path: a client can download a zip from the central API's GET /sync/content and PUT it to the classroom server's PUT /import/master; the current learner app does not call either. That route always accepts the server sync key as the raw Authorization header, and accepts an admin, superadmin or teacher token only when the classroom server runs with RPI_OFFLINE=true. See import.controller.ts.

B. Classroom to cloud: student and activity logs ​

  1. On the classroom server, GET /export/log returns a zip of activity logs. See export.controller.ts.
  2. A client can download that zip from the classroom server and upload it to the central API's PUT /log/import. See log.controller.ts. This upload route is off unless LOG_IMPORT_ENABLED is true or 1, and the current learner app does not call it.

C. Teacher and student login ​

  • Students on the classroom server typically sign in with POST /auth/login against EXPO_PUBLIC_BASE_URL.
  • Teachers and other staff sign in with POST /auth/school/login against the central API, EXPO_PUBLIC_SYNC_URL. This login (and any school-user token it issues) is for staff only; a student account is refused.

Central API configuration for classroom integration ​

From the central API's src/config.ts, these values control how the central API reaches a classroom server:

  • RPI_CLOUD is the base URL of the classroom API used when POST /sync/cloud pushes content, and for the other server-to-server calls the central API makes to a classroom server (student and teacher import, reports).
  • SERVER_SYNC_KEY authenticates that server-to-server import/master call.
  • RPI_SECRET is the JWT secret for the RPIACCESS token type. No route currently uses it, but outside development and test the API refuses to start while it holds the placeholder value.

SERVER_SYNC_KEY and RPI_SECRET are secrets. RPI_CLOUD is deployment configuration.

See also ​

Documentation under CC BY 4.0. Code under AGPL-3.0-only.