From 021092ef7826032634faafb9b029ef234415d8ea Mon Sep 17 00:00:00 2001
From: Mingjing <1239443+hackergene@users.noreply.github.com>
Date: Tue, 11 Aug 2026 16:41:53 +0800
Subject: [PATCH] refactor: rename project to AI ThemeStore
---
AGENTS.md | 2 +-
CHANGELOG.md | 2 +-
CONTRIBUTING.md | 4 +--
NOTICE.md | 4 +--
Package.swift | 10 +++----
README.md | 26 +++++++++---------
README.zh-CN.md | 26 +++++++++---------
Resources/Info.plist | 8 +++---
SECURITY.md | 4 +--
.../AIThemeStoreApp.swift} | 2 +-
.../AppModel.swift | 4 +--
.../BridgeClient.swift | 10 +++----
.../ContentView.swift | 6 ++--
.../Models.swift | 4 +--
.../ThemeLibrary.swift | 20 +++++++-------
docs/images/README.md | 2 +-
docs/images/codex-theme-showcase.png | Bin 1712689 -> 1713388 bytes
.../images/x-launch-fortune-code-workshop.png | Bin 862147 -> 861677 bytes
scripts/build-app.sh | 12 ++++----
scripts/build-release.sh | 4 +--
tests/run-tests.sh | 17 ++++++++++--
themes/cyber-neon/theme.json | 4 +--
themes/minimal-glass/theme.json | 4 +--
themes/pink-future-city/theme.json | 4 +--
24 files changed, 95 insertions(+), 84 deletions(-)
rename Sources/{AIThemeStoreCommunity/AIThemeStoreCommunityApp.swift => AIThemeStore/AIThemeStoreApp.swift} (86%)
rename Sources/{AIThemeStoreCommunity => AIThemeStore}/AppModel.swift (95%)
rename Sources/{AIThemeStoreCommunity => AIThemeStore}/BridgeClient.swift (90%)
rename Sources/{AIThemeStoreCommunity => AIThemeStore}/ContentView.swift (97%)
rename Sources/{AIThemeStoreCommunity => AIThemeStore}/Models.swift (93%)
rename Sources/{AIThemeStoreCommunity => AIThemeStore}/ThemeLibrary.swift (82%)
diff --git a/AGENTS.md b/AGENTS.md
index 56416c0..6b21276 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -2,7 +2,7 @@
## Scope
-This repository contains the offline macOS Community App, its loopback-only
+This repository contains the offline macOS App, its loopback-only
theme engine, three original starter themes, and tests. Do not add production
backend, deployment, Firebase, analytics, remote-device, account, or update
infrastructure.
diff --git a/CHANGELOG.md b/CHANGELOG.md
index bb1c4e9..4be5920 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,7 +2,7 @@
## 0.1.0 — 2026-08-11
-- Added a native, offline macOS Community App for applying and restoring Codex
+- Added a native, offline macOS App for applying and restoring Codex
themes.
- Included three original starter themes and an open local theme format.
- Added loopback-only injection, signature validation, transactional theme
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index cf5ece8..3d4333d 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,9 +1,9 @@
# Contributing
-Thank you for helping improve AI ThemeStore Community.
+Thank you for helping improve AI ThemeStore.
1. Fork the repository and create a focused branch.
-2. Keep changes within the offline Community scope.
+2. Keep changes within the offline, local-only project scope.
3. Run `./tests/run-tests.sh` on macOS.
4. Describe the user impact and actual checks in the pull request.
5. Include screenshots for visual changes.
diff --git a/NOTICE.md b/NOTICE.md
index 527a979..9f282be 100644
--- a/NOTICE.md
+++ b/NOTICE.md
@@ -1,6 +1,6 @@
# Notices
-AI ThemeStore Community is an unofficial customization project. It is not
+AI ThemeStore is an unofficial customization project. It is not
affiliated with, endorsed by, or sponsored by OpenAI.
The MIT License applies to the source code and the three original starter
@@ -14,7 +14,7 @@ UI, text, or watermarks.
Screenshots under `docs/images/` are sanitized, high-fidelity previews rendered
with project-owned themes. Some showcase themes come from the wider ThemeStore
-catalog and are not bundled with this Community app. The previews contain a
+catalog and are not bundled with this app. The previews contain a
simulated Codex interface for demonstration only and no real account, project,
or conversation data. No third-party character fan artwork is included. OpenAI
and Codex names and interface elements remain the property of their respective
diff --git a/Package.swift b/Package.swift
index eb76198..f60c852 100644
--- a/Package.swift
+++ b/Package.swift
@@ -3,18 +3,18 @@
import PackageDescription
let package = Package(
- name: "AIThemeStoreCommunity",
+ name: "AIThemeStore",
platforms: [.macOS(.v13)],
products: [
.executable(
- name: "ai-themestore-community",
- targets: ["AIThemeStoreCommunity"]
+ name: "ai-themestore",
+ targets: ["AIThemeStore"]
),
],
targets: [
.executableTarget(
- name: "AIThemeStoreCommunity",
- path: "Sources/AIThemeStoreCommunity"
+ name: "AIThemeStore",
+ path: "Sources/AIThemeStore"
),
]
)
diff --git a/README.md b/README.md
index b3e2bf1..c98010a 100644
--- a/README.md
+++ b/README.md
@@ -2,19 +2,19 @@
English · 简体中文
-# AI ThemeStore Community
+# AI ThemeStore
An open-source, offline theme app for **Codex Desktop on macOS**. It gives the
Codex workspace a visual identity while keeping the official app intact and
making every change reversible.
-[](https://github.com/hackergene/AI-ThemeStore-Community/releases/latest)
+[](https://github.com/hackergene/AI-ThemeStore/releases/latest)
[](#technology-stack)
[](#technology-stack)
[](./LICENSE)
[](#privacy-and-safety)
-> AI ThemeStore Community is an independent, unofficial project. It is not
+> AI ThemeStore is an independent, unofficial project. It is not
> affiliated with, endorsed by, or sponsored by OpenAI.
## Codex, themed
@@ -41,7 +41,7 @@ No third-party character fan art is included in this repository.
## Technology stack
-AI ThemeStore Community is a hybrid native macOS app: **Swift and SwiftUI**
+AI ThemeStore is a hybrid native macOS app: **Swift and SwiftUI**
provide the application interface, while a local **JavaScript and CSS theme
engine** handles Codex theming, verification, and recovery.
@@ -58,7 +58,7 @@ JavaScript even though the user-facing application is native SwiftUI.
## What we learned from theming Codex
Codex is a living product, so a durable theme cannot be just a wallpaper or a
-collection of fragile selectors. The Community engine is built around a few
+collection of fragile selectors. The theme engine is built around a few
practical lessons:
1. **Theme the complete workflow.** New Chat and active tasks must share the
@@ -80,7 +80,7 @@ customization boundary understandable and recoverable.
### Download
-Download the latest build from [GitHub Releases](https://github.com/hackergene/AI-ThemeStore-Community/releases/latest).
+Download the latest build from [GitHub Releases](https://github.com/hackergene/AI-ThemeStore/releases/latest).
### Build from source
@@ -88,18 +88,18 @@ Requirements: macOS 13 or newer, the official Codex Desktop app, and Xcode
Command Line Tools.
```bash
-git clone https://github.com/hackergene/AI-ThemeStore-Community.git
-cd AI-ThemeStore-Community
+git clone https://github.com/hackergene/AI-ThemeStore.git
+cd AI-ThemeStore
./scripts/build-app.sh
-open "dist/AI ThemeStore Community.app"
+open "dist/AI ThemeStore.app"
```
-The build script creates the Community app locally. It does not modify or
+The build script creates the app locally. It does not modify or
re-sign the official Codex app.
### Use the app
-1. Open AI ThemeStore Community.
+1. Open AI ThemeStore.
2. Select a local theme and choose **Apply Theme**.
3. The app restarts Codex and verifies the themed New Chat and task surfaces.
4. Choose **Restore Codex Appearance** whenever you want the native look back.
@@ -122,12 +122,12 @@ a minimal example.
## Privacy and safety
-The Community edition works offline and contains no telemetry or account code.
+AI ThemeStore works offline and contains no telemetry or account code.
Its debugging connection is bound to `127.0.0.1` only. Because a local debugging
port is sensitive while a theme is active, avoid running untrusted local
software at the same time. Read the full boundary in [SECURITY.md](./SECURITY.md).
-## Community and full edition
+## Project scope
This repository is intentionally focused on a small, auditable, offline Codex
theme experience. The broader theme catalog and hosted browsing experience are
diff --git a/README.zh-CN.md b/README.zh-CN.md
index ccba5ea..e098f67 100644
--- a/README.zh-CN.md
+++ b/README.zh-CN.md
@@ -2,18 +2,18 @@
English · 简体中文
-# AI ThemeStore Community
+# AI ThemeStore
一套面向 **macOS Codex Desktop** 的开源离线主题 App。它可以为 Codex
工作区加入完整的视觉主题,同时保持官方 App 完整,所有改动均可恢复。
-[](https://github.com/hackergene/AI-ThemeStore-Community/releases/latest)
+[](https://github.com/hackergene/AI-ThemeStore/releases/latest)
[](#技术栈)
[](#技术栈)
[](./LICENSE)
[](#隐私与安全)
-> AI ThemeStore Community 是独立的非官方项目,与 OpenAI 无隶属、背书或赞助关系。
+> AI ThemeStore 是独立的非官方项目,与 OpenAI 无隶属、背书或赞助关系。
## Codex 主题效果
@@ -37,7 +37,7 @@
## 技术栈
-AI ThemeStore Community 是一套混合架构的原生 macOS App:**Swift 与
+AI ThemeStore 是一套混合架构的原生 macOS App:**Swift 与
SwiftUI** 提供应用界面,本地 **JavaScript 与 CSS 主题引擎**负责 Codex
主题应用、验证和恢复。
@@ -54,7 +54,7 @@ GitHub 的语言标签依据源码字节数计算,因此即使用户看到的
## 适配 Codex 的实践经验
Codex 是持续演进的产品,因此稳定主题不能只是一张壁纸,也不能依赖一组脆弱的
-选择器。Community 引擎基于以下实践构建:
+选择器。主题引擎基于以下实践构建:
1. **覆盖完整工作流。** New Chat 与运行中任务应使用统一视觉语言,包括任务卡、
输入区、侧边栏和分层面板。
@@ -74,7 +74,7 @@ Codex 是持续演进的产品,因此稳定主题不能只是一张壁纸,
### 下载
-从 [GitHub Releases](https://github.com/hackergene/AI-ThemeStore-Community/releases/latest)
+从 [GitHub Releases](https://github.com/hackergene/AI-ThemeStore/releases/latest)
下载最新版本。
### 从源码构建
@@ -82,17 +82,17 @@ Codex 是持续演进的产品,因此稳定主题不能只是一张壁纸,
需要 macOS 13 或更高版本、官方 Codex Desktop App,以及 Xcode Command Line Tools。
```bash
-git clone https://github.com/hackergene/AI-ThemeStore-Community.git
-cd AI-ThemeStore-Community
+git clone https://github.com/hackergene/AI-ThemeStore.git
+cd AI-ThemeStore
./scripts/build-app.sh
-open "dist/AI ThemeStore Community.app"
+open "dist/AI ThemeStore.app"
```
-构建脚本只生成本地 Community App,不会修改或重新签名官方 Codex App。
+构建脚本只生成本地 App,不会修改或重新签名官方 Codex App。
### 使用 App
-1. 打开 AI ThemeStore Community。
+1. 打开 AI ThemeStore。
2. 选择本地主题并点击“应用主题”。
3. App 会重启 Codex,并验证 New Chat 与任务页的主题状态。
4. 随时点击“恢复 Codex 外观”即可回到原生界面。
@@ -114,11 +114,11 @@ open "dist/AI ThemeStore Community.app"
## 隐私与安全
-Community 版离线运行,不包含遥测或账号代码。调试连接仅绑定 `127.0.0.1`。
+AI ThemeStore 离线运行,不包含遥测或账号代码。调试连接仅绑定 `127.0.0.1`。
主题启用期间,本地调试端口属于敏感能力,请勿同时运行不可信的本机软件。完整边界
见 [SECURITY.md](./SECURITY.md)。
-## Community 与完整版
+## 项目边界
本仓库有意保持为一套小型、可审计、离线的 Codex 主题体验。更多主题及在线浏览
体验请访问 [themestore.ai](https://themestore.ai)。
diff --git a/Resources/Info.plist b/Resources/Info.plist
index 60cde90..2e3e143 100644
--- a/Resources/Info.plist
+++ b/Resources/Info.plist
@@ -5,17 +5,17 @@
CFBundleDevelopmentRegion
zh_CN
CFBundleDisplayName
- AI ThemeStore Community
+ AI ThemeStore
CFBundleExecutable
- ai-themestore-community
+ ai-themestore
CFBundleIconFile
AppIcon
CFBundleIdentifier
- ai.themestore.community
+ ai.themestore.opensource
CFBundleInfoDictionaryVersion
6.0
CFBundleName
- AI ThemeStore Community
+ AI ThemeStore
CFBundlePackageType
APPL
CFBundleShortVersionString
diff --git a/SECURITY.md b/SECURITY.md
index 29b398e..90e03da 100644
--- a/SECURITY.md
+++ b/SECURITY.md
@@ -2,11 +2,11 @@
## Supported version
-Security fixes are provided for the latest Community release.
+Security fixes are provided for the latest release.
## Runtime boundary
-AI ThemeStore Community does not modify the official Codex application. It
+AI ThemeStore does not modify the official Codex application. It
launches Codex with a Chromium DevTools endpoint bound to `127.0.0.1`, validates
the official app and bundled Node.js signatures, and injects only into verified
Codex renderer targets.
diff --git a/Sources/AIThemeStoreCommunity/AIThemeStoreCommunityApp.swift b/Sources/AIThemeStore/AIThemeStoreApp.swift
similarity index 86%
rename from Sources/AIThemeStoreCommunity/AIThemeStoreCommunityApp.swift
rename to Sources/AIThemeStore/AIThemeStoreApp.swift
index edb61a0..7a2ad28 100644
--- a/Sources/AIThemeStoreCommunity/AIThemeStoreCommunityApp.swift
+++ b/Sources/AIThemeStore/AIThemeStoreApp.swift
@@ -1,7 +1,7 @@
import SwiftUI
@main
-struct AIThemeStoreCommunityApp: App {
+struct AIThemeStoreApp: App {
@StateObject private var model = AppModel()
var body: some Scene {
diff --git a/Sources/AIThemeStoreCommunity/AppModel.swift b/Sources/AIThemeStore/AppModel.swift
similarity index 95%
rename from Sources/AIThemeStoreCommunity/AppModel.swift
rename to Sources/AIThemeStore/AppModel.swift
index 1b6c0f3..e619929 100644
--- a/Sources/AIThemeStoreCommunity/AppModel.swift
+++ b/Sources/AIThemeStore/AppModel.swift
@@ -3,7 +3,7 @@ import Foundation
@MainActor
final class AppModel: ObservableObject {
- @Published private(set) var themes: [CommunityTheme] = []
+ @Published private(set) var themes: [ThemeModel] = []
@Published private(set) var runtime = RuntimeStatus.unavailable
@Published private(set) var busy = false
@Published private(set) var activity = "正在读取本地主题…"
@@ -54,7 +54,7 @@ final class AppModel: ObservableObject {
}
}
- func apply(_ theme: CommunityTheme) async {
+ func apply(_ theme: ThemeModel) async {
guard !busy else { return }
busy = true
activity = "正在应用 \(theme.name)…"
diff --git a/Sources/AIThemeStoreCommunity/BridgeClient.swift b/Sources/AIThemeStore/BridgeClient.swift
similarity index 90%
rename from Sources/AIThemeStoreCommunity/BridgeClient.swift
rename to Sources/AIThemeStore/BridgeClient.swift
index 01e0b07..d824e42 100644
--- a/Sources/AIThemeStoreCommunity/BridgeClient.swift
+++ b/Sources/AIThemeStore/BridgeClient.swift
@@ -7,7 +7,7 @@ struct BridgeClient: Sendable {
func apply(themeID: String) async throws -> RuntimeStatus {
guard ThemeLibrary.isSafeThemeID(themeID) else {
- throw CommunityError.invalidTheme("主题 ID 不安全。")
+ throw ThemeStoreError.invalidTheme("主题 ID 不安全。")
}
return try await run(action: "apply", themeID: themeID)
}
@@ -30,7 +30,7 @@ struct BridgeClient: Sendable {
return bundled
}
}
- if let root = ProcessInfo.processInfo.environment["THEMESTORE_COMMUNITY_ROOT"] {
+ if let root = ProcessInfo.processInfo.environment["THEMESTORE_PROJECT_ROOT"] {
let development = URL(fileURLWithPath: root, isDirectory: true)
.appendingPathComponent("engine/scripts/app-bridge-macos.sh", isDirectory: false)
if FileManager.default.isExecutableFile(atPath: development.path) {
@@ -41,7 +41,7 @@ struct BridgeClient: Sendable {
}
private func run(action: String, themeID: String? = nil) async throws -> RuntimeStatus {
- guard let executable = executableURL() else { throw CommunityError.bridgeUnavailable }
+ guard let executable = executableURL() else { throw ThemeStoreError.bridgeUnavailable }
let arguments = [action, themeID ?? "", "codex"]
let home = FileManager.default.homeDirectoryForCurrentUser.path
@@ -66,12 +66,12 @@ struct BridgeClient: Sendable {
guard process.terminationStatus == 0 else {
let message = String(data: errorData, encoding: .utf8)?
.trimmingCharacters(in: .whitespacesAndNewlines)
- throw CommunityError.bridgeFailed(
+ throw ThemeStoreError.bridgeFailed(
message?.isEmpty == false ? message! : "本地主题操作失败。"
)
}
guard let status = try? JSONDecoder().decode(RuntimeStatus.self, from: outputData) else {
- throw CommunityError.invalidBridgeResponse
+ throw ThemeStoreError.invalidBridgeResponse
}
return status
}.value
diff --git a/Sources/AIThemeStoreCommunity/ContentView.swift b/Sources/AIThemeStore/ContentView.swift
similarity index 97%
rename from Sources/AIThemeStoreCommunity/ContentView.swift
rename to Sources/AIThemeStore/ContentView.swift
index 554de60..f49dcfc 100644
--- a/Sources/AIThemeStoreCommunity/ContentView.swift
+++ b/Sources/AIThemeStore/ContentView.swift
@@ -32,7 +32,7 @@ struct ContentView: View {
.frame(minWidth: 940, minHeight: 680)
.task { await model.bootstrap() }
.alert(
- "AI ThemeStore Community",
+ "AI ThemeStore",
isPresented: Binding(
get: { !model.alertMessage.isEmpty },
set: { if !$0 { model.alertMessage = "" } }
@@ -49,7 +49,7 @@ struct ContentView: View {
VStack(alignment: .leading, spacing: 8) {
Text("AI ThemeStore")
.font(.system(size: 34, weight: .bold, design: .rounded))
- Text("COMMUNITY · OFFLINE MAC APP")
+ Text("OPEN SOURCE · OFFLINE MAC APP")
.font(.system(size: 12, weight: .semibold, design: .monospaced))
.foregroundStyle(.secondary)
Text("选择一套本地主题,为 Codex 换一张会呼吸的脸。")
@@ -134,7 +134,7 @@ struct ContentView: View {
}
private struct ThemeCard: View {
- let theme: CommunityTheme
+ let theme: ThemeModel
let active: Bool
let disabled: Bool
let apply: () -> Void
diff --git a/Sources/AIThemeStoreCommunity/Models.swift b/Sources/AIThemeStore/Models.swift
similarity index 93%
rename from Sources/AIThemeStoreCommunity/Models.swift
rename to Sources/AIThemeStore/Models.swift
index b7f65f6..df2bcfb 100644
--- a/Sources/AIThemeStoreCommunity/Models.swift
+++ b/Sources/AIThemeStore/Models.swift
@@ -13,7 +13,7 @@ struct ThemeMetadata: Decodable, Sendable {
let assets: Assets
}
-struct CommunityTheme: Identifiable, Sendable {
+struct ThemeModel: Identifiable, Sendable {
let id: String
let metadata: ThemeMetadata
let directoryURL: URL
@@ -39,7 +39,7 @@ struct RuntimeStatus: Decodable, Sendable {
)
}
-enum CommunityError: LocalizedError {
+enum ThemeStoreError: LocalizedError {
case invalidTheme(String)
case bridgeUnavailable
case bridgeFailed(String)
diff --git a/Sources/AIThemeStoreCommunity/ThemeLibrary.swift b/Sources/AIThemeStore/ThemeLibrary.swift
similarity index 82%
rename from Sources/AIThemeStoreCommunity/ThemeLibrary.swift
rename to Sources/AIThemeStore/ThemeLibrary.swift
index af35465..3b12156 100644
--- a/Sources/AIThemeStoreCommunity/ThemeLibrary.swift
+++ b/Sources/AIThemeStore/ThemeLibrary.swift
@@ -21,7 +21,7 @@ enum ThemeLibrary {
static func installBundledThemes() throws {
let manager = FileManager.default
guard let resourceRoot = Bundle.main.resourceURL else {
- throw CommunityError.invalidTheme("App 资源目录不可用。")
+ throw ThemeStoreError.invalidTheme("App 资源目录不可用。")
}
let bundledRoot = resourceRoot.appendingPathComponent("themes", isDirectory: true)
let destinationRoot = try themesRoot()
@@ -40,7 +40,7 @@ enum ThemeLibrary {
}
}
- static func scan() throws -> [CommunityTheme] {
+ static func scan() throws -> [ThemeModel] {
let manager = FileManager.default
let root = try themesRoot()
let directories = try manager.contentsOfDirectory(
@@ -52,10 +52,10 @@ enum ThemeLibrary {
.sorted { $0.name.localizedStandardCompare($1.name) == .orderedAscending }
}
- static func readTheme(at directory: URL) throws -> CommunityTheme {
+ static func readTheme(at directory: URL) throws -> ThemeModel {
let values = try directory.resourceValues(forKeys: [.isDirectoryKey, .isSymbolicLinkKey])
guard values.isDirectory == true, values.isSymbolicLink != true else {
- throw CommunityError.invalidTheme("主题目录必须是本地普通目录。")
+ throw ThemeStoreError.invalidTheme("主题目录必须是本地普通目录。")
}
let metadataURL = directory.appendingPathComponent("theme.json", isDirectory: false)
@@ -67,27 +67,27 @@ enum ThemeLibrary {
let size = metadataValues.fileSize,
size > 0,
size <= 64 * 1024 else {
- throw CommunityError.invalidTheme("theme.json 缺失或大小不安全。")
+ throw ThemeStoreError.invalidTheme("theme.json 缺失或大小不安全。")
}
let metadata = try JSONDecoder().decode(ThemeMetadata.self, from: Data(contentsOf: metadataURL))
guard isSafeThemeID(metadata.id), metadata.id == directory.lastPathComponent else {
- throw CommunityError.invalidTheme("主题 ID 与目录名不一致。")
+ throw ThemeStoreError.invalidTheme("主题 ID 与目录名不一致。")
}
guard metadata.name.count <= 80, metadata.version.count <= 32 else {
- throw CommunityError.invalidTheme("主题名称或版本号过长。")
+ throw ThemeStoreError.invalidTheme("主题名称或版本号过长。")
}
guard metadata.assets.hero == URL(fileURLWithPath: metadata.assets.hero).lastPathComponent,
!metadata.assets.hero.contains("/") else {
- throw CommunityError.invalidTheme("主题背景必须位于主题目录内。")
+ throw ThemeStoreError.invalidTheme("主题背景必须位于主题目录内。")
}
let previewURL = directory.appendingPathComponent(metadata.assets.hero, isDirectory: false)
let previewValues = try previewURL.resourceValues(forKeys: [.isRegularFileKey, .isSymbolicLinkKey])
guard previewValues.isRegularFile == true, previewValues.isSymbolicLink != true else {
- throw CommunityError.invalidTheme("主题背景不存在或不是普通文件。")
+ throw ThemeStoreError.invalidTheme("主题背景不存在或不是普通文件。")
}
- return CommunityTheme(
+ return ThemeModel(
id: metadata.id,
metadata: metadata,
directoryURL: directory,
diff --git a/docs/images/README.md b/docs/images/README.md
index e05fd45..e0de0d6 100644
--- a/docs/images/README.md
+++ b/docs/images/README.md
@@ -7,7 +7,7 @@ project-owned source themes from the wider ThemeStore catalog:
- `fortune-code-workshop/hero.png` — original Chinese fortune-workbench collection
- `azure-lotus-dharma/hero.png` — original blue Buddha and Zen collection
- `ember-ninja-legacy/hero.png` — original, non-franchise ninja world
-- `silver-nocturne-rose/hero.png` — ThemeStore Community theme
+- `silver-nocturne-rose/hero.png` — original AI ThemeStore theme
The original ninja asset is used deliberately instead of the personal-use
`hero-ip.png` fan asset. No third-party character fan artwork is included.
diff --git a/docs/images/codex-theme-showcase.png b/docs/images/codex-theme-showcase.png
index bfa90ab8edff26ead30ece3dd73e5299bbbfff51..9c36d2ea6bf2e36fd7fa80d6f4473456abfd85c3 100644
GIT binary patch
delta 1640685
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