Thank you for your interest in contributing to Mori! Whether you want to fix bugs, add UI features, expand language translations, or improve documentation, your help is welcome.
- Code of Conduct & Etiquette
- How Can I Contribute?
- Development & Build Guide
- Architecture & Scraper Engine
- Contributing Translations (i18n)
- CSS & Styling Architecture
- Submitting a Pull Request
- Be Respectful: Treat everyone in the community with courtesy and respect.
- Keep it Clean: Mori is a free, ad-free, and tracker-free application. We will strictly reject any PR that introduces telemetry, ads, trackers, or monetization schemes.
- Respect Copyleft: Mori is licensed under GPL-3.0. All code contributions must honor this copyleft license.
- Check existing GitHub Issues before opening a new one to prevent duplicates.
- Clearly specify your Platform & OS version (Android / macOS / Windows / iOS), Mori Version, and the Source URL causing the error.
Mori supports 9 languages (English, Indonesian, Japanese, Korean, Simplified Chinese, Arabic with RTL, Russian, Tagalog, and Hindi). If you want to refine translations or add a new locale, edit the dictionary files in public/js/i18n/.
Feel free to refine the CSS design system, optimize MoriPlayer controls, enhance glassmorphism effects, or add responsive styling.
- Node.js:
v18.xor higher (Nodev20+recommended) - npm:
v9.xor higher - Git: Installed and configured
- Android: Android Studio, Android SDK (API 34+), NDK (
28.2+), Java 17. - Desktop (macOS & Windows): Rust toolchain (
rustup,cargo), Tauri CLI. - iOS: macOS with Xcode 15+ and CocoaPods (
gem install cocoapods).
-
Clone your fork:
git clone https://github.com/YOUR_USERNAME/Mori.git cd Mori -
Install dependencies:
npm install
Mori uses CapacitorJS paired with a native OkHttp bridge (MainActivity.java) to handle network requests and bypass WebView CORS restrictions.
# Build Debug APK
npm run build:android
# Build Signed Release APK (Requires keystore configured below)
npm run build:android:releaseOutput location: android/app/build/outputs/apk/release/Mori v{VERSION}.apk
# 1. Sync web assets to Android
npx cap sync android
# 2. Compile via Gradle
cd android
./gradlew assembleReleasekeytool -genkey -v -keystore android/app/release.keystore -alias mori \
-keyalg RSA -keysize 2048 -validity 10000 \
-storepass android123 -keypass android123 \
-dname "CN=Mori, OU=Development, O=MoriApp, L=Unknown, ST=Unknown, C=ID"Configure signingConfigs in android/app/build.gradle:
android {
signingConfigs {
release {
storeFile file('release.keystore')
storePassword 'android123'
keyAlias 'mori'
keyPassword 'android123'
}
}
buildTypes {
release {
signingConfig signingConfigs.release
}
}
}Mori Desktop is powered by Tauri v2 (Rust) for minimal resource usage and instant startup times.
npm run tauri:devnpm run tauri:buildOutput artifacts:
- macOS:
src-tauri/target/release/bundle/macos/Mori.app&.dmg/.tar.gz - Windows:
src-tauri/target/release/bundle/msi/*.msi&.exesetup bundle
# 1. Sync web assets & CocoaPods dependencies
npx cap sync ios
# 2. Open Xcode workspace
npx cap open ios
# 3. Select target device and press Run (Cmd + R)# Single-command build
npm run build:ios:ipaManual steps:
# 1. Sync assets
npx cap sync ios
# 2. Compile archive without code signing
xcodebuild -workspace ios/App/App.xcworkspace -scheme App -configuration Release \
-sdk iphoneos -archivePath build/Mori.xcarchive archive \
CODE_SIGNING_ALLOWED=NO CODE_SIGNING_REQUIRED=NO CODE_SIGN_IDENTITY=""
# 3. Package into IPA
mkdir -p Payload && cp -r build/Mori.xcarchive/Products/Applications/App.app Payload/
zip -r "Mori.ipa" Payload && rm -rf Payload build- Frontend: Vanilla ES6 JavaScript + modern CSS design system located in
public/. - Scraper Runtime: The core scraping engine is compiled via esbuild into
public/js/scrapers/bundle.jsas an IIFE bundle containing all 16 platform engines. - HTTP Layer: Cross-origin requests are routed through
public/js/scrapers/httpHelper.js, utilizing native OkHttp on Android and native Rust HTTP on Desktop to bypass CORS.
Note
Scraper Core Contributions: The scraper sources are maintained privately in src-scrapers/ to deter low-effort ad-injected clones and scrapers abuse. The public repository runs from the precompiled public/js/scrapers/bundle.js. Honest developers who wish to fix broken endpoints or suggest scraper algorithms are encouraged to discuss them in an issue or PR with the author.
Mori supports multiple languages out-of-the-box (en, id, ja, ko, zh, ar, ru, tl, hi). All language strings are modularized into individual locale files located in:
public/js/i18n/
├── locales/
│ ├── en.js # English (Source of Truth / Fallback)
│ ├── id.js # Bahasa Indonesia
│ ├── ja.js # 日本語 (Japanese)
│ ├── ko.js # 한국어 (Korean)
│ ├── zh.js # 中文 (Simplified Chinese)
│ ├── ar.js # العربية (Arabic with RTL)
│ ├── ru.js # Русский (Russian)
│ ├── tl.js # Tagalog (Filipino)
│ └── hi.js # हिन्दी (Hindi)
└── index.js # Translation registry & fallback helper
- Open the relevant file in
public/js/i18n/locales/<lang>.js. - Update the translation value for the desired key.
- Verify the changes by switching to that language in Mori Settings.
- Create a new locale file in
public/js/i18n/locales/<new_code>.js(e.g.es.jsfor Spanish). - Copy the key structure from
en.jsand translate the values. - Import and register the new locale in
public/js/i18n/index.js:import es from "./locales/es.js"; export const translations = { ..., es };
- Add the language name to
langNamesinpublic/js/modules/settings/language.jsand the language option inpublic/index.html.
Tip
Safe Fallback: If a key is not yet translated in your locale, Mori automatically falls back to English (en), preventing blank text or broken UI.
Mori's stylesheet is modularized into domain-focused files under public/css/:
public/css/
├── variables.css # Design tokens, themes (dark/light), font, speed, glass, corner presets
├── base.css # Reset, body typography, layout wrappers, bottom navigation
├── components.css # Reusable buttons, custom toasts, floating progress toasts, badges
├── home.css # Main URL input bar, batch input, skeleton loader, media cards
├── history.css # History items, summary stats card, thumbnail overlay & spinners
├── settings.css # Menu lists, subpage slide transitions, dropdowns, live BG controls
├── modals.css # Universal modal backdrops, PIN keypad, guide, confirm, batch modal
├── rtl.css # Right-to-Left (RTL) overrides for Arabic layout
└── style.css # Master stylesheet entry point importing all modules
When modifying styles:
- Edit the specific component/page file instead of cluttering a single file.
- Design tokens and CSS custom properties live in
variables.css. - Ensure all interactive controls support both dark and light themes.
- Fork the repo and create a descriptive branch:
git checkout -b feat/your-feature-name
- Keep your commits clean and follow conventional commit syntax (
feat: ...,fix: ...,docs: ...). - Ensure the project builds cleanly without lint or syntax errors.
- Push to your fork and submit a Pull Request to
main. - Describe what your PR changes, why it is needed, and how it was verified.
Developed with ❤️ by coflyn.
GitHub: https://github.com/coflyn
Instagram: @_coflyn