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
Binary file modified apps/web/public/apple-touch-icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified apps/web/public/favicon-16x16.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified apps/web/public/favicon-32x32.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified apps/web/public/favicon.ico
Binary file not shown.
2 changes: 1 addition & 1 deletion assets/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ The three Icon Composer projects are the source of truth for full application ic

Each project uses `text.svg` for the T3 mark and `background.svg` when the background is a vector layer. Additional layers use semantic names that describe their role and placement.

Run `vp run icons:export` from the repository root to regenerate the tracked iOS, Linux, Windows, and web assets. Run `vp run icons:check` to verify that those generated assets match their sources without changing files.
Run `vp run icons:export` from the repository root to regenerate the tracked iOS, Linux, Windows, and web assets. The development web exports are also copied to `apps/web/public` for the browser favicon and splash screen. Run `vp run icons:check` to verify that the generated assets and public copies match their sources without changing files.

Exporting requires Icon Composer 2 or newer on macOS. The script selects the newest compatible exporter from Xcode or a standalone Icon Composer installation and pins design generation 26. Set `ICON_COMPOSER_TOOL` to the full path of `Icon Composer.app/Contents/Executables/ictool` to override automatic discovery.

Expand Down
6 changes: 6 additions & 0 deletions scripts/build-desktop-artifact.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import {
resolveDesktopBuildIconAssets,
resolveDesktopProductName,
resolveDesktopUpdateChannel,
resolveDesktopWebAssetBrand,
resolveGitHubPublishConfig,
resolveMockUpdateServerPort,
resolveMockUpdateServerUrl,
Expand Down Expand Up @@ -102,6 +103,11 @@ it.layer(NodeServices.layer)("build-desktop-artifact", (it) => {
});
});

it("switches the bundled splash and favicon branding for nightly versions", () => {
assert.equal(resolveDesktopWebAssetBrand("0.0.17"), "production");
assert.equal(resolveDesktopWebAssetBrand("0.0.17-nightly.20260413.42"), "nightly");
});

it.effect("resolves GitHub desktop publish config from Effect config", () =>
Effect.gen(function* () {
const latestConfig = yield* resolveGitHubPublishConfig("latest").pipe(
Expand Down
14 changes: 13 additions & 1 deletion scripts/build-desktop-artifact.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,12 @@ 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 { BRAND_ASSET_PATHS } from "./lib/brand-assets.ts";
import { applyWebBrandAssets } from "./apply-web-brand-assets.ts";
import {
BRAND_ASSET_PATHS,
resolveWebAssetBrandForChannel,
type WebAssetBrand,
} from "./lib/brand-assets.ts";
import { getDefaultBuildArch } from "./lib/build-target-arch.ts";
import { loadRepoEnv } from "./lib/public-config.ts";
import { resolveCatalogDependencies } from "./lib/resolve-catalog.ts";
Expand Down Expand Up @@ -1324,6 +1329,10 @@ export function resolveDesktopUpdateChannel(version: string): "latest" | "nightl
return /-nightly\.\d{8}\.\d+$/.test(version) ? "nightly" : "latest";
}

export function resolveDesktopWebAssetBrand(version: string): WebAssetBrand {
return resolveWebAssetBrandForChannel(resolveDesktopUpdateChannel(version));
}

export function resolveDesktopBuildIconAssets(version: string): DesktopBuildIconAssets {
if (resolveDesktopUpdateChannel(version) === "nightly") {
return {
Expand Down Expand Up @@ -1665,6 +1674,9 @@ const buildDesktopArtifact = Effect.fn("buildDesktopArtifact")(function* (
});
}

const webAssetBrand = resolveDesktopWebAssetBrand(appVersion);
yield* applyWebBrandAssets(webAssetBrand, "apps/server/dist/client");
yield* Effect.log(`[desktop-artifact] Applied ${webAssetBrand} web client branding.`);
yield* validateBundledClientAssets(path.dirname(bundledClientEntry));

yield* fs.makeDirectory(path.join(stageAppDir, "apps/desktop"), { recursive: true });
Expand Down
12 changes: 11 additions & 1 deletion scripts/export-brand-icons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import * as Stream from "effect/Stream";
import { Command, Flag } from "effect/unstable/cli";
import { ChildProcess, ChildProcessSpawner } from "effect/unstable/process";

import { BRAND_ASSET_PATHS } from "./lib/brand-assets.ts";
import { BRAND_ASSET_PATHS, DEVELOPMENT_PUBLIC_ICON_OVERRIDES } from "./lib/brand-assets.ts";
import { encodePngIco, readPngDimensions, WINDOWS_ICON_SIZES } from "./lib/icon-export.ts";

const DESIGN_GENERATION = 26;
Expand Down Expand Up @@ -751,6 +751,16 @@ export const exportBrandIcons = Effect.fn("exportBrandIcons")(function* (checkOn
}
}

for (const override of DEVELOPMENT_PUBLIC_ICON_OVERRIDES) {
const sourceContents = generated.get(override.sourceRelativePath);
if (sourceContents === undefined) {
return yield* Effect.die(
new Error(`Generated development web icon is missing: ${override.sourceRelativePath}`),
);
}
generated.set(override.targetRelativePath, sourceContents);
}

if (checkOnly) {
const stale = yield* Effect.filter(
[...generated.entries()],
Expand Down
22 changes: 22 additions & 0 deletions scripts/lib/brand-assets.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { describe, expect, it } from "vite-plus/test";
import {
BRAND_ASSET_PATHS,
DEVELOPMENT_ICON_OVERRIDES,
DEVELOPMENT_PUBLIC_ICON_OVERRIDES,
PUBLISH_ICON_OVERRIDES,
resolveWebAssetBrandForChannel,
resolveWebIconOverrides,
Expand Down Expand Up @@ -37,6 +38,27 @@ describe("brand-assets", () => {
});
});

it("maps development web assets to the public splash and favicon files", () => {
expect(DEVELOPMENT_PUBLIC_ICON_OVERRIDES).toEqual([
{
sourceRelativePath: BRAND_ASSET_PATHS.developmentWebFaviconIco,
targetRelativePath: "apps/web/public/favicon.ico",
},
{
sourceRelativePath: BRAND_ASSET_PATHS.developmentWebFavicon16Png,
targetRelativePath: "apps/web/public/favicon-16x16.png",
},
{
sourceRelativePath: BRAND_ASSET_PATHS.developmentWebFavicon32Png,
targetRelativePath: "apps/web/public/favicon-32x32.png",
},
{
sourceRelativePath: BRAND_ASSET_PATHS.developmentWebAppleTouchIconPng,
targetRelativePath: "apps/web/public/apple-touch-icon.png",
},
]);
});

it("can target hosted web dist directly", () => {
expect(resolveWebIconOverrides("production", "apps/web/dist")).toContainEqual({
sourceRelativePath: BRAND_ASSET_PATHS.productionWebAppleTouchIconPng,
Expand Down
5 changes: 5 additions & 0 deletions scripts/lib/brand-assets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,4 +101,9 @@ export function resolveWebIconOverrides(

export const DEVELOPMENT_ICON_OVERRIDES = resolveWebIconOverrides("development", "dist/client");

export const DEVELOPMENT_PUBLIC_ICON_OVERRIDES = resolveWebIconOverrides(
"development",
"apps/web/public",
);

export const PUBLISH_ICON_OVERRIDES = resolveWebIconOverrides("production", "dist/client");
Loading