Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 13 additions & 13 deletions BRANDING.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@
| **Stage Label** | Dev (development only) |
| **Display Name** | OK Code |
| **Version** | 0.0.1 |
| **Tagline** | `[TBD]` |
| **One-liner Description** | `[TBD]` |
| **Tagline** | A Minimal Web GUI for Coding Agents |
| **One-liner Description** | Chat with Codex and Claude in a modern web UI. Git worktree isolation, diff review, integrated terminal, and more. |
| **Parent Organization** | OpenKnots |
| **Website URL** | `[TBD]` |
| **Website URL** | `[TBD]` |
| **Repository** | `OpenKnots/okcode` |

### Brand Voice & Tone
Expand All @@ -27,8 +27,8 @@
| **Tone** | Confident but not arrogant; technical but accessible |
| **Copy Style** | Action-oriented imperatives ("New Thread", "Terminal", "Settings"); no unnecessary filler words |
| **Audience** | Software engineers and technical users |
| **Emoji Usage** | `[TBD — currently none in the UI]` |
| **Error/Empty States Voice** | `[TBD]` |
| **Emoji Usage** | None in UI copy; reserved for user-generated content only |
| **Error/Empty States Voice** | Concise and helpful; state what happened and what to do next, no blame or humor |

---

Expand Down Expand Up @@ -256,7 +256,7 @@ A subtle **fractal noise SVG overlay** is applied to `body::after` at **3.5% opa
| Disabled opacity | `opacity-64` |
| Disabled interaction | `pointer-events: none` |
| Placeholder text | `muted-foreground/72` (72% opacity) |
| Contrast standard | `[TBD — WCAG level target]` |
| Contrast standard | WCAG 2.1 AA minimum |

---

Expand Down Expand Up @@ -321,7 +321,7 @@ The app includes bespoke SVG icons for:

| Property | Value |
| -------------------------------- | ------- |
| `prefers-reduced-motion` support | `[TBD]` |
| `prefers-reduced-motion` support | Respect; disable non-essential animations when set |
| Global animation toggle | `[TBD]` |

---
Expand Down Expand Up @@ -385,19 +385,19 @@ Built with:

The following need to be provided/decided:

- [ ] **Tagline** — short memorable phrase
- [ ] **One-liner description** — for app stores, meta tags, social cards
- [x] **Tagline** — "A Minimal Web GUI for Coding Agents"
- [x] **One-liner description** — see Brand Identity table above
- [x] **WCAG contrast target** — AA minimum
- [x] **Reduced motion support** — respect `prefers-reduced-motion`
- [x] **Emoji policy** — none in UI copy
- [x] **Error/empty state voice** — concise and helpful
- [ ] **Logo mark description** — what does the mark depict?
- [ ] **Logo usage guidelines** — minimum size, clear space, do's and don'ts
- [ ] **Heading type scale** — H1–H6 sizes and weights
- [ ] **WCAG contrast target** — AA or AAA?
- [ ] **Reduced motion support** — respect `prefers-reduced-motion`?
- [ ] **Website URL**
- [ ] **Social media handles / links**
- [ ] **App store descriptions**
- [ ] **Open Graph / social card image**
- [ ] **Brand color as hex** — the primary `oklch(0.488 0.217 264)` converts to approximately **#2b4acb** (a deep blue-violet); confirm this is the intended brand hex
- [ ] **Secondary brand color** — is there a distinct secondary brand color beyond the neutral system?
- [ ] **Emoji policy** — use in UI copy, notifications, etc.?
- [ ] **Error/empty state voice** — tone for error messages, empty states, onboarding
- [ ] **Icon stroke width** — confirm Lucide default (2) or custom
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2026 OpenKnot
Copyright (c) 2026 OpenKnots

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
6 changes: 4 additions & 2 deletions apps/desktop/scripts/electron-launcher.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@ import { dirname, join, resolve } from "node:path";
import { fileURLToPath } from "node:url";

const isDevelopment = Boolean(process.env.VITE_DEV_SERVER_URL);
const APP_DISPLAY_NAME = isDevelopment ? "OK Code (Dev)" : "OK Code";
const APP_BUNDLE_ID = "com.okcode.okcode";
// Keep in sync with APP_BASE_NAME from @okcode/shared/brand
const APP_BASE_NAME = "OK Code";
const APP_DISPLAY_NAME = isDevelopment ? `${APP_BASE_NAME} (Dev)` : APP_BASE_NAME;
const APP_BUNDLE_ID = "com.openknots.okcode";
const LAUNCHER_VERSION = 1;

const __dirname = dirname(fileURLToPath(import.meta.url));
Expand Down
5 changes: 3 additions & 2 deletions apps/desktop/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import type {
PreviewTabsState,
} from "@okcode/contracts";
import { autoUpdater } from "electron-updater";
import { APP_BASE_NAME } from "@okcode/shared/brand";

import type { ContextMenuItem } from "@okcode/contracts";
import { NetService } from "@okcode/shared/Net";
Expand Down Expand Up @@ -79,8 +80,8 @@ const STATE_DIR = Path.join(BASE_DIR, "userdata");
const DESKTOP_SCHEME = "okcode";
const ROOT_DIR = Path.resolve(__dirname, "../../..");
const isDevelopment = Boolean(process.env.VITE_DEV_SERVER_URL);
const APP_DISPLAY_NAME = isDevelopment ? "OK Code (Dev)" : "OK Code";
const APP_USER_MODEL_ID = "com.okcode.okcode";
const APP_DISPLAY_NAME = isDevelopment ? `${APP_BASE_NAME} (Dev)` : APP_BASE_NAME;
const APP_USER_MODEL_ID = "com.openknots.okcode";
const USER_DATA_DIR_NAME = isDevelopment ? "okcode-dev" : "okcode";
const LEGACY_USER_DATA_DIR_NAME = isDevelopment ? "T3 Code (Dev)" : "T3 Code (Alpha)";
const COMMIT_HASH_PATTERN = /^[0-9a-f]{7,40}$/i;
Expand Down
2 changes: 1 addition & 1 deletion apps/marketing/components/workflows-section.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ function ApiMockup() {
return (
<div className="flex items-center justify-center h-full">
<div className="bg-secondary/50 rounded-lg px-4 py-2 border border-border/50">
<span className="text-xs font-mono text-muted-foreground">OK CODE API</span>
<span className="text-xs font-mono text-muted-foreground">OK Code API</span>
</div>
</div>
);
Expand Down
5 changes: 3 additions & 2 deletions apps/server/src/checkpointing/Layers/CheckpointStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { GitCommandError } from "../../git/Errors.ts";
import { GitCore } from "../../git/Services/GitCore.ts";
import { CheckpointStore, type CheckpointStoreShape } from "../Services/CheckpointStore.ts";
import { CheckpointRef } from "@okcode/contracts";
import { GIT_IDENTITY_NAME } from "@okcode/shared/brand";

const makeCheckpointStore = Effect.gen(function* () {
const fs = yield* FileSystem.FileSystem;
Expand Down Expand Up @@ -98,9 +99,9 @@ const makeCheckpointStore = Effect.gen(function* () {
const commitEnv: NodeJS.ProcessEnv = {
...process.env,
GIT_INDEX_FILE: tempIndexPath,
GIT_AUTHOR_NAME: "OK Code",
GIT_AUTHOR_NAME: GIT_IDENTITY_NAME,
GIT_AUTHOR_EMAIL: "okcode@users.noreply.github.com",
GIT_COMMITTER_NAME: "OK Code",
GIT_COMMITTER_NAME: GIT_IDENTITY_NAME,
GIT_COMMITTER_EMAIL: "okcode@users.noreply.github.com",
};

Expand Down
4 changes: 3 additions & 1 deletion apps/server/src/provider/codexCliVersion.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { APP_BASE_NAME } from "@okcode/shared/brand";

const CODEX_VERSION_PATTERN = /\bv?(\d+\.\d+(?:\.\d+)?(?:-[0-9A-Za-z.-]+)?)\b/;

export const MINIMUM_CODEX_CLI_VERSION = "0.37.0";
Expand Down Expand Up @@ -137,5 +139,5 @@ export function isCodexCliVersionSupported(version: string): boolean {

export function formatCodexCliUpgradeMessage(version: string | null): string {
const versionLabel = version ? `v${version}` : "the installed version";
return `Codex CLI ${versionLabel} is too old for OK Code. Upgrade to v${MINIMUM_CODEX_CLI_VERSION} or newer and restart OK Code.`;
return `Codex CLI ${versionLabel} is too old for ${APP_BASE_NAME}. Upgrade to v${MINIMUM_CODEX_CLI_VERSION} or newer and restart ${APP_BASE_NAME}.`;
}
3 changes: 2 additions & 1 deletion apps/web/src/branding.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export const APP_BASE_NAME = "OK Code";
export { APP_BASE_NAME } from "@okcode/shared/brand";

export const APP_STAGE_LABEL = import.meta.env.DEV ? "Dev" : "";
export const APP_DISPLAY_NAME = APP_STAGE_LABEL
? `${APP_BASE_NAME} (${APP_STAGE_LABEL})`
Expand Down
4 changes: 2 additions & 2 deletions apps/web/src/components/ChatHomeEmptyState.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
import { useCallback, useMemo, useState } from "react";

import { useAppSettings } from "../appSettings";
import { APP_DISPLAY_NAME } from "../branding";
import { APP_BASE_NAME, APP_DISPLAY_NAME } from "../branding";
import { isElectron } from "../env";
import { useHandleNewThread } from "../hooks/useHandleNewThread";
import { serverConfigQueryOptions } from "../lib/serverReactQuery";
Expand Down Expand Up @@ -363,7 +363,7 @@ export function ChatHomeEmptyState() {
Launch a premium coding workspace with reliable agent sessions built in.
</h1>
<p className="mt-5 max-w-2xl text-sm leading-7 text-muted-foreground sm:text-base">
OK Code keeps threads tied to real repositories, preserves provider state,
{APP_BASE_NAME} keeps threads tied to real repositories, preserves provider state,
and gives your desktop a calmer control surface for deep, multi-session
work.
</p>
Expand Down
8 changes: 4 additions & 4 deletions apps/web/src/components/Sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ import {
useAppSettings,
} from "../appSettings";
import { isElectron } from "../env";
import { APP_VERSION } from "../branding";
import { APP_BASE_NAME, APP_VERSION } from "../branding";
import { cn, isLinuxPlatform, isMacPlatform, newCommandId, newProjectId } from "../lib/utils";
import { useStore } from "../store";
import { shortcutLabelForCommand } from "../keybindings";
Expand Down Expand Up @@ -1805,8 +1805,8 @@ export default function Sidebar() {
render={
<div className="wordmark-stitch flex min-w-0 flex-1 items-center justify-center gap-1.5 cursor-pointer mx-auto px-3 py-1.5 rounded-lg">
<OkCodeMark className="size-6 text-foreground drop-shadow-[0_1px_0_rgba(255,255,255,0.15)]" />
<span className="truncate text-base font-semibold tracking-wide text-foreground uppercase drop-shadow-[0_1px_0_rgba(255,255,255,0.15)]">
OK Code
<span className="truncate text-base font-semibold tracking-wide text-foreground drop-shadow-[0_1px_0_rgba(255,255,255,0.15)]">
{APP_BASE_NAME}
</span>
</div>
}
Expand Down Expand Up @@ -1860,7 +1860,7 @@ export default function Sidebar() {
onClick={() => {
toastManager.add({
type: "info",
title: `OK Code ${serverUpdateInfo.latestVersion} available`,
title: `${APP_BASE_NAME} ${serverUpdateInfo.latestVersion} available`,
description: `Update with: npm install -g okcodes@latest`,
});
}}
Expand Down
4 changes: 4 additions & 0 deletions packages/shared/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@
"./skillCatalog": {
"types": "./src/skillCatalog.ts",
"import": "./src/skillCatalog.ts"
},
"./brand": {
"types": "./src/brand.ts",
"import": "./src/brand.ts"
}
},
"scripts": {
Expand Down
13 changes: 13 additions & 0 deletions packages/shared/src/brand.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/**
* Canonical brand constants for the OK Code product.
*
* Import from `@okcode/shared/brand` in any workspace package.
* The web app's `branding.ts` re-exports these with Vite-specific additions
* (stage labels, build-time version injection).
*/

/** Base product name — use for display text that should not include a stage label. */
export const APP_BASE_NAME = "OK Code";

/** Git committer identity used by OK Code's internal operations (checkpoints, etc.). */
export const GIT_IDENTITY_NAME = APP_BASE_NAME;
5 changes: 3 additions & 2 deletions scripts/build-desktop-artifact.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import rootPackageJson from "../package.json" with { type: "json" };
import desktopPackageJson from "../apps/desktop/package.json" with { type: "json" };
import serverPackageJson from "../apps/server/package.json" with { type: "json" };

import { APP_BASE_NAME } from "@okcode/shared/brand";
import { BRAND_ASSET_PATHS } from "./lib/brand-assets.ts";
import { resolveCatalogDependencies } from "./lib/resolve-catalog.ts";

Expand Down Expand Up @@ -519,7 +520,7 @@ const createBuildConfig = Effect.fn("createBuildConfig")(function* (
macEntitlementsPlistAbsolutePath: string | undefined,
) {
const buildConfig: Record<string, unknown> = {
appId: "com.okcode.okcode",
appId: "com.openknots.okcode",
productName,
artifactName: "OK-Code-${version}-${arch}.${ext}",
directories: {
Expand Down Expand Up @@ -736,7 +737,7 @@ const buildDesktopArtifact = Effect.fn("buildDesktopArtifact")(function* (
build: yield* createBuildConfig(
options.platform,
options.target,
desktopPackageJson.productName ?? "OK Code",
desktopPackageJson.productName ?? APP_BASE_NAME,
options.signed,
options.signed && options.platform === "mac" ? macEntitlementsPlistAbsolutePath : undefined,
),
Expand Down
13 changes: 3 additions & 10 deletions scripts/generate-brand-assets.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
#!/usr/bin/env python3
"""Regenerate favicons and desktop icon PNGs/ICOs from assets/source/okcode-mark-512.png.

Windows `.ico` files use `assets/source/openknot-mark-512.png` when present (OpenKnots org
mark); otherwise they fall back to the OK Code mark.
All platforms (macOS, Windows, Linux, iOS, web) use the same OK Code mark as their source.

Requires Pillow (`python3 -m pip install pillow` if missing).
Run from repository root: python3 scripts/generate-brand-assets.py
Expand All @@ -22,7 +21,6 @@

ROOT = Path(__file__).resolve().parents[1]
SRC = ROOT / "assets/source/okcode-mark-512.png"
OPENKNOT_MARK_SRC = ROOT / "assets/source/openknot-mark-512.png"

ICO_SIZES_WEB = (16, 32, 48)
ICO_SIZES_DESKTOP = (16, 32, 48, 64, 128, 256)
Expand Down Expand Up @@ -99,11 +97,6 @@ def main() -> None:

img = Image.open(SRC).convert("RGBA")

if OPENKNOT_MARK_SRC.exists():
windows_icon_source = Image.open(OPENKNOT_MARK_SRC).convert("RGBA")
else:
windows_icon_source = img

# Master 1024 for desktop / marketing hero
mark_1024 = resize(img, 1024)
prod_dir = ROOT / "assets/prod"
Expand Down Expand Up @@ -133,8 +126,8 @@ def main() -> None:

save_ico(prod_dir / "okcode-web-favicon.ico", img, ICO_SIZES_WEB)
save_ico(dev_dir / "okcode-dev-web-favicon.ico", img, ICO_SIZES_WEB)
save_ico(prod_dir / "okcode-windows.ico", windows_icon_source, ICO_SIZES_DESKTOP)
save_ico(dev_dir / "okcode-dev-windows.ico", windows_icon_source, ICO_SIZES_DESKTOP)
save_ico(prod_dir / "okcode-windows.ico", img, ICO_SIZES_DESKTOP)
save_ico(dev_dir / "okcode-dev-windows.ico", img, ICO_SIZES_DESKTOP)

# Marketing site: large nav icon + same favicons as prod web
mkt = ROOT / "apps/marketing/public"
Expand Down
Loading