Skip to content

Rebrand to TerKix, add PWA shell & offline cache, tighten Gemini server and storage handling#4

Open
Huynhthuongg wants to merge 3 commits into
mainfrom
codex/review-and-update-project-setup-61nx8b
Open

Rebrand to TerKix, add PWA shell & offline cache, tighten Gemini server and storage handling#4
Huynhthuongg wants to merge 3 commits into
mainfrom
codex/review-and-update-project-setup-61nx8b

Conversation

@Huynhthuongg

@Huynhthuongg Huynhthuongg commented Jun 7, 2026

Copy link
Copy Markdown
Member

Motivation

  • Rebrand the project from RKix to TerKix and provide a polished, installable PWA shell with offline caching and app metadata.
  • Harden server-side Gemini integration with a configurable model, better request parsing, health endpoint, and improved error handling for more robust AI command processing.
  • Improve client state persistence and migration with defensive storage helpers and modernize the UI/UX with new assets and accessibility metadata.

Description

  • Server: added dotenv config, health endpoint (/api/health), GEMINI_MODEL env support, lazy GoogleGenAI init, request/response helpers (normalizeFiles, parseGeminiJson), stronger JSON schema and error handling for /api/gemini/command, and safer port parsing.
  • Client & UX: replaced RKix branding with TerKix across UI, added PWA install flow and service worker registration, integrated new public/manifest.webmanifest, public/sw.js, and public/terkix-logo.svg, expanded index meta tags, and many UI refinements and Vietnamese/localized labels.
  • Persistence & tooling: added src/utils/storage.ts (read/write helpers with legacy-key migration), replaced direct localStorage usage in App.tsx with these helpers, added main.tsx service worker registration, updated CSS for new visual styles, and added README and updated .env.example.
  • Packaging: updated package.json (name, version, scripts and dependencies ordering) and brought package-lock.json into sync with the changes.

Testing

  • Ran TypeScript validation with npm run typecheck and it completed successfully.
  • Built a production bundle with npm run build and the build succeeded without errors.

Codex Task


Summary by cubic

Rebranded the app to TerKix and shipped an installable PWA with offline shell caching, hardened the Gemini server, and moved to safer client storage. Added persistent terminal command history and an online/offline status for smoother use on flaky networks.

  • New Features

    • PWA shell: public/manifest.webmanifest, public/sw.js, service worker registration; offline-first shell caching.
    • Terminal: persisted command history (arrow-key recall) and online/offline status indicator.
    • Gemini server: GEMINI_MODEL and safe PORT parsing, lazy GoogleGenAI init, typed /api/gemini/command payloads with stricter validation, and /api/health.
    • Storage: src/utils/storage.ts with validators and legacy-key migration; replaced direct localStorage.
    • TerKix rebrand: new logo and copy; metadata.json updates including microphone permission.
  • Refactors

    • Package updates: renamed to terkix-terminal-os v1.0.5, added preview/typecheck; refreshed .env.example, package-lock.json, and README.
    • UI polish and accessibility: updated icons/meta, theme tweaks, and localized labels.

Written for commit d3f8a14. Summary will update on new commits.

Review in cubic

@qodo-code-review

Copy link
Copy Markdown

Qodo reviews are paused for this user.

Troubleshooting steps vary by plan Learn more →

On a Teams plan?
Reviews resume once this user has a paid seat and their Git account is linked in Qodo.
Link Git account →

Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center?
These require an Enterprise plan - Contact us
Contact us →

@coderabbitai

coderabbitai Bot commented Jun 7, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

PR này thực hiện rebranding toàn bộ dự án từ "RKix" sang "TerKix", thêm hỗ trợ PWA (Service Worker, manifest, install prompt), externalize cấu hình server (PORT, GEMINI_MODEL) vào biến môi trường, tạo storage abstraction layer, và cập nhật UI/styling toàn cầu để phù hợp với thương hiệu mới.

Changes

TerKix Rebranding và PWA Enablement

Layer / File(s) Summary
Configuration, Documentation, và Build Setup
.env.example, package.json, metadata.json, index.html, README.md, vite.config.ts
Cập nhật .env.example thêm PORT/GEMINI_MODEL, sắp xếp lại build tools thành devDependencies, đổi metadata từ RKix sang TerKix với quyền microphone, thêm PWA metadata/icons vào index.html, tạo README.md với hướng dẫn đầy đủ, sửa lỗi encoding trong vite.config.
Backend Configuration Externalization và Gemini API Refactoring
server.ts
Externalize PORT/GEMINI_MODEL từ env vars, refactor Gemini client initialization thành lazy singleton getGenAI(), thêm request parsing utilities (normalizeFiles, parseGeminiJson), cập nhật /api/gemini/command endpoint với typed destructuring, trim/validate command, build filesContext, sửa response schema yêu cầu log field cho agentWorkflow và language field cho filesToCreate.
Storage Abstraction Layer
src/utils/storage.ts
Tạo utility functions readJsonStorage, readStringStorage, readNumberStorage, writeStorage hỗ trợ fallback values, optional JSON validation, legacy key migration, và defensive error handling cho browser localStorage.
PWA Infrastructure
public/sw.js, public/manifest.webmanifest, src/main.tsx
Thêm Service Worker với cache-first strategy, CACHE_NAME="terkix-shell-v1", install/activate/fetch handlers; thêm PWA manifest với icons/shortcuts; cập nhật src/main.tsx phát hiện Vite dev server và đăng ký SW có điều kiện khi load event.
Frontend App Integration: Storage, PWA State, Branding, Command Deck
src/App.tsx
Đổi toàn bộ branding RKix → TerKix (prompt, labels, titles, footer), thêm PWA state (installPromptEvent, pwaInstallState), listener beforeinstallprompt/appinstalled, handleInstallApp; đổi persistence từ localStorage sang storage wrapper với key terkix_*; thêm activeProject selector; thêm latestTelemetry/stats widgets; đổi container id sang terkix-root; thêm Command Deck section với flow steps/quick actions/install button/stats trên terminal.
UI Component Branding Updates
src/components/DashboardOverview.tsx, src/components/PluginManager.tsx, src/components/ContactsManager.tsx, src/components/TelemetryD3Chart.tsx, src/data/presets.ts
Cập nhật branding RKix → TerKix trong DashboardOverview OS Banner, PluginManager UI strings/examples, ContactsManager email domains, TelemetryD3Chart comments; cập nhật sample data commit authors/compilation messages/labels.
Styling for TerKix UI Effects
src/index.css
Thêm CSS rules cho .terkix-grid-bg::before (nền lưới/gradient), .terkix-command-deck (overflow), .terkix-command-deck::after (radial glow), .terkix-terminal-glass (glass-effect gradient).

Poem

🐰 Cổ áo phủ đỏ TerKix, dự án mới chào đón
Service Worker đến, offline mà không sợn
Từ RKix thời xưa, giờ TerKix tỏa sáng
Storage và PWA, tương lai sáng chói
Branding xuyên suốt mã, đơn vị thật hoàn hảo!

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 7.14% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed Tiêu đề rõ ràng và chính xác tóm tắt ba thay đổi chính: rebranding thành TerKix, thêm PWA shell với offline cache, và cải thiện xử lý Gemini/storage. Phù hợp hoàn toàn với các thay đổi trong pull request.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description check ✅ Passed Mô tả pull request liên quan chặt chẽ đến các thay đổi trong changeset, cung cấp chi tiết về việc rebrand từ RKix sang TerKix, PWA shell, cải thiện Gemini server và lưu trữ client.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/review-and-update-project-setup-61nx8b
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch codex/review-and-update-project-setup-61nx8b
  • 🛠️ Aethon

Warning

Review ran into problems

🔥 Problems

Linked repositories: Your configuration references 1 linked repositories, but your current plan allows 0. Analyzed ``, skipped Aethon/backend-api.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@kilo-code-bot

kilo-code-bot Bot commented Jun 7, 2026

Copy link
Copy Markdown

Kilo Code Review could not run — your account is out of credits.

Add credits or switch to a free model to enable reviews on this change.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 9

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/App.tsx (1)

2014-2020: ⚠️ Potential issue | 🔴 Critical | 🏗️ Heavy lift

Không mở preview ngoài bằng document.write() cùng origin.

indexHtmlCode là nội dung workspace có thể đến từ prompt/Gemini. Nhánh này ghi nó vào about:blank do chính app mở ra, nên script trong preview sẽ chạy cùng origin với ứng dụng và có thể đọc localStorage, gọi API same-origin, hoặc thao tác window.opener. Inline preview phía dưới đã được sandbox; nút này đang bỏ qua toàn bộ lớp cách ly đó.

Muốn giữ “Open External”, hãy mở một route/static page chỉ chứa <iframe sandbox> rồi truyền srcDoc/message vào iframe, hoặc vô hiệu hóa external preview cho nội dung không tin cậy.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/App.tsx` around lines 2014 - 2020, The current onClick handler uses
window.open + document.write to render indexHtmlCode which executes with the
app's origin; change this to avoid document.write: either route the "Open
External" action to a dedicated static page/route (e.g. /external-preview) that
renders a single <iframe sandbox> and communicates the HTML via postMessage or
sets iframe.srcdoc, or disable/grey-out the button when indexHtmlCode is
untrusted. Update the onClick logic (the handler that calls window.open,
document.write and uses indexHtmlCode) to open the safe preview route or trigger
the sandboxed iframe flow instead of writing directly into the new window.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@index.html`:
- Line 11: The apple-touch-icon currently points to an SVG
(href="/terkix-logo.svg"), which iOS Safari ignores; replace or add a PNG touch
icon and update the webmanifest icons to include PNG fallbacks: change the link
rel="apple-touch-icon" href to a generated PNG (or add an additional <link
rel="apple-touch-icon" href="/terkix-logo.png" sizes="180x180"> alongside the
SVG), and in manifest.webmanifest ensure the icons array contains PNG entries
(e.g., 192x192/512x512 PNG) so iOS Home Screen and other platforms will load the
proper PNG icons.

In `@public/sw.js`:
- Around line 18-39: The fetch handler is doing a blanket cache-first for all
same-origin GETs which causes stale API responses and navigation/shortcut
mismatches and caches error responses; update the fetch event listener to
branch: for navigations (event.request.mode === "navigate") use a network-first
strategy that falls back to the precached navigation entry (e.g., '/' or your
precached index.html) so shortcuts like "/?section=files" can resolve offline;
for API or dynamic endpoints (e.g., requestUrl.pathname.startsWith("/api/") or
other dynamic prefixes) use network-first and only cache when response.ok is
true (status 200) to avoid caching 404/500; for other static assets you can keep
cache-first via caches.match; keep references to event.respondWith,
caches.match, CACHE_NAME, cache.put and ensure you only call cache.put with
response.clone() after verifying response.ok.

In `@server.ts`:
- Line 35: The PORT constant is parsed but not validated, allowing invalid
values like "abc", negative numbers or >65535 to reach server.listen; update the
logic that defines PORT to validate Number.parseInt(process.env.PORT || "3000",
10) by checking for NaN and ensuring an integer in the valid port range
(0–65535) and fall back to 3000 when invalid; locate the constant named PORT and
replace its assignment with a guarded parse + range check (use Number.isInteger
and range checks) so server.listen always receives a safe port number.
- Around line 91-93: The POST handler for app.post("/api/gemini/command") is
unprotected and can be abused; add server-side authentication and throttling:
implement middleware (e.g., auth middleware that checks a configured server API
key or JWT in the Authorization header) and a simple rate-limiter middleware
that wraps the route, then apply them to the route handling the
GeminiCommandRequest payload; ensure the handler validates the key and returns
401/429 on failure and logs unauthorized/rate-limited attempts before calling
the existing Gemini invocation logic.

In `@src/App.tsx`:
- Around line 167-169: The initial pwaInstallState should not default to "ready"
unconditionally; change its initialization to detect if the app is already
running in standalone and set pwaInstallState to "installed" when appropriate
(use a lazy useState initializer that checks typeof window !== "undefined" and
evaluates window.matchMedia('(display-mode: standalone)').matches ||
(window.navigator as any).standalone), and keep existing listeners that update
installPromptEvent and call setPwaInstallState on 'beforeinstallprompt' and
'appinstalled' so the UI reflects the real installed state; update references to
pwaInstallState, setPwaInstallState, installPromptEvent, and
setInstallPromptEvent accordingly.
- Around line 123-127: The current validator passed into readJsonStorage for the
"terkix_projects" key only checks id and files, but the UI reads many other
Project fields; update the predicate used in the useState initializer (the arrow
passed to readJsonStorage in the projects state) to validate the full Project
surface used by the renderer (at minimum: id, name, description, deployments,
activeBranch, commitHistory, files and the expected types for each
files/commit/deployment item), ensuring nested arrays/objects have the required
properties and types so malformed/legacy records are rejected and
PRESET_PROJECTS used instead.
- Around line 134-140: currentSection is always initialized to "terminal" and
never reads the URL, so the PWA shortcut ?section=... is ignored; update the
initialization of currentSection (the useState holding currentSection and
setCurrentSection) to parse window.location.search (via URLSearchParams) for a
"section" value and use that as the initial state (falling back to "terminal" if
absent/invalid), or add a useEffect that reads URLSearchParams on mount and
calls setCurrentSection accordingly; reference the currentSection state and
setCurrentSection symbols when implementing this change.

In `@src/utils/storage.ts`:
- Line 6: The check function isBrowserStorageAvailable can throw when access to
window.localStorage is blocked; wrap its body in a try/catch so it safely
returns false on any exception. Update the isBrowserStorageAvailable
implementation to first verify typeof window !== "undefined" and then try
reading/using window.localStorage inside a try block, returning true if
accessible and false from the catch (ensuring callers like the useState lazy
initializer don't crash the app).
- Around line 60-61: Hàm readStringStorage đang dùng `|| fallback`, khiến giá
trị chuỗi rỗng ("") bị coi là falsy và bị thay bằng fallback; thay bằng phép
kiểm tra nullish (hoặc kiểm tra === undefined) để chỉ dùng fallback khi
getStoredValue(key, legacyKeys) là null hoặc undefined. Cụ thể, trong khối try
nơi gọi getStoredValue(key, legacyKeys), thay logic `... || fallback` bằng `...
?? fallback` (hoặc `const v = getStoredValue(...); return v === undefined ?
fallback : v;`) để đảm bảo chuỗi rỗng được trả nguyên vẹn.

---

Outside diff comments:
In `@src/App.tsx`:
- Around line 2014-2020: The current onClick handler uses window.open +
document.write to render indexHtmlCode which executes with the app's origin;
change this to avoid document.write: either route the "Open External" action to
a dedicated static page/route (e.g. /external-preview) that renders a single
<iframe sandbox> and communicates the HTML via postMessage or sets
iframe.srcdoc, or disable/grey-out the button when indexHtmlCode is untrusted.
Update the onClick logic (the handler that calls window.open, document.write and
uses indexHtmlCode) to open the safe preview route or trigger the sandboxed
iframe flow instead of writing directly into the new window.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: fbace136-edf4-46cb-93e8-4f2ebc06d631

📥 Commits

Reviewing files that changed from the base of the PR and between 868c5c8 and 01a608d.

⛔ Files ignored due to path filters (2)
  • package-lock.json is excluded by !**/package-lock.json
  • public/terkix-logo.svg is excluded by !**/*.svg
📒 Files selected for processing (18)
  • .env.example
  • README.md
  • index.html
  • metadata.json
  • package.json
  • public/manifest.webmanifest
  • public/sw.js
  • server.ts
  • src/App.tsx
  • src/components/ContactsManager.tsx
  • src/components/DashboardOverview.tsx
  • src/components/PluginManager.tsx
  • src/components/TelemetryD3Chart.tsx
  • src/data/presets.ts
  • src/index.css
  • src/main.tsx
  • src/utils/storage.ts
  • vite.config.ts

Comment thread index.html
Comment thread public/sw.js Outdated
Comment thread server.ts Outdated
Comment thread server.ts
Comment thread src/App.tsx
Comment thread src/App.tsx
Comment thread src/App.tsx
Comment thread src/utils/storage.ts
Comment thread src/utils/storage.ts

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

5 issues found across 20 files

You’re at about 96% of the monthly reviewed-line limit. You may want to disable incremental reviews to conserve quota. Reviews will continue until that limit is exceeded. If you need help avoiding interruptions, please contact contact@cubic.dev.

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread server.ts Outdated
Comment thread public/sw.js Outdated
Comment thread src/utils/storage.ts
Comment thread src/utils/storage.ts
Comment thread index.html

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 01a608d453

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread package.json
Comment thread public/sw.js Outdated
Comment thread public/manifest.webmanifest
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
Signed-off-by: Huỳnh Thương <252359928+Huynhthuongg@users.noreply.github.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d3f8a142b5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread public/sw.js
Comment thread src/utils/storage.ts
@alwaysmeticulous

Copy link
Copy Markdown

Meticulous was unable to execute a test run for this PR because the most recent commit is associated with multiple PRs. To execute a test run, please try pushing up a new commit that is only associated with this PR.

Last updated for commit d3f8a14. This comment will update as new commits are pushed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant