krz/brand-bench

A dynamic brand documentation generator with Ollama integration.

clone: git clone https://gitbay.org/krz/brand-bench.git

109cfef2ae202d32677032ecff1f4fcc12d30e49

unsigned

author: Christian Cleberg <hello@cleberg.net> · 2026-04-19T03:57:00Z

clarify ollama settings in docker environments
 src/components/SettingsPanel.tsx |  8 +++++---
 src/engine/aiGenerator.ts        | 11 ++++++++---
 src/hooks/useSettings.ts         |  2 +-
 3 files changed, 14 insertions(+), 7 deletions(-)

diff --git a/src/components/SettingsPanel.tsx b/src/components/SettingsPanel.tsx
index bb44c74..fd0b15e 100644
--- a/src/components/SettingsPanel.tsx
+++ b/src/components/SettingsPanel.tsx
@@ -86,7 +86,7 @@ export function SettingsPanel({ settings, onChange, onClose }: Props) {
                     onChange={e => setUrl(e.target.value)}
                     onBlur={commitUrl}
                     onKeyDown={e => e.key === 'Enter' && commitUrl()}
-                    placeholder="http://localhost:11434"
+                    placeholder="empty = same-origin proxy (recommended)"
                     spellCheck={false}
                   />
                   <button
@@ -147,8 +147,10 @@ export function SettingsPanel({ settings, onChange, onClose }: Props) {
               Install from <strong>ollama.com</strong>, then pull any model to get started.
             </p>
             <p>
-              If connection fails, ensure Ollama is running and CORS is open:<br />
-              <code>OLLAMA_ORIGINS=* ollama serve</code>
+              Leave <strong>Server URL</strong> empty to route through the app's
+              own server (works automatically with the Docker setup). For local
+              dev, set it to <code>http://localhost:11434</code> and ensure CORS
+              is open: <code>OLLAMA_ORIGINS=* ollama serve</code>
             </p>
           </div>
         </div>
diff --git a/src/engine/aiGenerator.ts b/src/engine/aiGenerator.ts
index 3cd9d5e..5648ec9 100644
--- a/src/engine/aiGenerator.ts
+++ b/src/engine/aiGenerator.ts
@@ -84,7 +84,10 @@ export async function generateWithAI(
   settings: OllamaSettings,
   signal?: AbortSignal,
 ): Promise<BrandOutputs> {
-  const url = `${settings.baseUrl.replace(/\/$/, '')}/api/chat`;
+  // Empty baseUrl means "same origin" — nginx proxies /api/ to Ollama internally.
+  // A full URL (e.g. http://localhost:11434) is used as-is for local dev.
+  const base = settings.baseUrl ? settings.baseUrl.replace(/\/$/, '') : '';
+  const url = `${base}/api/chat`;
 
   let res: Response;
   try {
@@ -104,7 +107,8 @@ export async function generateWithAI(
     });
   } catch (err) {
     if ((err as Error).name === 'AbortError') throw err;
-    throw new Error(`Cannot reach Ollama at ${settings.baseUrl}. Is it running?`);
+    const target = settings.baseUrl || '(same origin /api/)';
+    throw new Error(`Cannot reach Ollama at ${target}. Is it running?`);
   }
 
   if (!res.ok) {
@@ -130,7 +134,8 @@ export async function generateWithAI(
 
 // Test connectivity and return available model names
 export async function testOllamaConnection(baseUrl: string): Promise<string[]> {
-  const url = `${baseUrl.replace(/\/$/, '')}/api/tags`;
+  const base = baseUrl ? baseUrl.replace(/\/$/, '') : '';
+  const url = `${base}/api/tags`;
   const res = await fetch(url, { signal: AbortSignal.timeout(5000) });
   if (!res.ok) throw new Error(`Ollama responded with ${res.status}`);
   const data = await res.json() as { models?: Array<{ name: string }> };
diff --git a/src/hooks/useSettings.ts b/src/hooks/useSettings.ts
index 2452945..09a8f01 100644
--- a/src/hooks/useSettings.ts
+++ b/src/hooks/useSettings.ts
@@ -8,7 +8,7 @@ export interface OllamaSettings {
 
 const DEFAULTS: OllamaSettings = {
   enabled: false,
-  baseUrl: 'http://localhost:11434',
+  baseUrl: '',   // empty = same-origin proxy (/api/ via nginx); set to http://localhost:11434 for local dev
   model: 'llama3.2',
 };