modtale/
├── backend/ # ☕ Spring Boot API
│ ├── src/main/java/ # Core Java Application
│ │ ├── config/ # Security, CORS, and WebMvc configs
│ │ ├── controllers/ # REST endpoints mapping
│ │ ├── models/ # MongoDB document schemas
│ │ ├── repositories/ # Database interaction layer
│ │ └── services/ # Core business logic (Uploads, Auth, etc.)
│ ├── Dockerfile.status # Detached status page/checker image
│ └── build.gradle # Dependencies & build definitions
│
├── frontend/ # Astro + React Web Application
│ ├── src/
│ │ ├── components/ # Reusable, stateless UI components (Buttons, Modals)
│ │ ├── modules/ # Domain-Driven Design (Auth, Project, User domains)
│ │ ├── pages/ # Astro SSR entry points (e.g., /[...all].astro)
│ │ ├── styles/ # Tailwind global CSS & theme constants
│ │ └── utils/ # API clients, Helpers
│ ├── astro.config.mjs # Astro build & integration settings
│ └── package.json # Node dependencies
│
├── launcher/ # JavaFX desktop client and native packaging
└── mock-db/ # Sanitized fixture generation and import tools
Warden is a separate, closed-source security scanner service.
| Domain | Technology | Usage |
|---|---|---|
| Frontend | Astro | Framework & Server-Side Rendering (SSR) |
| React | Interactive UI Components & SPA Routing (react-router-dom) |
|
| Tailwind CSS | Utility-first, responsive, and dark-mode compatible styling | |
| Lucide React | Consistent, lightweight SVG iconography | |
| Backend | Java 21 | Modern, high-performance server language |
| Spring Boot | Enterprise-grade REST API Framework | |
| MongoDB | Primary NoSQL document data store | |
| Bucket4j / Caffeine | Token-bucket rate limiting and high-speed in-memory caching | |
| Infrastructure | Cloudflare R2 | Zero-egress, S3-compatible Object Storage for mod files & images |
The public status page is served by a separate Spring Boot entry point: net.modtale.status.StatusServiceApplication.
It owns the status HTML, /api/v1/status, and /api/v1/status/live, and it does not depend on the main Astro server or the main backend process to render.
Build and run it locally from backend/:
./gradlew statusServiceJar
PORT=18080 \
STATUS_TARGET_SITE_URL=http://localhost:5173 \
STATUS_TARGET_API_URL=http://localhost:8080/actuator/health/readiness \
java -jar build/libs/modtale-backend-0.0.1-SNAPSHOT-status.jarThe status image is built with backend/Dockerfile.status and backend/cloudbuild-status.yml as modtale-status. Production CI deploys it to an always-on, single-instance Cloud Run service and maintains the status.modtale.net domain mapping. The main frontend /status path redirects to PUBLIC_STATUS_URL (https://status.modtale.net by default).
Ready to contribute? Follow these steps to get Modtale running on your local machine.
- Node.js: v22.12.0 or higher.
- Java JDK: Version 21 (Amazon Corretto, Eclipse Temurin, or standard OpenJDK).
- MongoDB: A local instance running on port
27017, or a valid MongoDB Atlas connection string.
git clone https://github.com/Modtale/modtale.git
cd modtale
The Spring Boot backend relies on environment variables. You can set these in your IDE's Run Configuration or export them directly in your terminal.
| Variable | Description | Example |
|---|---|---|
MONGODB_URI |
Connection String | mongodb://localhost:27017/modtale |
R2_BUCKET_NAME |
Storage Bucket | modtale-dev |
R2_ACCESS_KEY |
Storage Access Key | your_dev_access_key |
R2_SECRET_KEY |
Storage Secret Key | your_dev_secret_key |
R2_ENDPOINT |
Storage Endpoint URL | https://<accountid>.r2.cloudflarestorage.com |
R2_PUBLIC_DOMAIN |
Optional public storage URL | https://cdn.example.test |
WARDEN_ENABLED |
Must be false locally | false |
PRE_AUTH_SECRET |
Shared random MFA pre-auth signing secret; required for consistent token validation across multiple instances | Set through your deployment secret manager |
STATUS_DISCORD_WEBHOOK_URL |
Optional Discord webhook for the continually updated status mirror | https://discord.com/api/webhooks/... |
STATUS_CHECKER_ENABLED |
Opt into the legacy embedded backend checker | false |
If PRE_AUTH_SECRET is unset, the backend generates a random secret for that process. In-flight MFA sign-ins will need to restart after a backend restart. Use the same configured secret on every instance of a deployment.
Detached status service variables:
| Variable | Description | Default |
|---|---|---|
PUBLIC_STATUS_URL |
Frontend redirect target for /status |
https://status.modtale.net |
STATUS_TARGET_SITE_URL |
Main site URL checked by the detached service | https://modtale.net |
STATUS_TARGET_API_URL |
API health URL checked by the detached service | https://api.modtale.net/actuator/health/readiness |
STATUS_MONGODB_URI |
Optional status-service Mongo URI; falls back to MONGODB_URI |
empty |
STATUS_R2_BUCKET_NAME / STATUS_R2_ACCESS_KEY / STATUS_R2_SECRET_KEY / STATUS_R2_ENDPOINT |
Optional status-service R2 credentials; each falls back to the main R2 variable | empty |
STATUS_SNAPSHOT_PATH |
Local fallback history cache file | /tmp/modtale-status-snapshot.json |
STATUS_DEGRADED_LATENCY |
Probe latency above which a service is degraded | 2s |
STATUS_STALE_AFTER |
Maximum age of a sample before readiness fails | 3m |
STATUS_REQUEST_TIMEOUT |
Probe timeout for HTTP, Mongo, and R2 checks | 5s |
STATUS_REFRESH_INTERVAL_MS |
Probe interval | 60000 |
STATUS_CORS_ALLOWED_ORIGINS |
Allowed origins for status API reads | * |
Note on Warden: The "Warden" malware and security scanner is proprietary to protect our threat-detection logic. You must set
WARDEN_ENABLED=falseto run the backend locally. This enables a "Mock Mode" where file uploads bypass the scanner and automatically return a mock "CLEAN" status.
(Optional) OAuth Variables:
To test social logins, provide each provider's client ID and secret (for example,
GITHUB_CLIENT_ID / GITHUB_CLIENT_SECRET). Hytale uses the registered Modtale
client ID by default and requires HYTALE_CLIENT_SECRET; its production callback
is https://api.modtale.net/login/oauth2/code/hytale.
Open a terminal in the backend/ directory and use the Gradle wrapper.
cd backend
# Linux/Mac
./gradlew bootRun
# Windows
gradlew.bat bootRun
The API will start and listen on http://localhost:8080.
Create a .env file inside the frontend/ directory to point the React client to your local API.
File: frontend/.env
PUBLIC_API_URL=http://localhost:8080/api/v1
Next, open a separate terminal, install the Node dependencies, and start the Astro development server.
cd frontend
npm install
npm run dev
The web client is now accessible at http://localhost:5173!
The launcher/ project is a native Java 21 JavaFX client for installing Modtale projects into a local Hytale mods folder. It does not use Electron.
cd launcher
./gradlew runThe launcher lets users search the Modtale catalog, install the latest compatible version, include required or optional dependencies, check installed projects for updates, apply updates, and point the app at the correct Hytale mods folder.
Self-contained native packages are built by default:
cd launcher
./gradlew buildPackage outputs land in launcher/build/distributions/. Windows builds produce an .exe installer, macOS builds produce a .dmg, and Linux builds produce an .AppImage. Each package embeds the required Java runtime, so end users do not need Java installed. Build on each target OS, or use a CI matrix, to produce all three platform artifacts.
This project is licensed under the GNU Affero General Public License v3.0 (AGPLv3).
Modtale is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This ensures that the platform remains open and accessible to the Hytale community forever.
- Docs: modtale.net/api-docs
- Discord: Join the Server
- X (Twitter): @modtalenet
- Bluesky: @modtale.net
We welcome contributions from the community! Whether it's a bug fix, a new feature, or documentation improvements, please refer to our CONTRIBUTING.md for coding guidelines and pull request instructions.
© 2026 Modtale. The Hytale Community Repository.