DIY e-liquid calculator — mix smarter, not harder.
A lightweight, offline-ready web app for crafting custom e-liquid recipes.
🔗 mixmy.cloud/en — try it live, no install or account needed · French version
- "MyMix" — build a recipe from scratch — target your desired outcome (nicotine, PG/VG ratio, water/vodka/PGA) and let the solver calculate the volumes, or enter volumes you already have and see the resulting recipe
- "MixMyMix" — adapt a recipe you already have — describe your current mix and the mix you're aiming for, and the app works out exactly what to add
- Multi-ingredient support — add as many flavor concentrates as needed, with individual PG base ratios
- Nicotine base flexibility — supports PG, VG, or mixed nicotine bases
- PDF, Markdown & JSON export — save and share your recipes
- Fully bilingual — French / English interface
- Fluid background — WebGL fluid simulation + Three.js volumetric smoke, GPU-optimized (30fps cap, Visibility API pause)
- No installation, no account, no data sent anywhere — runs entirely in your browser
Why a local server? The app uses ES modules (
type="module") for Three.js. Browsers block these on thefile://protocol for security reasons — you must serve the project over HTTP(S), even locally.
HTTP or HTTPS? The page sets a
Content-Security-Policywithupgrade-insecure-requests. Safari enforces this even onlocalhostand will fail to load over plainhttp://. Firefox exemptslocalhostand works fine over plain HTTP. Chromium-based browsers (Chrome/Edge) may behave either way depending on the version. The HTTPS method below works in every browser — use it if unsure. The plain-HTTP method is only a quick shortcut for Firefox.
Python 3 and OpenSSL are pre-installed on macOS and most Linux distributions. A self-signed certificate and the serve-https.py launcher are already included in the repo (the certs/ folder is git-ignored; generate it once if missing — see below).
git clone https://github.com/Albabit/MixMyCloud.git
cd MixMyCloud
python3 serve-https.py # serves on https://localhost:8080Then open https://localhost:8080 in your browser. Press Ctrl+C to stop.
One-time trust step (for Safari/Chrome to accept the local certificate):
double-click certs/localhost-cert.pem → in Keychain Access, set the localhost entry to Always Trust. Or, in a terminal:
sudo security add-trusted-cert -d -r trustRoot \
-k /Library/Keychains/System.keychain certs/localhost-cert.pemRegenerate the certificate (only if certs/ is missing)
mkdir -p certs
openssl req -x509 -newkey rsa:2048 -nodes \
-keyout certs/localhost-key.pem -out certs/localhost-cert.pem \
-days 825 -subj "/CN=localhost" \
-addext "subjectAltName=DNS:localhost,IP:127.0.0.1,IP:::1"python3 -m http.server 8080Then open http://localhost:8080 in Firefox.
The included serve-https.py is cross-platform and runs the same way on Windows. You need Python 3 and OpenSSL (OpenSSL ships with Git for Windows — already installed if you used git clone).
git clone https://github.com/Albabit/MixMyCloud.git
cd MixMyCloud
python serve-https.py # serves on https://localhost:8080Then open https://localhost:8080. Press Ctrl+C to stop.
One-time trust step (so Chrome/Edge accept the local certificate):
import certs\localhost-cert.pem into the current user's Trusted Root Certification Authorities store. From a terminal (no admin needed):
certutil -addstore -user Root certs\localhost-cert.pemOr double-click certs\localhost-cert.pem → Install Certificate → Current User → place it in Trusted Root Certification Authorities.
Chrome and Edge use the Windows certificate store, so the step above covers them. Firefox keeps its own store, but Firefox already loads the app fine over plain HTTP (see below).
Regenerate the certificate (only if certs\ is missing)
Run in Git Bash (OpenSSL on PATH):
mkdir -p certs
openssl req -x509 -newkey rsa:2048 -nodes \
-keyout certs/localhost-key.pem -out certs/localhost-cert.pem \
-days 825 -subj "/CN=localhost" \
-addext "subjectAltName=DNS:localhost,IP:127.0.0.1,IP:::1"Option A — Python:
python -m http.server 8080Option B — Node.js:
npx serve .Option C — VS Code (easiest for non-developers):
- Install the Live Server extension
- Open the project folder in VS Code
- Right-click
index.html→ Open with Live Server
Then open the served URL in Firefox.
MixMyCloud/
├── index.html # Single-page app entry point (French)
├── en/index.html # English entry point — same body as index.html (see dev/sync-en.js)
├── style.css # UI styling
├── favicon.ico # Root favicon (browsers request this regardless of <link rel="icon">)
├── robots.txt / sitemap.xml # Search engine indexing
├── .htaccess # HTTPS/canonical-host redirect + cache headers
├── LICENSE # All rights reserved
├── serve-https.py # Local HTTPS dev server (works in every browser)
├── certs/ # Local HTTPS certificate (git-ignored — see "Running locally" above)
├── img/ # Logos & favicon source
├── js/
│ ├── app.js # Core calculator logic & UI (IIFE)
│ ├── ing-row-category.js # Ingredient-row category accent color
│ ├── vapor.js # Three.js smoke background
│ ├── fluid.js # WebGL fluid simulation config
│ ├── fluid-lib.js # WebGL fluid engine (local fork of WebGLFluidEnhanced 0.8.0)
│ └── jspdf.umd.min.js # Vendored jsPDF, used for native PDF export
└── dev/ # Dev-only tooling, not shipped with the app
├── dom-smoke.js # Headless JSDOM smoke-test harness (npm run smoke)
└── sync-en.js # Keeps index.html's and en/index.html's <body> identical
| Layer | Technology |
|---|---|
| UI & logic | Vanilla JavaScript (no framework) |
| 3D smoke | Three.js 0.160.1 via ES module CDN |
| Fluid sim | WebGLFluidEnhanced 0.8.0 (de-minified local fork) |
| PDF export | jsPDF — drawn natively (text/shapes), not a screenshot of the page, so it renders identically across browsers |
| Styling | Pure CSS |
Made with ☕ and curiosity — From France with love 🇫🇷

