Thanks to visit codestin.com
Credit goes to github.com

Skip to content

This is a web-based operating system architected with a React/Vite/TypeScript frontend and a Spring Boot 3 backend. The application simulates a desktop environment in the browser, providing a window manager, Dock, terminal, and games, with an available REST API for creating S3-backed system snapshots.

License

Notifications You must be signed in to change notification settings

AngRoy/NostalgiOS

Repository files navigation

NostalgiOS β€” A Web-Native, Retro-Modern OS in the Browser

This is a web based operating system architected with a React/Vite/TypeScript frontend and a Spring Boot 3 backend. The application simulates a desktop environment in the browser, providing a window manager, Dock, terminal, and games, with an available REST API for creating S3-backed system snapshots.


Key Features

  • Retro-inspired desktop UI

  • State that survives reloads IndexedDB + localStorage snapshotting; optional server snapshots on disk or S3. Reopen and continue where you left off.

  • Games, the 90s way Included: Snake, Paddle Battle (pong-like), Call Break cards; start/replay screens, score boards, original assets. (Planned: Minefield, Crate Mover, Tile Merge, Space Rocks.)

  • Terminal(s) Fast virtual FS shell (built-in commands). Optional WASM Bash mode (lazy-loaded, offline-bundled).

  • In-OS Browser (sandboxed) Tabs + address bar via <iframe sandbox> with an allow-list of embeddable sites and a retro β€œNostalgiNet” homepage. CSP-blocked sites get a clear β€œOpen in new tab” button. (Proxy mode optional later.)

  • Backend APIs (Spring Boot 3 + Java 21) Health endpoints; snapshot store/fetch/delete to local disk or AWS S3 (v2 SDK). H2 for local dev; secure defaults for production.


🧭 Table of Contents


Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Browser (SPA, PWA-ish)  β”‚  React + Vite + TS
β”‚  β€’ Desktop, Dock, Windowsβ”‚  IndexedDB/localStorage
β”‚  β€’ Apps: Explorer, Games β”‚  Optional WASM (Pyodide/Bash)
β”‚  β€’ Terminal, Settings    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
              β”‚ fetch /api/*
              β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Spring Boot 3 (Java 21)  β”‚  REST APIs
β”‚ β€’ /api/health, /api/ping β”‚  H2 for dev
β”‚ β€’ /api/snap/*            β”‚  S3 (AWS SDK v2) optional
β”‚ Serves SPA static files  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
              β”‚
              β–Ό
     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
     β”‚ Storage          β”‚
     β”‚ β€’ /app/data/...  β”‚  (volume)
     β”‚ β€’ S3 bucket      β”‚  (opt-in)
     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Repo Structure

nostalgios/
β”œβ”€ apps/
β”‚  └─ web-os/
β”‚     β”œβ”€ public/
β”‚     β”‚  β”œβ”€ wallpapers/               # default.jpg (your default wallpaper)
β”‚     β”‚  β”œβ”€ sdk/pyodide/              # local Pyodide bundle (offline)
β”‚     β”‚  └─ assets/games/...          # game sprites, SFX, icons
β”‚     β”œβ”€ src/
β”‚     β”‚  β”œβ”€ components/               # Desktop, Window, Dock, MenuBar, etc.
β”‚     β”‚  β”œβ”€ apps/                     # Explorer, Settings, Help, Browser, Games, Terminal
β”‚     β”‚  β”œβ”€ games/                    # Snake, PaddleBattle, CallBreak (and more)
β”‚     β”‚  β”œβ”€ os/                       # boot, vfs, wallpaper utils
β”‚     β”‚  β”œβ”€ state/                    # Store, types, init (no top-level await)
β”‚     β”‚  β”œβ”€ workers/                  # py.worker.ts (loads pyodide via importScripts)
β”‚     β”‚  β”œβ”€ ui/                       # Menu, ModalProvider, shared UI
β”‚     β”‚  β”œβ”€ ErrorBoundary.tsx
β”‚     β”‚  β”œβ”€ main.tsx                  # awaits initStore() + bootOS(), mounts UI
β”‚     β”‚  └─ styles.css                # themes (aqua-light default), tokens
β”‚     β”œβ”€ index.html
β”‚     β”œβ”€ vite.config.ts
β”‚     └─ package.json
β”‚
β”œβ”€ server/
β”‚  └─ snap/
β”‚     β”œβ”€ src/main/java/com/nostalgi/snap/
β”‚     β”‚  β”œβ”€ SnapApplication.java
β”‚     β”‚  β”œβ”€ SecurityConfig.java
β”‚     β”‚  β”œβ”€ HealthController.java     # GET /api/health
β”‚     β”‚  β”œβ”€ ApiControllers.java       # GET /api/ping, APIs
β”‚     β”‚  β”œβ”€ SnapshotService.java      # local/S3 storage, path-style support
β”‚     β”‚  └─ ... repositories/entities if needed
β”‚     β”œβ”€ src/main/resources/
β”‚     β”‚  β”œβ”€ application.yaml          # prod/dev props (optional)
β”‚     β”‚  └─ static/                   # SPA bundle injected at build
β”‚     └─ pom.xml
β”‚
β”œβ”€ docker/
β”‚  └─ entrypoint.sh                   # fixes volume ownership, then gosu β†’ appuser
β”‚
β”œβ”€ Dockerfile                         # all-in-one (build SPA + jar)
β”œβ”€ docker-compose.yml                 # dev split: web (5173) + api (8080)
└─ README.md

Prerequisites

  • Docker (Desktop) or Docker Engine
  • Optional: Node 18+/20+, Java 21 if you want to run parts without Docker

Quick Start (Docker All-in-One)

Build SPA β†’ bundle into Spring Boot β†’ run one container.

# From repo root
docker build --no-cache -t nostalgios:all-in-one .
docker run --rm -p 8080:8080 -v nostalgios_data:/app/data nostalgios:all-in-one

# Open the SPA served by Spring:
http://localhost:8080/

Notes

  • The container runs an entrypoint that ensures /app/data is owned by the app user:

    • It creates ${SNAP_STORAGE_DIR:-/app/data/snapshots} and chowns /app/data.
    • Then starts Spring with -Dsnap.storageDir=....
  • Data persists in the named volume nostalgios_data.


Dev Workflow (docker-compose)

Use Vite’s hot-reload (PORT 5173) + API (PORT 8080).

docker-compose.yml (example):

services:
  web:
    build:
      context: .
      dockerfile: Dockerfile.dev.web   # or use the main Dockerfile if you prefer
    working_dir: /app/apps/web-os
    command: npm run dev -- --host 0.0.0.0
    ports:
      - "5173:5173"
    volumes:
      - ./apps/web-os:/app/apps/web-os
    environment:
      - VITE_API_BASE=http://localhost:8080

  server:
    build:
      context: .
      dockerfile: Dockerfile.dev.server
    working_dir: /app/server/snap
    ports:
      - "8080:8080"
    volumes:
      - ./server/snap:/app/server/snap
      - nostalgios_data:/app/data
    environment:
      - SPRING_PROFILES_ACTIVE=dev
      - SNAP_STORAGE_DIR=/app/data/snapshots

volumes:
  nostalgios_data:

You can also drive both services from the single root Dockerfile; many teams keep small .dev Dockerfiles for faster inner-loop.

Open:

  • Frontend (Vite dev): http://localhost:5173/
  • API: http://localhost:8080/api/health

Configuration & Env

Frontend

  • Default theme: aqua-light (stronger contrast). Change under Settings β†’ Appearance.
  • Wallpapers: add apps/web-os/public/wallpapers/default.jpg. Users can upload images; we store them in IndexedDB (and optionally server snapshots).
  • Safe state init: initStore() is awaited in main.tsx. get snapshot() never throws; Desktop renders a boot splash until ready.

Backend (Spring Boot)

Key properties (via env or application.yaml):

Property Default Description
snap.storageDir ./data/snapshots Local snapshot path (overridden by entrypoint to /app/data/snapshots)
snap.s3.enabled false Enable S3 storage
snap.s3.bucket nostalgios-snaps S3 bucket
snap.s3.region ap-south-1 AWS region
snap.s3.endpoint (empty) Custom endpoint (e.g. MinIO)
snap.s3.forcePathStyle true Path style access
aws.accessKeyId (empty) S3 creds (if not using default provider chain)
aws.secretAccessKey (empty) S3 creds

Security In dev, Spring Security prints a generated password to logs; the API allows unauthenticated /api/health (and /api/ping if present). Harden for production as needed.


Backend API

  • GET /api/health β†’ { "status": "ok" }
  • GET /api/ping β†’ { "status": "ok" } (optional)
  • POST /api/snap/{deviceId} β†’ body bytes stored (disk or S3)
  • GET /api/snap/{deviceId} β†’ returns snapshot bytes
  • DELETE /api/snap/{deviceId} β†’ delete snapshot

The SPA primarily uses the browser-local snapshot. Server snapshots are optional long-term persistence or sync.


Front-End Tech Notes

  • React + Vite + TypeScript (modern target, esnext).
  • State Store with explicit initStore() (no top-level await).
  • ErrorBoundary overlays any crash with a β€œReset & Reload” button that clears local storage + IndexedDB (one origin only).
  • Windowing: draggable panels, right-docked Dock, z-index stacking, snap gap.
  • Keyboard: Esc closes menus, arrow keys in games, space/pause where relevant.

WASM & Python

  • Pyodide: bundled locally under apps/web-os/public/sdk/pyodide/ so it works offline (no CDN). In py.worker.ts, Pyodide is loaded via importScripts(BASE + 'sdk/pyodide/pyodide.js') with indexURL pointing to the same folderβ€”not bundled by Vite.

  • Bash (WASM): optional. When enabled, the wasm asset is lazy-loaded from public/wasm/bash/. If it fails, terminal falls back to the built-in VFS shell.


Theming & Accessibility

  • Light/Dark/High-Contrast with tokens:

    • Light: higher contrast for readability (--text, --border, --shadow tuned).
    • Dark (Aqua-inspired): glow accents, subtle transparencyβ€”original palettes (no traffic-lights).
  • Focus rings, large hit targets on menus, color-blind safe accent defaults.

  • Users can upload wallpapers and pick fit (fill/fit/tile/center).


Testing & Quality

  • TypeScript strictness where practical.

  • Lint/format recommended:

    • Frontend: npm run lint, npm run format (add ESLint/Prettier as desired).
    • Backend: mvn -q -DskipTests=false test (add tests over time).
  • CI suggestion (GitHub Actions):

    • Cache Maven & npm.
    • Build SPA, inject into jar, run mvn -DskipTests package for release.
    • Build Docker image per tag.

Deployment Options

1) Single Docker image (recommended)

Already covered in β€œQuick Start”. Push to any registry and run.

2) Render / Fly.io / Railway

  • Build from Docker. Expose port 8080.
  • Set SNAP_STORAGE_DIR=/app/data/snapshots, mount a persistent volume to /app/data.
  • For S3: set snap.s3.* env vars and snap.s3.enabled=true.

3) K8s

  • One Deployment + Service; mount a PVC at /app/data.
  • Optional: HPA on CPU/RAM; externalized S3 credentials via Secret.

About

This is a web-based operating system architected with a React/Vite/TypeScript frontend and a Spring Boot 3 backend. The application simulates a desktop environment in the browser, providing a window manager, Dock, terminal, and games, with an available REST API for creating S3-backed system snapshots.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published