diff --git a/apps/app/src/components/layout/sidebar.tsx b/apps/app/src/components/layout/sidebar.tsx
index 82e46044..8476483c 100644
--- a/apps/app/src/components/layout/sidebar.tsx
+++ b/apps/app/src/components/layout/sidebar.tsx
@@ -4,6 +4,7 @@ import { useState, useMemo, useEffect, useCallback, useRef } from "react";
import { cn } from "@/lib/utils";
import { useAppStore, formatShortcut } from "@/store/app-store";
import { CoursePromoBadge } from "@/components/ui/course-promo-badge";
+import { IS_MARKETING } from "@/config/app-config";
import {
FolderOpen,
Plus,
@@ -366,7 +367,7 @@ export function Sidebar() {
if (
event.type === "auto_mode_feature_complete" ||
event.type === "auto_mode_error" ||
- event.type === "auto_mode_feature_started"
+ event.type === "auto_mode_feature_start"
) {
const fetchRunningAgentsCount = async () => {
try {
@@ -853,7 +854,15 @@ export function Sidebar() {
sidebarOpen ? "hidden lg:block" : "hidden"
)}
>
- Automaker
+ {IS_MARKETING ? (
+ <>
+ https://automaker.app
+ >
+ ) : (
+ <>
+ Automaker
+ >
+ )}
{/* Bug Report Button */}
diff --git a/apps/app/src/config/app-config.ts b/apps/app/src/config/app-config.ts
new file mode 100644
index 00000000..6755a303
--- /dev/null
+++ b/apps/app/src/config/app-config.ts
@@ -0,0 +1,6 @@
+/**
+ * Marketing mode flag
+ * When set to true, displays "https://automaker.app" with "maker" in theme color
+ */
+
+export const IS_MARKETING = process.env.NEXT_PUBLIC_IS_MARKETING === "true";
diff --git a/apps/app/src/lib/http-api-client.ts b/apps/app/src/lib/http-api-client.ts
index ba0f4c6b..ed5377bb 100644
--- a/apps/app/src/lib/http-api-client.ts
+++ b/apps/app/src/lib/http-api-client.ts
@@ -33,7 +33,6 @@ import type {
} from "@/types/electron";
import { getGlobalFileBrowser } from "@/contexts/file-browser-context";
-
// Server URL - configurable via environment variable
const getServerUrl = (): string => {
if (typeof window !== "undefined") {
@@ -43,7 +42,6 @@ const getServerUrl = (): string => {
return "http://localhost:3008";
};
-
// Get API key from environment variable
const getApiKey = (): string | null => {
if (typeof window !== "undefined") {
@@ -76,7 +74,10 @@ export class HttpApiClient implements ElectronAPI {
}
private connectWebSocket(): void {
- if (this.isConnecting || (this.ws && this.ws.readyState === WebSocket.OPEN)) {
+ if (
+ this.isConnecting ||
+ (this.ws && this.ws.readyState === WebSocket.OPEN)
+ ) {
return;
}
@@ -103,7 +104,10 @@ export class HttpApiClient implements ElectronAPI {
callbacks.forEach((cb) => cb(data.payload));
}
} catch (error) {
- console.error("[HttpApiClient] Failed to parse WebSocket message:", error);
+ console.error(
+ "[HttpApiClient] Failed to parse WebSocket message:",
+ error
+ );
}
};
@@ -130,7 +134,10 @@ export class HttpApiClient implements ElectronAPI {
}
}
- private subscribeToEvent(type: EventType, callback: EventCallback): () => void {
+ private subscribeToEvent(
+ type: EventType,
+ callback: EventCallback
+ ): () => void {
if (!this.eventCallbacks.has(type)) {
this.eventCallbacks.set(type, new Set());
}
@@ -196,7 +203,9 @@ export class HttpApiClient implements ElectronAPI {
return result.status === "ok" ? "pong" : "error";
}
- async openExternalLink(url: string): Promise<{ success: boolean; error?: string }> {
+ async openExternalLink(
+ url: string
+ ): Promise<{ success: boolean; error?: string }> {
// Open in new tab
window.open(url, "_blank", "noopener,noreferrer");
return { success: true };
@@ -301,7 +310,9 @@ export class HttpApiClient implements ElectronAPI {
async getPath(name: string): Promise {
// Server provides data directory
if (name === "userData") {
- const result = await this.get<{ dataDir: string }>("/api/health/detailed");
+ const result = await this.get<{ dataDir: string }>(
+ "/api/health/detailed"
+ );
return result.dataDir || "/data";
}
return `/data/${name}`;
@@ -313,7 +324,12 @@ export class HttpApiClient implements ElectronAPI {
mimeType: string,
projectPath?: string
): Promise {
- return this.post("/api/fs/save-image", { data, filename, mimeType, projectPath });
+ return this.post("/api/fs/save-image", {
+ data,
+ filename,
+ mimeType,
+ projectPath,
+ });
}
async saveBoardBackground(
@@ -464,14 +480,19 @@ export class HttpApiClient implements ElectronAPI {
output?: string;
}> => this.post("/api/setup/auth-claude"),
- authCodex: (apiKey?: string): Promise<{
+ authCodex: (
+ apiKey?: string
+ ): Promise<{
success: boolean;
requiresManualAuth?: boolean;
command?: string;
error?: string;
}> => this.post("/api/setup/auth-codex", { apiKey }),
- storeApiKey: (provider: string, apiKey: string): Promise<{
+ storeApiKey: (
+ provider: string,
+ apiKey: string
+ ): Promise<{
success: boolean;
error?: string;
}> => this.post("/api/setup/store-api-key", { provider, apiKey }),
@@ -483,7 +504,9 @@ export class HttpApiClient implements ElectronAPI {
hasGoogleKey: boolean;
}> => this.get("/api/setup/api-keys"),
- configureCodexMcp: (projectPath: string): Promise<{
+ configureCodexMcp: (
+ projectPath: string
+ ): Promise<{
success: boolean;
configPath?: string;
error?: string;
@@ -516,8 +539,11 @@ export class HttpApiClient implements ElectronAPI {
this.post("/api/features/get", { projectPath, featureId }),
create: (projectPath: string, feature: Feature) =>
this.post("/api/features/create", { projectPath, feature }),
- update: (projectPath: string, featureId: string, updates: Partial) =>
- this.post("/api/features/update", { projectPath, featureId, updates }),
+ update: (
+ projectPath: string,
+ featureId: string,
+ updates: Partial
+ ) => this.post("/api/features/update", { projectPath, featureId, updates }),
delete: (projectPath: string, featureId: string) =>
this.post("/api/features/delete", { projectPath, featureId }),
getAgentOutput: (projectPath: string, featureId: string) =>
@@ -534,8 +560,16 @@ export class HttpApiClient implements ElectronAPI {
this.post("/api/auto-mode/stop-feature", { featureId }),
status: (projectPath?: string) =>
this.post("/api/auto-mode/status", { projectPath }),
- runFeature: (projectPath: string, featureId: string, useWorktrees?: boolean) =>
- this.post("/api/auto-mode/run-feature", { projectPath, featureId, useWorktrees }),
+ runFeature: (
+ projectPath: string,
+ featureId: string,
+ useWorktrees?: boolean
+ ) =>
+ this.post("/api/auto-mode/run-feature", {
+ projectPath,
+ featureId,
+ useWorktrees,
+ }),
verifyFeature: (projectPath: string, featureId: string) =>
this.post("/api/auto-mode/verify-feature", { projectPath, featureId }),
resumeFeature: (projectPath: string, featureId: string) =>
@@ -559,7 +593,10 @@ export class HttpApiClient implements ElectronAPI {
commitFeature: (projectPath: string, featureId: string) =>
this.post("/api/auto-mode/commit-feature", { projectPath, featureId }),
onEvent: (callback: (event: AutoModeEvent) => void) => {
- return this.subscribeToEvent("auto-mode:event", callback as EventCallback);
+ return this.subscribeToEvent(
+ "auto-mode:event",
+ callback as EventCallback
+ );
},
};
@@ -578,7 +615,11 @@ export class HttpApiClient implements ElectronAPI {
getDiffs: (projectPath: string, featureId: string) =>
this.post("/api/worktree/diffs", { projectPath, featureId }),
getFileDiff: (projectPath: string, featureId: string, filePath: string) =>
- this.post("/api/worktree/file-diff", { projectPath, featureId, filePath }),
+ this.post("/api/worktree/file-diff", {
+ projectPath,
+ featureId,
+ filePath,
+ }),
};
// Git API
@@ -596,20 +637,30 @@ export class HttpApiClient implements ElectronAPI {
stop: () => this.post("/api/suggestions/stop"),
status: () => this.get("/api/suggestions/status"),
onEvent: (callback: (event: SuggestionsEvent) => void) => {
- return this.subscribeToEvent("suggestions:event", callback as EventCallback);
+ return this.subscribeToEvent(
+ "suggestions:event",
+ callback as EventCallback
+ );
},
};
// Spec Regeneration API
specRegeneration: SpecRegenerationAPI = {
- create: (projectPath: string, projectOverview: string, generateFeatures?: boolean) =>
+ create: (
+ projectPath: string,
+ projectOverview: string,
+ generateFeatures?: boolean
+ ) =>
this.post("/api/spec-regeneration/create", {
projectPath,
projectOverview,
generateFeatures,
}),
generate: (projectPath: string, projectDefinition: string) =>
- this.post("/api/spec-regeneration/generate", { projectPath, projectDefinition }),
+ this.post("/api/spec-regeneration/generate", {
+ projectPath,
+ projectDefinition,
+ }),
generateFeatures: (projectPath: string) =>
this.post("/api/spec-regeneration/generate-features", { projectPath }),
stop: () => this.post("/api/spec-regeneration/stop"),
@@ -656,7 +707,10 @@ export class HttpApiClient implements ElectronAPI {
// Agent API
agent = {
- start: (sessionId: string, workingDirectory?: string): Promise<{
+ start: (
+ sessionId: string,
+ workingDirectory?: string
+ ): Promise<{
success: boolean;
messages?: Message[];
error?: string;
@@ -668,9 +722,16 @@ export class HttpApiClient implements ElectronAPI {
workingDirectory?: string,
imagePaths?: string[]
): Promise<{ success: boolean; error?: string }> =>
- this.post("/api/agent/send", { sessionId, message, workingDirectory, imagePaths }),
+ this.post("/api/agent/send", {
+ sessionId,
+ message,
+ workingDirectory,
+ imagePaths,
+ }),
- getHistory: (sessionId: string): Promise<{
+ getHistory: (
+ sessionId: string
+ ): Promise<{
success: boolean;
messages?: Message[];
isRunning?: boolean;
@@ -690,17 +751,24 @@ export class HttpApiClient implements ElectronAPI {
// Templates API
templates = {
- clone: (repoUrl: string, projectName: string, parentDir: string): Promise<{
+ clone: (
+ repoUrl: string,
+ projectName: string,
+ parentDir: string
+ ): Promise<{
success: boolean;
projectPath?: string;
projectName?: string;
error?: string;
- }> => this.post("/api/templates/clone", { repoUrl, projectName, parentDir }),
+ }> =>
+ this.post("/api/templates/clone", { repoUrl, projectName, parentDir }),
};
// Sessions API
sessions = {
- list: (includeArchived?: boolean): Promise<{
+ list: (
+ includeArchived?: boolean
+ ): Promise<{
success: boolean;
sessions?: SessionListItem[];
error?: string;
@@ -730,13 +798,19 @@ export class HttpApiClient implements ElectronAPI {
): Promise<{ success: boolean; error?: string }> =>
this.put(`/api/sessions/${sessionId}`, { name, tags }),
- archive: (sessionId: string): Promise<{ success: boolean; error?: string }> =>
+ archive: (
+ sessionId: string
+ ): Promise<{ success: boolean; error?: string }> =>
this.post(`/api/sessions/${sessionId}/archive`, {}),
- unarchive: (sessionId: string): Promise<{ success: boolean; error?: string }> =>
+ unarchive: (
+ sessionId: string
+ ): Promise<{ success: boolean; error?: string }> =>
this.post(`/api/sessions/${sessionId}/unarchive`, {}),
- delete: (sessionId: string): Promise<{ success: boolean; error?: string }> =>
+ delete: (
+ sessionId: string
+ ): Promise<{ success: boolean; error?: string }> =>
this.httpDelete(`/api/sessions/${sessionId}`),
};
}