Skip to content

Commit ab560d9

Browse files
Eranclaude
andcommitted
v0.0.8 - server config.json support
- Load config.json on startup (when hosted on a server) - serverCfg takes priority over localStorage for all settings - Supports: appName, base, instance, apikey, country, delayMin, delayMax - Settings modal shows notice when server config is active - Add config.example.json as template (config.json is gitignored) - Update README with server deployment instructions Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 4992e80 commit ab560d9

File tree

4 files changed

+66
-15
lines changed

4 files changed

+66
-15
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
versions/
22
.claude/
3+
config.json

README.md

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,34 @@ A browser-based WhatsApp management interface built on top of [Evolution API v2]
5757

5858
---
5959

60+
## Server Deployment — `config.json`
61+
62+
When hosting on a web server, you can pre-configure all settings centrally using a `config.json` file placed next to `index.html`. Users won't need to touch Settings — everything is loaded automatically.
63+
64+
Copy `config.example.json``config.json` and fill in your values:
65+
66+
```json
67+
{
68+
"appName": "My Business",
69+
"base": "https://your-evolution-api-server.com",
70+
"instance": "MyInstance",
71+
"apikey": "your-api-key-here",
72+
"country": "IL",
73+
"delayMin": 1,
74+
"delayMax": 5
75+
}
76+
```
77+
78+
Any field can be omitted — omitted fields fall back to the user's local browser settings.
79+
80+
> **Note:** `config.json` is listed in `.gitignore` so your credentials are never committed to the repo.
81+
82+
---
83+
6084
## Security
6185

62-
- All credentials (API key, instance name, server URL) are stored exclusively in your **browser's localStorage**
63-
- Nothing is hardcoded — the repo contains zero credentials
86+
- Credentials are stored in your **browser's localStorage** (local use) or in `config.json` on your server (hosted use)
87+
- Nothing is hardcoded in the source — the repo contains zero credentials
6488
- Credentials never leave your browser except in direct API calls to your own Evolution API server
6589

6690
---

config.example.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"appName": "My Business",
3+
"base": "https://your-evolution-api-server.com",
4+
"instance": "MyInstance",
5+
"apikey": "your-api-key-here",
6+
"country": "IL",
7+
"delayMin": 1,
8+
"delayMax": 5
9+
}

index.html

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,9 @@ <h2 class="text-base font-bold text-gray-900">Connection Settings</h2>
7979
</button>
8080
</div>
8181
<div class="px-6 py-5 space-y-4">
82+
<div id="cfg-server-notice" class="hidden bg-blue-50 border border-blue-200 text-blue-700 text-xs rounded-lg px-3 py-2">
83+
⚙ Server configuration loaded from <code>config.json</code> — those values take priority over local settings.
84+
</div>
8285
<div>
8386
<label class="block text-sm font-medium text-gray-700 mb-1.5">Business / App Name</label>
8487
<input id="cfg-app-name" type="text" placeholder="WhatsApp Manager" class="w-full border border-gray-300 rounded-lg px-3.5 py-2.5 text-sm"/>
@@ -1091,7 +1094,9 @@ <h3 class="text-sm font-semibold text-gray-800">Privacy Settings</h3>
10911094
</div>
10921095

10931096
<script>
1094-
// ── CONFIG (localStorage-backed) ──────────────────────────────────────────
1097+
// ── CONFIG (server config.json → localStorage → defaults) ────────────────
1098+
let serverCfg = {}; // populated from config.json if present
1099+
10951100
const DEFAULTS = {
10961101
base: '',
10971102
instance: '',
@@ -1103,14 +1108,15 @@ <h3 class="text-sm font-semibold text-gray-800">Privacy Settings</h3>
11031108
};
11041109

11051110
function getCfg() {
1111+
const s = serverCfg;
11061112
return {
1107-
base: localStorage.getItem('wa_base') || '',
1108-
instance: localStorage.getItem('wa_instance') || '',
1109-
apikey: localStorage.getItem('wa_apikey') || '',
1110-
country: localStorage.getItem('wa_country') || 'IL',
1111-
delayMin: parseFloat(localStorage.getItem('wa_delay_min')) || 1,
1112-
delayMax: parseFloat(localStorage.getItem('wa_delay_max')) || 3,
1113-
appName: localStorage.getItem('wa_app_name') || 'WhatsApp Manager',
1113+
appName: s.appName || localStorage.getItem('wa_app_name') || DEFAULTS.appName,
1114+
base: s.base || localStorage.getItem('wa_base') || '',
1115+
instance: s.instance || localStorage.getItem('wa_instance') || '',
1116+
apikey: s.apikey || localStorage.getItem('wa_apikey') || '',
1117+
country: s.country || localStorage.getItem('wa_country') || DEFAULTS.country,
1118+
delayMin: s.delayMin != null ? s.delayMin : (parseFloat(localStorage.getItem('wa_delay_min')) || DEFAULTS.delayMin),
1119+
delayMax: s.delayMax != null ? s.delayMax : (parseFloat(localStorage.getItem('wa_delay_max')) || DEFAULTS.delayMax),
11141120
};
11151121
}
11161122

@@ -1131,6 +1137,12 @@ <h3 class="text-sm font-semibold text-gray-800">Privacy Settings</h3>
11311137

11321138
function openConfig() {
11331139
const cfg = getCfg();
1140+
const serverNotice = document.getElementById('cfg-server-notice');
1141+
if (Object.keys(serverCfg).length > 0) {
1142+
serverNotice.classList.remove('hidden');
1143+
} else {
1144+
serverNotice.classList.add('hidden');
1145+
}
11341146
document.getElementById('cfg-app-name').value = cfg.appName !== 'WhatsApp Manager' ? cfg.appName : '';
11351147
document.getElementById('cfg-base').value = cfg.base;
11361148
document.getElementById('cfg-instance').value = cfg.instance;
@@ -1231,11 +1243,16 @@ <h3 class="text-sm font-semibold text-gray-800">Privacy Settings</h3>
12311243
if (e.target === this) closeConfig();
12321244
});
12331245

1234-
// Init config on load — auto-open settings if not yet configured
1235-
applyConfig();
1236-
if (!localStorage.getItem('wa_apikey') || !localStorage.getItem('wa_base')) {
1237-
openConfig();
1238-
}
1246+
// Init — load config.json (if on a server), then apply and open settings if needed
1247+
(async () => {
1248+
try {
1249+
const res = await fetch('config.json');
1250+
if (res.ok) serverCfg = await res.json();
1251+
} catch (e) { /* no config.json — local file usage, that's fine */ }
1252+
applyConfig();
1253+
const cfg = getCfg();
1254+
if (!cfg.apikey || !cfg.base) openConfig();
1255+
})();
12391256

12401257
// ── PHONE VALIDATION (libphonenumber-js) ──────────────────────────────────
12411258
function validatePhone(raw) {

0 commit comments

Comments
 (0)