ISC Steam is a Steam-style web store and desktop launcher for games made by ISC
students at HES-SO Valais. Students submit a Git repository, the platform reads
an optional isc.json manifest, compiles Scala sources,
packages the game, stores the build in MongoDB GridFS, and makes it available to
signed-in players.
The app is built with:
- React 18 + Vite 6 for the web client
- Express 4 + Mongoose 8 for the API
- MongoDB + GridFS for app data, media, packages, avatars, banners, and chat images
- Socket.IO for friends, chat, presence, and playtime updates
- Electron for the desktop launcher
- Scala/JDK tooling for compiling and packaging submitted games
The visual identity uses the ISC logo assets from ISC-HEI/isc-logos.
Requirements:
- Node.js >= 20
- npm
- git
- Scala 2.13 on
PATHfor local game builds - Java/JDK tooling for packaging games
- Docker, if you want the provided local MongoDB
npm install
cp .env.example server/.env
npm run db:up
npm run devThen open http://localhost:5173.
The API runs on http://localhost:5174. The first registered account becomes
the admin. Students become publishers by registering with PUBLISHER_CODE from
server/.env.
If MongoDB is not available, the server still starts and /api/health reports
the database state. Data-backed routes return 503 until MongoDB connects.
Copy .env.example to server/.env for local development.
Important variables:
| Variable | Purpose |
|---|---|
PORT |
API port, defaults to 5174. |
MONGODB_URI |
MongoDB connection string. |
CLIENT_ORIGIN |
Allowed browser origin for CORS and Socket.IO. |
JWT_SECRET |
Secret used to sign account tokens. Change this. |
PUBLISHER_CODE |
Registration code that grants the student/publisher role. |
SCALA_LIBRARY_JAR |
Optional explicit path to scala-library.jar. |
GAME_DEPENDENCY_JARS |
Optional fallback jars for submitted games. |
WINDOWS_JDK_JMODS |
Required on Linux/macOS when cross-building Windows game runtimes. |
JAVAFX_JMODS |
Windows JavaFX jmods for JavaFX games. |
JAVAFX_JMODS_LINUX |
Linux JavaFX jmods for Linux game packages. |
For multiple Scala installations, the builder can use versioned variables such
as SCALAC_2_12, SCALA_2_12_HOME, and SCALA_LIBRARY_JAR_2_12 before falling
back to PATH.
| Command | What it does |
|---|---|
npm run dev |
Runs the API and client together with hot reload. |
npm run dev:client |
Runs only the Vite client. |
npm run dev:server |
Runs only the API with Node watch mode and server/.env. |
npm run build |
Builds the production client into client/dist. |
npm run start |
Starts the API; serves client/dist too when present. |
npm run db:up |
Starts local MongoDB through Docker Compose. |
npm run db:down |
Stops the local Docker Compose stack. |
- Visitor: can register, browse the public catalog, and view public game pages.
- Player: any signed-in account can add games to the library, download packages, review games, manage a profile, add friends, and chat.
- Student/publisher: can submit Git repositories, inspect metadata, trigger
rebuilds, edit game pages, and read build logs on
/dashboard. - Admin: first registered account, or a user promoted later. Admins moderate
games, feature/publish entries, manage accounts, and edit the site
announcement on
/admin.
- A student submits a Git repository on
/dashboard. - The server clones the repository and reads
isc.jsonwhen present. Without a manifest, it infers basic metadata from README files, Scala sources,build.sbt,.scala-version, and dependency jar names. - The build pipeline imports cover art and screenshots into GridFS, resolves
dependencies, compiles
.scalasources, creates runnable packages, and saves the full build log. - An admin publishes or features the game. Published games appear in the store and can be added to a player's library.
See docs/ISC_MANIFEST.md for the complete manifest
format and docs/examples/isctaker.isc.json
for an example.
The pipeline lives in server/src/services/pipeline.js.
It builds one game at a time.
Supported inputs:
- Scala sources under manifest-defined source directories, defaulting to
src - resources such as sprites, sounds, and levels
- repo-local dependency jars
- fallback dependency jars from
server/vendor - Maven dependencies declared with sbt-style syntax in
build.sbtor README text - FunGraphics, gdx2d, JavaFX, and plain Scala projects when the required jars or jmods are available
Package output:
- Windows package: always the primary package, served by default from
/api/games/:slug/download - Linux package: produced on Linux build servers when the required Linux runtime
tooling is available, served with
?platform=linux
Local game builds need compatible Scala and Java tooling. The production Docker image installs git, a JDK, Scala 2.13, Windows JDK jmods, and JavaFX jmods so it can compile and package student submissions in the container.
Core pages:
/: public store catalog with tags, search, featured games, and game cards/game/:slug: game detail page, screenshots, reviews, authors, downloads/library: signed-in user's library and playtime/dashboard: publisher tools for submissions and rebuilds/admin: admin moderation, users, games, stats, and announcement controls/user/:username: Steam-style profile page/docs/manifest: in-app manifest reference/style-guide: local design-system reference
Profiles include avatar and banner uploads, bio, status, stat cards, showcase panels, activity, friends, recent games, reviews, screenshot gallery, and comments with likes.
The social dock provides friends, one-to-one chat, image messages, online/in-game
presence, unread state, and playtime reporting. Socket.IO is initialized by the
API server; production proxies must forward /socket.io/ with WebSocket
upgrades.
desktop/ is an Electron launcher for the hosted web app. It loads the server
URL configured in desktop/package.json under iscsteam.url, so normal web
changes do not require a desktop rebuild.
Unlike the browser version, the desktop app can install, unzip, and launch games
from the Library page. It also reports playtime and "playing" presence back to
the web app. Discord Rich Presence is configured with
iscsteam.discordClientId in desktop/package.json.
cd desktop
npm install
ISCSTEAM_URL=http://localhost:5173 npm start
npm run distnpm run dist builds Windows artifacts by default. The package config also
defines a Linux AppImage target, used by the GitHub release workflow.
Pushing a tag such as v2.2.3 triggers
.github/workflows/release-desktop.yml. The workflow builds:
- Windows installer:
ISCSteam-Setup-<version>.exe - Windows portable executable:
ISCSteam.exe - Linux AppImage:
ISCSteam-<version>.AppImage - updater metadata for Electron auto-update
git tag v2.2.3
git push origin v2.2.3All client calls use /api.
| Route | Access | Purpose |
|---|---|---|
GET /api/health |
public | Server and database health. |
POST /api/auth/register |
public | Create an account; first user becomes admin. |
POST /api/auth/login |
public | Log in and receive a JWT. |
GET /api/auth/me |
token | Read the current user. |
GET /api/games |
public | Published store catalog. |
GET /api/games/tags |
public | Available tags. |
GET /api/games/:slug |
public/optional token | Game details. |
GET /api/games/:slug/media/:mediaId |
public | Cover and screenshot media. |
GET /api/games/:slug/download?platform=linux |
token | Download a packaged game; omit platform for Windows. |
GET /api/games/:slug/reviews |
public/optional token | List reviews. |
POST /api/games/:slug/reviews |
token | Create or update your review. |
DELETE /api/games/:slug/reviews |
token | Delete your review. |
GET /api/games/mine |
student/admin | Publisher's games. |
POST /api/games/inspect-repo |
student/admin | Inspect a repository before publishing. |
POST /api/games |
student/admin | Create a game entry and package upload/build. |
POST /api/games/:slug/rebuild |
student/admin | Rebuild a submitted game. |
PATCH /api/games/:slug |
student/admin | Update game metadata/media/package. |
DELETE /api/games/:slug |
student/admin | Delete a game. |
GET /api/library |
token | Current user's library. |
POST /api/library/:slug |
token | Add a game to the library. |
DELETE /api/library/:slug |
token | Remove a game from the library. |
POST /api/library/:slug/playtime |
token | Add tracked playtime. |
GET /api/social/friends |
token | List friends. |
POST /api/social/friends |
token | Send a friend request. |
POST /api/social/friends/:friendshipId/accept |
token | Accept a request. |
DELETE /api/social/friends/:friendshipId |
token | Remove a friendship/request. |
GET /api/social/messages/:userId |
token | List one-to-one messages. |
POST /api/social/messages/:userId |
token | Send a text message. |
POST /api/social/messages/:userId/image |
token | Send an image message. |
POST /api/social/messages/:userId/read |
token | Mark a chat as read. |
GET /api/social/media/:messageId |
token | Fetch chat image media. |
GET /api/users/resolve |
public | Resolve display names to profile users. |
GET /api/users/:username |
public/optional token | Public profile. |
GET /api/users/:username/activity |
public | Profile activity. |
PATCH /api/users/me/profile |
token | Update your profile. |
POST /api/users/me/avatar |
token | Upload avatar. |
POST /api/users/me/banner |
token | Upload banner. |
GET /api/users/:username/comments |
public/optional token | Profile comments. |
POST /api/users/:username/comments |
token | Add a profile comment. |
DELETE /api/users/:username/comments/:commentId |
token | Delete a profile comment. |
POST /api/users/:username/comments/:commentId/like |
token | Like/unlike a comment. |
GET /api/admin/stats |
admin | Admin dashboard stats. |
GET /api/admin/users |
admin | User management. |
PATCH /api/admin/users/:id |
admin | Change a user role. |
DELETE /api/admin/users/:id |
admin | Delete a user. |
GET /api/admin/games |
admin | All games, including unpublished entries. |
PUT /api/admin/announcement |
admin | Update the site announcement. |
GET /api/announcement |
public | Active announcement. |
GET /api/releases |
public | Desktop release metadata. |
client/
src/
api/ Fetch wrapper and download URLs
components/ Layout, cards, reviews, social dock, profile widgets
context/ Auth and social/presence state
hooks/ Theme hook
pages/ Store, game detail, library, dashboard, admin, profile
styles/ Theme tokens and page styles
desktop/
main.js Electron shell
preload.js Browser bridge for install/launch features
games.js Local install and launch helpers
discord.js Discord Rich Presence integration
deploy/
nginx-iscsteam.conf Host nginx reverse-proxy example
Caddyfile Optional Caddy reverse-proxy example
docs/
ISC_MANIFEST.md isc.json specification
examples/ Example manifests
server/
src/
config/ MongoDB and GridFS setup
controllers/ Route handlers
middleware/ Auth, DB guard, error handling
models/ Mongoose models
routes/ API route definitions
services/ Manifest parsing, build pipeline, presence
vendor/ Checked-in and cached build dependencies
Dockerfile Production API/client/build-toolchain image
docker-compose.yml Local MongoDB
docker-compose.prod.yml Production app + Mongo stack
The included production stack is designed for an Ubuntu VPS where host nginx terminates HTTPS and proxies to the app container on localhost.
git clone <this repo>
cd ISC-Steam
cp .env.example deploy/.env
# edit deploy/.env: DOMAIN, JWT_SECRET, PUBLISHER_CODE, and any build settings
docker compose -f docker-compose.prod.yml --env-file deploy/.env up -d --buildThe app container binds to 127.0.0.1:5174. Use
deploy/nginx-iscsteam.conf as the host nginx
template, including the /socket.io/ WebSocket proxy rules. Certbot or another
host-level TLS tool can manage HTTPS certificates.
To update a deployed server:
git pull
docker compose -f docker-compose.prod.yml --env-file deploy/.env up -d --builddeploy/Caddyfile is kept for setups where Caddy handles HTTPS instead of host
nginx.
The ISC logos are copyrighted by their authors and licensed CC BY-NC-SA 4.0 via ISC-HEI/isc-logos. Keep the attribution in the footer and respect the non-commercial license.
"Steam" is used here as a class-project nickname. This project is not affiliated with Valve.