-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
feat(i18n): add German language support and schema-based wizard system #345
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
feat(i18n): add German language support and schema-based wizard system #345
Conversation
German Language Support:
- Add complete German translations for all UI components
- New locale files: common, navigation, settings, tasks, welcome, onboarding, dialogs
- Update i18n configuration to include German ('de') as available language
- German now selectable in Settings → Language
Schema-Based Wizard System:
- Add wizard-step.schema.ts with TypeScript definitions for wizard steps
- Add wizard-registry.ts for auto-discovery of wizard steps
- Add OnboardingWizardV2.tsx that dynamically renders steps from registry
- Add README.md with documentation for adding new wizard steps
The new wizard system allows adding new steps by:
1. Creating the step component
2. Registering it in wizard-registry.ts with priority and conditions
3. Adding translations
Steps are automatically sorted by priority and filtered by conditions.
No changes to the main wizard component needed when adding new features.
Priority ranges:
- 0-99: Welcome screens
- 100-199: Authentication
- 200-299: Integrations
- 300-399: Memory/persistence
- 400-499: Agent configuration
- 900-999: Completion screens
📝 WalkthroughWalkthroughAdds a registry-driven onboarding and guided-tour system: new OnboardingWizardV2, wizard schema and registry (runtime registration, condition filtering, progress steps), tour hook/context/components, German i18n resources, PathMode/project base path settings, UI components (FeatureOverview, EmptyState) and related exports. Changes
Sequence DiagramsequenceDiagram
participant User
participant Wizard as OnboardingWizardV2
participant Registry as WizardRegistry
participant Cond as ConditionEvaluator
participant Step as LazyStepComponent
participant Settings as Settings/Electron
Note over Wizard,Registry: Wizard mounts and discovers steps
User->>Wizard: open/start wizard
Wizard->>Registry: getActiveSteps(conditionContext)
Registry->>Cond: evaluate each step.condition
Cond-->>Registry: boolean results
Registry-->>Wizard: activeSteps (sorted)
Wizard->>Step: lazy-load render current step (Suspense)
Step-->>Wizard: emits actions (onNext/onBack/onSkip, openTaskCreator, openSettings)
rect rgb(220,245,220)
User->>Wizard: next / prev / skip / finish
Wizard->>Wizard: update currentIndex & completedSteps
end
Wizard->>Settings: persist onboarding completion (save via electron/settings)
Settings-->>Wizard: persisted response
Wizard-->>User: close dialog
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎉 Thanks for your first PR!
A maintainer will review it soon. Please make sure:
- Your branch is synced with
develop - CI checks pass
- You've followed our contribution guide
Welcome to the Auto Claude community!
| @@ -0,0 +1,130 @@ | |||
| # Onboarding Wizard System | |||
|
|
|||
| Das Wizard-System nutzt ein **schema-basiertes Auto-Discovery-Pattern**, das automatisch neue Schritte erkennt und integriert. | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can this file be in english? as it is the main languange ? thanks and great addition
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 5
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (15)
apps/frontend/src/renderer/components/onboarding/OnboardingWizardV2.tsxapps/frontend/src/renderer/components/onboarding/README.mdapps/frontend/src/renderer/components/onboarding/index.tsapps/frontend/src/renderer/components/onboarding/wizard-registry.tsapps/frontend/src/renderer/components/onboarding/wizard-step.schema.tsapps/frontend/src/shared/constants/i18n.tsapps/frontend/src/shared/i18n/index.tsapps/frontend/src/shared/i18n/locales/de/common.jsonapps/frontend/src/shared/i18n/locales/de/dialogs.jsonapps/frontend/src/shared/i18n/locales/de/navigation.jsonapps/frontend/src/shared/i18n/locales/de/onboarding.jsonapps/frontend/src/shared/i18n/locales/de/settings.jsonapps/frontend/src/shared/i18n/locales/de/tasks.jsonapps/frontend/src/shared/i18n/locales/de/welcome.jsonapps/frontend/src/shared/i18n/locales/en/onboarding.json
🧰 Additional context used
📓 Path-based instructions (3)
apps/frontend/src/shared/i18n/locales/**/*.json
📄 CodeRabbit inference engine (CLAUDE.md)
Add new translation keys to ALL language files (minimum:
en/*.jsonandfr/*.json) inapps/frontend/src/shared/i18n/locales/
Files:
apps/frontend/src/shared/i18n/locales/de/tasks.jsonapps/frontend/src/shared/i18n/locales/de/navigation.jsonapps/frontend/src/shared/i18n/locales/de/welcome.jsonapps/frontend/src/shared/i18n/locales/de/onboarding.jsonapps/frontend/src/shared/i18n/locales/de/settings.jsonapps/frontend/src/shared/i18n/locales/de/dialogs.jsonapps/frontend/src/shared/i18n/locales/en/onboarding.jsonapps/frontend/src/shared/i18n/locales/de/common.json
apps/frontend/src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
apps/frontend/src/**/*.{ts,tsx}: Always use translation keys withuseTranslation()for all user-facing text in React/TypeScript frontend components - use formatnamespace:section.key(e.g.,navigation:items.githubPRs)
Never use hardcoded strings in JSX/TSX files for user-facing text - always reference translation keys fromapps/frontend/src/shared/i18n/locales/
Files:
apps/frontend/src/renderer/components/onboarding/wizard-step.schema.tsapps/frontend/src/renderer/components/onboarding/OnboardingWizardV2.tsxapps/frontend/src/renderer/components/onboarding/index.tsapps/frontend/src/shared/i18n/index.tsapps/frontend/src/renderer/components/onboarding/wizard-registry.tsapps/frontend/src/shared/constants/i18n.ts
apps/frontend/**/*.{ts,tsx}
⚙️ CodeRabbit configuration file
apps/frontend/**/*.{ts,tsx}: Review React patterns and TypeScript type safety.
Check for proper state management and component composition.
Files:
apps/frontend/src/renderer/components/onboarding/wizard-step.schema.tsapps/frontend/src/renderer/components/onboarding/OnboardingWizardV2.tsxapps/frontend/src/renderer/components/onboarding/index.tsapps/frontend/src/shared/i18n/index.tsapps/frontend/src/renderer/components/onboarding/wizard-registry.tsapps/frontend/src/shared/constants/i18n.ts
🧠 Learnings (3)
📚 Learning: 2025-12-25T18:29:32.954Z
Learnt from: CR
Repo: AndyMik90/Auto-Claude PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-25T18:29:32.954Z
Learning: Applies to apps/frontend/src/shared/i18n/locales/**/*.json : Add new translation keys to ALL language files (minimum: `en/*.json` and `fr/*.json`) in `apps/frontend/src/shared/i18n/locales/`
Applied to files:
apps/frontend/src/shared/i18n/locales/de/tasks.jsonapps/frontend/src/shared/i18n/locales/de/navigation.jsonapps/frontend/src/shared/i18n/locales/de/welcome.jsonapps/frontend/src/shared/i18n/locales/de/onboarding.jsonapps/frontend/src/shared/i18n/locales/de/settings.jsonapps/frontend/src/shared/i18n/locales/de/dialogs.jsonapps/frontend/src/shared/i18n/locales/en/onboarding.jsonapps/frontend/src/shared/i18n/locales/de/common.jsonapps/frontend/src/shared/i18n/index.tsapps/frontend/src/shared/constants/i18n.ts
📚 Learning: 2025-12-25T18:29:32.954Z
Learnt from: CR
Repo: AndyMik90/Auto-Claude PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-25T18:29:32.954Z
Learning: Applies to apps/frontend/src/**/*.{ts,tsx} : Always use translation keys with `useTranslation()` for all user-facing text in React/TypeScript frontend components - use format `namespace:section.key` (e.g., `navigation:items.githubPRs`)
Applied to files:
apps/frontend/src/shared/i18n/locales/de/navigation.jsonapps/frontend/src/shared/i18n/index.ts
📚 Learning: 2025-12-25T18:29:32.954Z
Learnt from: CR
Repo: AndyMik90/Auto-Claude PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-25T18:29:32.954Z
Learning: Applies to apps/frontend/src/**/*.{ts,tsx} : Never use hardcoded strings in JSX/TSX files for user-facing text - always reference translation keys from `apps/frontend/src/shared/i18n/locales/`
Applied to files:
apps/frontend/src/shared/i18n/locales/de/common.jsonapps/frontend/src/shared/i18n/index.tsapps/frontend/src/shared/constants/i18n.ts
🧬 Code graph analysis (1)
apps/frontend/src/renderer/components/onboarding/wizard-registry.ts (1)
apps/frontend/src/renderer/components/onboarding/wizard-step.schema.ts (5)
defineWizardStep(184-190)STEP_PRIORITIES(169-179)WizardStepDefinition(82-133)StepConditionContext(67-76)WizardConfig(151-163)
🪛 LanguageTool
apps/frontend/src/renderer/components/onboarding/README.md
[grammar] ~1-~1: Ergänze ein Satzzeichen
Context: # Onboarding Wizard System Das Wizard-System nutzt e...
(QB_NEW_DE_OTHER_ERROR_IDS_MISSING_PUNCTUATION_ONBOARDINGDASHWIZARDDASHSYSTEM)
[grammar] ~1-~1: Ergänze ein Satzzeichen
Context: # Onboarding Wizard System Das Wizard-System nutzt ein **sc...
(QB_NEW_DE_OTHER_ERROR_IDS_MISSING_PUNCTUATION_ONBOARDINGDASHWIZARDDASHSYSTEM)
[grammar] ~71-~71: Passe das Symbol an
Context: ...ibung des Schritts" } } ``` Fertig! Der Wizard zeigt den neuen Schritt auto...
(QB_NEW_DE_OTHER_ERROR_IDS_REPLACEMENT_OTHER)
[grammar] ~79-~79: Ersetze das Satzzeichen
Context: ...-----------|--------------| | Welcome | 0-99 | Willkommens-/Intro-Screens | | Auth |...
(QB_NEW_DE_OTHER_ERROR_IDS_REPLACEMENT_PUNCTUATION_DASH_–)
[grammar] ~80-~80: Ersetze das Satzzeichen
Context: ...| Willkommens-/Intro-Screens | | Auth | 100-199 | Authentifizierung (OAuth, API-Keys) |...
(QB_NEW_DE_OTHER_ERROR_IDS_REPLACEMENT_PUNCTUATION_DASH_–)
[grammar] ~81-~81: Ersetze das Satzzeichen
Context: ...ung (OAuth, API-Keys) | | Integration | 200-299 | Externe Dienste (GitHub, Linear) | | ...
(QB_NEW_DE_OTHER_ERROR_IDS_REPLACEMENT_PUNCTUATION_DASH_–)
[grammar] ~82-~82: Ersetze das Satzzeichen
Context: ...e Dienste (GitHub, Linear) | | Memory | 300-399 | Gedächtnis/Persistenz | | Agent | 400...
(QB_NEW_DE_OTHER_ERROR_IDS_REPLACEMENT_PUNCTUATION_DASH_–)
[grammar] ~83-~83: Ersetze das Satzzeichen
Context: ...399 | Gedächtnis/Persistenz | | Agent | 400-499 | Agent-Konfiguration | | Completion | ...
(QB_NEW_DE_OTHER_ERROR_IDS_REPLACEMENT_PUNCTUATION_DASH_–)
[grammar] ~84-~84: Ersetze das Satzzeichen
Context: ... | Agent-Konfiguration | | Completion | 900-999 | Abschluss-Screens | ## Bedingte Schr...
(QB_NEW_DE_OTHER_ERROR_IDS_REPLACEMENT_PUNCTUATION_DASH_–)
[grammar] ~116-~116: Hier könnte ein Fehler sein.
Context: ...s } ``` ## Step-Kategorien - welcome - Willkommens-Screens - `auth` - Authent...
(QB_NEW_DE)
[grammar] ~116-~116: Ersetze das Satzzeichen
Context: ... } ``` ## Step-Kategorien - welcome - Willkommens-Screens - `auth` - Authenti...
(QB_NEW_DE_OTHER_ERROR_IDS_REPLACEMENT_PUNCTUATION_DASH_–)
[grammar] ~116-~116: Entferne das Symbol
Context: ...orien - welcome - Willkommens-Screens - auth - Authentifizierung - integration - Ext...
(QB_NEW_DE_OTHER_ERROR_IDS_UNNECESSARY_OTHER)
[grammar] ~118-~118: Ersetze das Satzzeichen
Context: ...th- Authentifizierung -integration- Externe Dienste -memory` - Gedächtnis...
(QB_NEW_DE_OTHER_ERROR_IDS_REPLACEMENT_PUNCTUATION_DASH_–)
[grammar] ~118-~118: Entferne das Symbol
Context: ...ierung - integration - Externe Dienste - memory - Gedächtnis-Konfiguration - agent - Ag...
(QB_NEW_DE_OTHER_ERROR_IDS_UNNECESSARY_OTHER)
[grammar] ~119-~119: Entferne das Symbol
Context: ...te - memory - Gedächtnis-Konfiguration - agent - Agent-Einstellungen - completion - Ab...
(QB_NEW_DE_OTHER_ERROR_IDS_UNNECESSARY_OTHER)
[grammar] ~120-~120: Entferne das Symbol
Context: ...guration - agent - Agent-Einstellungen - completion - Abschluss ## Debugging ```typescript ...
(QB_NEW_DE_OTHER_ERROR_IDS_UNNECESSARY_OTHER)
🔇 Additional comments (16)
apps/frontend/src/shared/constants/i18n.ts (1)
6-11: LGTM: German language support correctly added.The type extension and language entry are properly structured. The
SupportedLanguagetype now includes 'de', and theAVAILABLE_LANGUAGESarray includes the German entry with appropriate labels.apps/frontend/src/shared/i18n/index.ts (1)
22-60: LGTM: German resources correctly imported and wired.The German translation resources are properly imported and added to the resources object. The implementation follows the same pattern as English and French, including all seven namespaces (common, navigation, settings, tasks, welcome, onboarding, dialogs) that are declared in the configuration.
apps/frontend/src/shared/i18n/locales/de/tasks.json (1)
1-86: Ensure all translation keys are present in English and French locale files.Per coding guidelines, all new translation keys added to
de/tasks.jsonmust also exist inen/tasks.jsonandfr/tasks.json. Verify key parity across these three language files before merging.apps/frontend/src/shared/i18n/locales/de/welcome.json (1)
1-16: All translation keys in the German locale file are properly defined in English and French locale files.Verification confirms that every key in
de/welcome.json(hero.title, hero.subtitle, actions.newProject, actions.openProject, recentProjects.title, recentProjects.empty, recentProjects.emptyDescription, and recentProjects.openFolder) exists in bothen/welcome.jsonandfr/welcome.jsonwith identical structure and nesting. The translation file adheres to the coding guideline requirement.apps/frontend/src/shared/i18n/locales/de/navigation.json (1)
1-31: Translation key parity confirmed across all locales.All translation keys in the German locale file (
de/navigation.json) have corresponding entries in both the English and French locale files. No missing keys detected. The file meets the coding guideline requirement of maintaining translation keys across all language files.apps/frontend/src/shared/i18n/locales/de/onboarding.json (1)
1-83: Translation key parity verified. All translation keys inde/onboarding.jsonexist in bothen/onboarding.jsonandfr/onboarding.json, meeting the coding guideline requirement for new translation keys to be added to minimum English and French locale files.apps/frontend/src/shared/i18n/locales/de/common.json (1)
1-102: Translation key parity confirmed across all language files.All 92 keys in
de/common.jsonhave corresponding entries in bothen/common.jsonandfr/common.json. The German locale file is properly synchronized with English and French.apps/frontend/src/shared/i18n/locales/de/settings.json (1)
1-240: All translation keys are properly synchronized across language files. Verification confirms that all 206 keys inde/settings.jsonexist in bothen/settings.jsonandfr/settings.json. The coding guideline requirement has been met.apps/frontend/src/renderer/components/onboarding/index.ts (1)
6-24: LGTM!Clean barrel exports following standard patterns. The module properly exposes the new wizard V2 system while maintaining backward compatibility with existing exports.
apps/frontend/src/renderer/components/onboarding/wizard-step.schema.ts (1)
1-203: LGTM overall!Well-structured TypeScript schema with comprehensive type definitions, sensible defaults in helper functions, and good JSDoc documentation. The schema enables a clean, type-safe wizard system with support for lazy loading, conditional steps, and extensibility.
apps/frontend/src/renderer/components/onboarding/OnboardingWizardV2.tsx (2)
227-234: Closing the dialog marks onboarding as complete — verify this is intended UX.When the user closes the dialog (e.g., clicking outside or pressing Escape),
skipWizardis called which persistsonboardingCompleted: true. This means users cannot reopen the wizard by reopening the dialog — they would need to reset it in settings. Ensure this is the intended behavior.
61-267: Well-structured registry-driven wizard component.Good use of React patterns: memoized derived state, proper callback dependencies, Suspense for lazy loading, and clean separation of concerns. The component properly integrates with the wizard registry system.
apps/frontend/src/renderer/components/onboarding/wizard-registry.ts (1)
1-281: Well-designed registry system with good separation of concerns.The registry pattern enables extensibility and auto-discovery. Good practices include:
- Defensive condition evaluation with try/catch
- Clear priority-based ordering
- Helpful debug utility
- Comprehensive API surface for querying steps
apps/frontend/src/shared/i18n/locales/de/dialogs.json (1)
1-122: ✓ Translation keys are properly synchronized. Verified thaten/dialogs.jsonandfr/dialogs.jsoncontain all the same keys as the German locale file.apps/frontend/src/renderer/components/onboarding/README.md (1)
1-130: Consider writing documentation in English for broader accessibility.This README is entirely in German, which may not align with the project's documentation conventions. While German language support is being added for UI translations, developer-facing documentation is typically written in English to ensure all contributors can understand it.
If German documentation is intentional, consider also providing an English version or at minimum English headings.
⛔ Skipped due to learnings
Learnt from: CR Repo: AndyMik90/Auto-Claude PR: 0 File: CLAUDE.md:0-0 Timestamp: 2025-12-25T18:29:32.954Z Learning: Applies to apps/frontend/src/**/*.{ts,tsx} : Always use translation keys with `useTranslation()` for all user-facing text in React/TypeScript frontend components - use format `namespace:section.key` (e.g., `navigation:items.githubPRs`)apps/frontend/src/shared/i18n/locales/en/onboarding.json (1)
68-82: Translation keys missing fromfr/onboarding.json, and top-level sections incomplete inen/onboarding.jsonandde/onboarding.json.The new step keys
graphiti,firstSpec,github,linear, andagentConfigare missing entirely fromfr/onboarding.json, violating the requirement that all translation keys exist in all language files (minimumenandfr).Additionally, in
en/onboarding.jsonandde/onboarding.json, the step keysgithub,linear, andagentConfiglack corresponding top-level sections withtitleanddescription(unlikegraphitiandfirstSpec). Add these top-level sections or confirm they are not needed for the wizard.⛔ Skipped due to learnings
Learnt from: CR Repo: AndyMik90/Auto-Claude PR: 0 File: CLAUDE.md:0-0 Timestamp: 2025-12-25T18:29:32.954Z Learning: Applies to apps/frontend/src/shared/i18n/locales/**/*.json : Add new translation keys to ALL language files (minimum: `en/*.json` and `fr/*.json`) in `apps/frontend/src/shared/i18n/locales/`Learnt from: CR Repo: AndyMik90/Auto-Claude PR: 0 File: CLAUDE.md:0-0 Timestamp: 2025-12-25T18:29:32.954Z Learning: Applies to apps/frontend/src/**/*.{ts,tsx} : Always use translation keys with `useTranslation()` for all user-facing text in React/TypeScript frontend components - use format `namespace:section.key` (e.g., `navigation:items.githubPRs`)Learnt from: CR Repo: AndyMik90/Auto-Claude PR: 0 File: CLAUDE.md:0-0 Timestamp: 2025-12-25T18:29:32.954Z Learning: Applies to apps/frontend/src/**/*.{ts,tsx} : Never use hardcoded strings in JSX/TSX files for user-facing text - always reference translation keys from `apps/frontend/src/shared/i18n/locales/`
| const skipWizard = useCallback(async () => { | ||
| try { | ||
| const result = await window.electronAPI.saveSettings({ onboardingCompleted: true }); | ||
| if (!result?.success) { | ||
| console.error('Failed to save onboarding completion:', result?.error); | ||
| } | ||
| } catch (err) { | ||
| console.error('Error saving onboarding completion:', err); | ||
| } | ||
| updateSettings({ onboardingCompleted: true }); | ||
| onOpenChange(false); | ||
| resetWizard(); | ||
| }, [updateSettings, onOpenChange, resetWizard]); | ||
|
|
||
| const finishWizard = useCallback(async () => { | ||
| try { | ||
| const result = await window.electronAPI.saveSettings({ onboardingCompleted: true }); | ||
| if (!result?.success) { | ||
| console.error('Failed to save onboarding completion:', result?.error); | ||
| } | ||
| } catch (err) { | ||
| console.error('Error saving onboarding completion:', err); | ||
| } | ||
| updateSettings({ onboardingCompleted: true }); | ||
| onOpenChange(false); | ||
| resetWizard(); | ||
| }, [updateSettings, onOpenChange, resetWizard]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick | 🔵 Trivial
Consider extracting duplicate persistence logic.
skipWizard and finishWizard share identical persistence logic (saving settings via Electron API and updating the store). Extract this into a shared helper to reduce duplication.
🔎 Proposed fix
+ const completeOnboarding = useCallback(async () => {
+ try {
+ const result = await window.electronAPI.saveSettings({ onboardingCompleted: true });
+ if (!result?.success) {
+ console.error('Failed to save onboarding completion:', result?.error);
+ }
+ } catch (err) {
+ console.error('Error saving onboarding completion:', err);
+ }
+ updateSettings({ onboardingCompleted: true });
+ }, [updateSettings]);
+
const skipWizard = useCallback(async () => {
- try {
- const result = await window.electronAPI.saveSettings({ onboardingCompleted: true });
- if (!result?.success) {
- console.error('Failed to save onboarding completion:', result?.error);
- }
- } catch (err) {
- console.error('Error saving onboarding completion:', err);
- }
- updateSettings({ onboardingCompleted: true });
+ await completeOnboarding();
onOpenChange(false);
resetWizard();
- }, [updateSettings, onOpenChange, resetWizard]);
+ }, [completeOnboarding, onOpenChange, resetWizard]);
const finishWizard = useCallback(async () => {
- try {
- const result = await window.electronAPI.saveSettings({ onboardingCompleted: true });
- if (!result?.success) {
- console.error('Failed to save onboarding completion:', result?.error);
- }
- } catch (err) {
- console.error('Error saving onboarding completion:', err);
- }
- updateSettings({ onboardingCompleted: true });
+ await completeOnboarding();
onOpenChange(false);
resetWizard();
- }, [updateSettings, onOpenChange, resetWizard]);
+ }, [completeOnboarding, onOpenChange, resetWizard]);📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const skipWizard = useCallback(async () => { | |
| try { | |
| const result = await window.electronAPI.saveSettings({ onboardingCompleted: true }); | |
| if (!result?.success) { | |
| console.error('Failed to save onboarding completion:', result?.error); | |
| } | |
| } catch (err) { | |
| console.error('Error saving onboarding completion:', err); | |
| } | |
| updateSettings({ onboardingCompleted: true }); | |
| onOpenChange(false); | |
| resetWizard(); | |
| }, [updateSettings, onOpenChange, resetWizard]); | |
| const finishWizard = useCallback(async () => { | |
| try { | |
| const result = await window.electronAPI.saveSettings({ onboardingCompleted: true }); | |
| if (!result?.success) { | |
| console.error('Failed to save onboarding completion:', result?.error); | |
| } | |
| } catch (err) { | |
| console.error('Error saving onboarding completion:', err); | |
| } | |
| updateSettings({ onboardingCompleted: true }); | |
| onOpenChange(false); | |
| resetWizard(); | |
| }, [updateSettings, onOpenChange, resetWizard]); | |
| const completeOnboarding = useCallback(async () => { | |
| try { | |
| const result = await window.electronAPI.saveSettings({ onboardingCompleted: true }); | |
| if (!result?.success) { | |
| console.error('Failed to save onboarding completion:', result?.error); | |
| } | |
| } catch (err) { | |
| console.error('Error saving onboarding completion:', err); | |
| } | |
| updateSettings({ onboardingCompleted: true }); | |
| }, [updateSettings]); | |
| const skipWizard = useCallback(async () => { | |
| await completeOnboarding(); | |
| onOpenChange(false); | |
| resetWizard(); | |
| }, [completeOnboarding, onOpenChange, resetWizard]); | |
| const finishWizard = useCallback(async () => { | |
| await completeOnboarding(); | |
| onOpenChange(false); | |
| resetWizard(); | |
| }, [completeOnboarding, onOpenChange, resetWizard]); |
🤖 Prompt for AI Agents
In apps/frontend/src/renderer/components/onboarding/OnboardingWizardV2.tsx
around lines 137 to 163, skipWizard and finishWizard duplicate the same async
persistence/update/cleanup logic; extract that into a single helper (e.g.,
persistOnboardingCompletion) that calls window.electronAPI.saveSettings, handles
errors/logging, calls updateSettings({ onboardingCompleted: true }),
onOpenChange(false), and resetWizard, then have both callbacks call that helper;
ensure dependencies and bindings remain correct (pass updateSettings,
onOpenChange, resetWizard or reference them from closure) and keep try/catch and
result checks intact.
| // Special handling for welcome step (uses onGetStarted instead of onNext) | ||
| if (currentStep.category === 'welcome') { | ||
| return ( | ||
| <Suspense fallback={<StepLoadingFallback />}> | ||
| <StepComponent | ||
| {...stepProps} | ||
| // WelcomeStep expects onGetStarted | ||
| {...({ onGetStarted: goToNextStep } as any)} | ||
| /> | ||
| </Suspense> | ||
| ); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick | 🔵 Trivial
Avoid as any type assertion; consider extending WizardStepProps.
The as any cast bypasses type safety. Since WelcomeStep expects onGetStarted, consider either:
- Adding
onGetStartedtoWizardStepPropsas an optional prop - Creating a separate
WelcomeStepPropsinterface that extendsWizardStepProps
🔎 Proposed fix
In wizard-step.schema.ts, extend WizardStepProps:
export interface WizardStepProps {
/** Navigate to the next step */
onNext: () => void;
/** Navigate to the previous step */
onBack: () => void;
/** Skip the entire wizard */
onSkip?: () => void;
/** Finish the wizard (for final step) */
onFinish?: () => void;
+ /** Get started (for welcome step) */
+ onGetStarted?: () => void;
/** Open task creator (for completion step) */
onOpenTaskCreator?: () => void;Then in OnboardingWizardV2.tsx:
if (currentStep.category === 'welcome') {
return (
<Suspense fallback={<StepLoadingFallback />}>
<StepComponent
{...stepProps}
- // WelcomeStep expects onGetStarted
- {...({ onGetStarted: goToNextStep } as any)}
+ onGetStarted={goToNextStep}
/>
</Suspense>
);
}Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In apps/frontend/src/renderer/components/onboarding/OnboardingWizardV2.tsx
around lines 207-218, remove the unsafe `{...({ onGetStarted: goToNextStep } as
any)}` cast and instead provide a properly typed prop: update the shared prop
types so WelcomeStep’s prop is recognized — either add `onGetStarted?: () =>
void` to `WizardStepProps` in wizard-step.schema.ts (preferred if optional for
other steps) or create a new `WelcomeStepProps extends WizardStepProps {
onGetStarted: () => void }` and type the lazy-loaded StepComponent accordingly;
then pass `onGetStarted={goToNextStep}` without casting and adjust imports/types
where StepComponent is defined so TypeScript accepts the narrower prop for the
welcome category.
| export function registerStep(definition: WizardStepDefinition): void { | ||
| // Check for duplicate ID | ||
| const existingIndex = STEP_DEFINITIONS.findIndex(s => s.id === definition.id); | ||
| if (existingIndex >= 0) { | ||
| console.warn(`Replacing existing step with ID "${definition.id}"`); | ||
| STEP_DEFINITIONS[existingIndex] = definition; | ||
| } else { | ||
| STEP_DEFINITIONS.push(definition); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Unregister a step by ID | ||
| */ | ||
| export function unregisterStep(id: string): boolean { | ||
| const index = STEP_DEFINITIONS.findIndex(s => s.id === id); | ||
| if (index >= 0) { | ||
| STEP_DEFINITIONS.splice(index, 1); | ||
| return true; | ||
| } | ||
| return false; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Runtime step registration mutates module-level state without triggering React re-renders.
registerStep and unregisterStep mutate the module-level STEP_DEFINITIONS array. Components using useMemo with getActiveSteps won't re-render when steps are dynamically added/removed because there's no reactive state management.
If dynamic step registration is needed, consider:
- Using a React context with state to trigger re-renders
- Exposing a subscription mechanism for step changes
- Documenting that runtime registration requires manual component re-mounting
🤖 Prompt for AI Agents
In apps/frontend/src/renderer/components/onboarding/wizard-registry.ts around
lines 230 to 251, the current registerStep/unregisterStep mutate the
module-level STEP_DEFINITIONS array but do not notify React consumers, so
dynamic changes won't trigger re-renders; implement a simple subscription
mechanism instead: keep STEP_DEFINITIONS but add an internal listeners Set and
export a subscribe(callback) -> unsubscribe function; after any mutation in
registerStep/unregisterStep call each listener (with the new STEP_DEFINITIONS or
no args) so React components can re-run their effects, and keep the existing
replace/push and return values unchanged.
| export const STEP_PRIORITIES = { | ||
| WELCOME: 0, | ||
| OAUTH: 100, | ||
| GITHUB: 150, | ||
| LINEAR: 160, | ||
| MEMORY: 300, | ||
| GRAPHITI: 310, | ||
| AGENT_CONFIG: 400, | ||
| FIRST_SPEC: 450, | ||
| COMPLETION: 999 | ||
| } as const; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick | 🔵 Trivial
Unused priority constants GITHUB and LINEAR.
STEP_PRIORITIES.GITHUB (150) and STEP_PRIORITIES.LINEAR (160) are defined but no corresponding steps are registered in wizard-registry.ts. If these are planned for future use, this is fine. Otherwise, consider removing unused constants to avoid confusion.
🤖 Prompt for AI Agents
In apps/frontend/src/renderer/components/onboarding/wizard-step.schema.ts around
lines 169 to 179, STEP_PRIORITIES defines GITHUB and LINEAR but no steps
register/use those priorities; either remove these unused constants or add the
corresponding step registrations in wizard-registry.ts. If they are not planned
now, delete the GITHUB and LINEAR entries from STEP_PRIORITIES to avoid
confusion; if they are planned, add the matching step definitions in
wizard-registry.ts and wire them into the registry so their priorities are used.
New Settings: - projectBasePath: Configure default directory for new projects - pathMode: Choose how file paths are interpreted - auto: Automatically detect correct path conversion - native: Use paths without conversion - wsl-windows: Convert WSL paths to Windows paths (/mnt/c/ → C:\) This allows users running Auto-Claude from WSL to configure Windows paths, while keeping the default behavior for native Windows/Mac/Linux users. UI: - Added new path settings section in Settings → Paths - Full i18n support (English + German translations)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (5)
apps/frontend/src/renderer/components/settings/GeneralSettings.tsxapps/frontend/src/shared/constants/config.tsapps/frontend/src/shared/i18n/locales/de/settings.jsonapps/frontend/src/shared/i18n/locales/en/settings.jsonapps/frontend/src/shared/types/settings.ts
🧰 Additional context used
📓 Path-based instructions (3)
apps/frontend/src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
apps/frontend/src/**/*.{ts,tsx}: Always use translation keys withuseTranslation()for all user-facing text in React/TypeScript frontend components - use formatnamespace:section.key(e.g.,navigation:items.githubPRs)
Never use hardcoded strings in JSX/TSX files for user-facing text - always reference translation keys fromapps/frontend/src/shared/i18n/locales/
Files:
apps/frontend/src/shared/types/settings.tsapps/frontend/src/shared/constants/config.tsapps/frontend/src/renderer/components/settings/GeneralSettings.tsx
apps/frontend/**/*.{ts,tsx}
⚙️ CodeRabbit configuration file
apps/frontend/**/*.{ts,tsx}: Review React patterns and TypeScript type safety.
Check for proper state management and component composition.
Files:
apps/frontend/src/shared/types/settings.tsapps/frontend/src/shared/constants/config.tsapps/frontend/src/renderer/components/settings/GeneralSettings.tsx
apps/frontend/src/shared/i18n/locales/**/*.json
📄 CodeRabbit inference engine (CLAUDE.md)
Add new translation keys to ALL language files (minimum:
en/*.jsonandfr/*.json) inapps/frontend/src/shared/i18n/locales/
Files:
apps/frontend/src/shared/i18n/locales/en/settings.jsonapps/frontend/src/shared/i18n/locales/de/settings.json
🧠 Learnings (1)
📚 Learning: 2025-12-25T18:29:32.954Z
Learnt from: CR
Repo: AndyMik90/Auto-Claude PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-25T18:29:32.954Z
Learning: Applies to apps/frontend/src/shared/i18n/locales/**/*.json : Add new translation keys to ALL language files (minimum: `en/*.json` and `fr/*.json`) in `apps/frontend/src/shared/i18n/locales/`
Applied to files:
apps/frontend/src/shared/i18n/locales/en/settings.jsonapps/frontend/src/shared/i18n/locales/de/settings.json
🧬 Code graph analysis (1)
apps/frontend/src/renderer/components/settings/GeneralSettings.tsx (1)
apps/frontend/src/shared/types/settings.ts (1)
PathMode(82-82)
🔇 Additional comments (5)
apps/frontend/src/shared/types/settings.ts (1)
81-96: LGTM!The PathMode type definition and AppSettings extensions are well-structured. The type is appropriately scoped to the three supported modes, and the optional fields are correctly typed with helpful documentation comments.
apps/frontend/src/shared/i18n/locales/de/settings.json (1)
1-252: German translations look comprehensive.The German translations are well-structured and appear to cover all settings sections comprehensively. The translation keys match the English version, and the path-related translations (lines 77-88) correctly mirror the new keys.
However, per the coding guidelines, French translations are also required. Please refer to the verification script in the review of
apps/frontend/src/shared/i18n/locales/en/settings.jsonto check French translation coverage.Based on learnings, translation keys must be added to all language files (minimum: en and fr).
apps/frontend/src/renderer/components/settings/GeneralSettings.tsx (3)
15-15: LGTM!The PathMode type is correctly imported from the shared types module, ensuring type safety across the component.
153-202: Review SelectValue rendering with nested SelectItem content.The path settings UI correctly uses translation keys for all user-facing text. However, the pathMode Select component has nested content in each SelectItem (lines 194-197) with both a label and description. When a value is selected, the SelectValue component (line 189) may not render the nested structure correctly.
Please verify that:
- The SelectValue component displays the selected option correctly (it should show just the label, not the nested structure).
- The descriptions in the dropdown are visible and properly styled.
- Consider whether the descriptions should be shown in a different way (e.g., as a tooltip or help text below the select) if the current implementation has rendering issues.
Test the path mode select in the UI to confirm the visual presentation works as expected.
167-178: LGTM!The projectBasePath input field is correctly implemented with proper translation keys, appropriate input handling, and two-way data binding with the settings state.
| // Path configuration for WSL/Windows compatibility | ||
| projectBasePath: undefined as string | undefined, // Default projects directory | ||
| pathMode: 'auto' as 'auto' | 'native' | 'wsl-windows', // How to interpret paths |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick | 🔵 Trivial
Consider importing PathMode type for better type safety.
The default settings are correctly defined with appropriate defaults. However, the inline type annotation 'auto' | 'native' | 'wsl-windows' duplicates the PathMode type definition from apps/frontend/src/shared/types/settings.ts.
🔎 Proposed refactor to use PathMode type
Import the PathMode type at the top of the file:
+import type { PathMode } from '../types/settings';
+
/**
* Application configuration constants
* Default settings, file paths, and project structure
*/Then update the pathMode default:
// Path configuration for WSL/Windows compatibility
projectBasePath: undefined as string | undefined, // Default projects directory
- pathMode: 'auto' as 'auto' | 'native' | 'wsl-windows', // How to interpret paths
+ pathMode: 'auto' as PathMode, // How to interpret paths🤖 Prompt for AI Agents
In apps/frontend/src/shared/constants/config.ts around lines 29 to 31, the
pathMode default uses an inline union type ('auto' | 'native' | 'wsl-windows')
which duplicates the existing PathMode type; import PathMode from
apps/frontend/src/shared/types/settings.ts at the top of the file and replace
the inline annotation with the imported PathMode type (e.g., pathMode: 'auto' as
PathMode) to centralize the type definition and improve type safety.
…anslations - Rewrote onboarding README.md completely in English - Added missing French translations for wizard steps (graphiti, firstSpec, github, linear, agentConfig) - Added 12 missing French translations for path settings (projectBasePath, pathMode, wslWindows, native, auto, etc.) - Fixed TypeScript errors in wizard step components using Pick<WizardStepProps> - Added vite-env.d.ts for import.meta.env support - Fixed wizard-step.schema.ts showInProgress duplicate warning
- Added tour system with step-by-step guidance for new users - Created TourOverlay and TourStepRenderer components - Added useTour hook for tour state management - Added tour translations for all 3 languages (en, de, fr) - Added FeatureOverview component for feature discovery - Created common components (Card, Badge) for consistent UI - Updated i18n configuration to include tour namespace - Extended CLAUDE.md with language and documentation rules
- Added tour integration to App.tsx with TourProvider - Updated Sidebar with tour trigger and improved navigation - Enhanced KanbanBoard and TerminalGrid layouts - Updated package-lock.json with dependencies
All Feedback Addressed ✅Thanks @AlexMadera for the review! I've addressed all the feedback items: 1. README.md in English ✅
2. French Translations for Onboarding Wizard ✅
3. French Translations for Path Settings ✅
Additional Fixes
The TypeScript compilation now passes without errors. Ready for re-review! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 10
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (9)
apps/frontend/src/renderer/components/TerminalGrid.tsx (1)
291-294: Critical i18n violation: hardcoded strings must use translation keys.This file contains multiple hardcoded English strings that violate the coding guidelines and break localization for the German language support this PR introduces.
Examples of violations:
- Line 291:
"Agent Terminals"- Line 293:
"Spawn multiple terminals to run Claude agents in parallel..."- Line 300, 379:
"New Terminal"- Line 317:
"terminals"- Line 336:
"History"- Line 342:
"Restore sessions from..."- Line 368:
"Invoke Claude All"- Line 393:
"Files"As per coding guidelines, you must:
- Import and use the
useTranslation()hook- Reference translation keys in the format
namespace:section.key- Add corresponding translations to all locale files (
en,de,fr)🔎 Example fix for lines 291-300
+import { useTranslation } from 'react-i18next'; + export function TerminalGrid({ projectPath, onNewTaskClick, isActive = false }: TerminalGridProps) { + const { t } = useTranslation('terminals'); + const allTerminals = useTerminalStore((state) => state.terminals); // ... rest of component // Empty state if (terminals.length === 0) { return ( <div className="flex h-full flex-col items-center justify-center gap-6 p-8" data-tour="terminals"> <div className="flex flex-col items-center gap-3 text-center"> <div className="rounded-full bg-card p-4"> <Grid2X2 className="h-8 w-8 text-muted-foreground" /> </div> <div> - <h2 className="text-lg font-semibold text-foreground">Agent Terminals</h2> + <h2 className="text-lg font-semibold text-foreground">{t('emptyState.title')}</h2> - <p className="mt-1 text-sm text-muted-foreground max-w-md"> - Spawn multiple terminals to run Claude agents in parallel. - Use <kbd className="px-1.5 py-0.5 text-xs bg-card border border-border rounded">Ctrl+T</kbd> to create a new terminal. - </p> + <p className="mt-1 text-sm text-muted-foreground max-w-md"> + {t('emptyState.description')} + </p> </div> </div> - <Button onClick={handleAddTerminal} className="gap-2"> + <Button onClick={handleAddTerminal} className="gap-2"> <Plus className="h-4 w-4" /> - New Terminal + {t('actions.newTerminal')} </Button> </div> ); }Then add to
apps/frontend/src/shared/i18n/locales/en/terminals.json:{ "emptyState": { "title": "Agent Terminals", "description": "Spawn multiple terminals to run Claude agents in parallel. Use Ctrl+T to create a new terminal." }, "actions": { "newTerminal": "New Terminal", "history": "History", "invokeClaude": "Invoke Claude All", "files": "Files" }, "toolbar": { "terminalCount": "{{count}} / 12 terminals", "restoreSessionsFrom": "Restore sessions from...", "sessionCount": "{{count}} session", "sessionCount_other": "{{count}} sessions" } }Based on coding guidelines.
Also applies to: 300-300, 317-317, 336-336, 342-342, 353-353, 368-368, 379-379, 393-393
apps/frontend/src/renderer/components/onboarding/OAuthStep.tsx (4)
297-302: Critical: Replace hardcoded strings with translation keys.The header contains hardcoded English strings which violate the coding guidelines.
As per coding guidelines: "Never use hardcoded strings in JSX/TSX files for user-facing text - always reference translation keys from
apps/frontend/src/shared/i18n/locales/"🔎 Proposed fix
Add translation keys to
locales/*/onboarding.json:{ "oauth": { "title": "Configure Claude Authentication", "subtitle": "Add your Claude accounts to enable AI features" } }Then update the component:
- <h1 className="text-2xl font-bold text-foreground tracking-tight"> - Configure Claude Authentication - </h1> - <p className="mt-2 text-muted-foreground"> - Add your Claude accounts to enable AI features - </p> + <h1 className="text-2xl font-bold text-foreground tracking-tight"> + {t('oauth.title')} + </h1> + <p className="mt-2 text-muted-foreground"> + {t('oauth.subtitle')} + </p>
328-339: Replace hardcoded info text with translation key.The info card description is hardcoded in English.
🔎 Proposed fix
Add to
locales/*/onboarding.json:{ "oauth": { "infoDescription": "Add multiple Claude subscriptions to automatically switch between them when you hit rate limits." } }Then update:
<div className="flex-1"> - <p className="text-sm text-muted-foreground"> - Add multiple Claude subscriptions to automatically switch between them when you hit rate limits. - </p> + <p className="text-sm text-muted-foreground"> + {t('oauth.infoDescription')} + </p> </div>
361-637: Critical: Extensive hardcoded strings in profile management UI.The entire profile management section contains numerous hardcoded English strings for labels, buttons, placeholders, and messages. This violates the coding guidelines and prevents localization to German and French.
Examples of hardcoded strings:
- "No accounts configured yet" (line 364)
- "Default", "Active", "Authenticated", "Needs Auth" (lines 426-441)
- "Authenticate", "Set Active" (lines 468, 479)
- Button labels: "Cancel", "Save Token", "Add" (lines 572, 585, 620)
- Placeholders: "Account name (e.g., Work, Personal)" (line 599)
- Success message (line 632)
All these strings should be replaced with translation keys. Given the extensive nature of this issue, I recommend creating a comprehensive set of translation keys in the
oauthsection ofonboarding.jsonfor all three locales (en, fr, de).🔎 Example translation structure needed
{ "oauth": { "noAccountsYet": "No accounts configured yet", "labels": { "default": "Default", "active": "Active", "authenticated": "Authenticated", "needsAuth": "Needs Auth" }, "buttons": { "authenticate": "Authenticate", "setActive": "Set Active", "cancel": "Cancel", "saveToken": "Save Token", "add": "Add" }, "placeholders": { "accountName": "Account name (e.g., Work, Personal)", "tokenPlaceholder": "sk-ant-oat01-...", "emailOptional": "Email (optional, for display)" }, "tooltips": { "hideTokenEntry": "Hide token entry", "enterTokenManually": "Enter token manually", "renameProfile": "Rename profile", "deleteProfile": "Delete profile" }, "manualToken": { "title": "Manual Token Entry", "instruction": "Run {{command}} to get your token" }, "successMessage": "You have at least one authenticated Claude account. You can continue to the next step." } }
642-665: Replace hardcoded button labels with common translation keys.The action buttons use hardcoded English labels instead of the existing common translations.
The
common.jsonalready has these button translations. Use them:🔎 Proposed fix
The component already imports
useTranslation('onboarding'). You can either:
- Use multiple namespaces:
- const { t } = useTranslation('onboarding'); + const { t } = useTranslation(['onboarding', 'common']);
- Or use the namespace prefix in translation keys:
- Back + {t('common:buttons.back')} - Skip + {t('common:buttons.skip')} - Continue + {t('common:buttons.continue')}apps/frontend/src/renderer/components/onboarding/MemoryStep.tsx (2)
377-383: Hardcoded user-facing strings violate i18n coding guidelines.This component contains numerous hardcoded strings that should use translation keys via
useTranslation(). Examples in this section:
"Memory"(line 378)"Auto Claude Memory helps remember context across your coding sessions"(line 381)As per coding guidelines: "Always use translation keys with
useTranslation()for all user-facing text in React/TypeScript frontend components."🔎 Suggested approach
- Add
useTranslationimport and hook:import { useTranslation } from 'react-i18next'; // Inside component: const { t } = useTranslation('onboarding');
- Replace hardcoded strings with translation keys:
- <h1 className="text-2xl font-bold text-foreground tracking-tight"> - Memory - </h1> + <h1 className="text-2xl font-bold text-foreground tracking-tight"> + {t('memory.title')} + </h1>
- Add corresponding keys to all locale files (
en/onboarding.json,fr/onboarding.json,de/onboarding.json).
433-444: Additional hardcoded strings requiring i18n.More hardcoded user-facing text in this section:
"What does Memory do?"(line 434)"Memory stores discoveries, patterns..."(line 437)- List items:
"Remembers patterns across sessions","Understands your codebase over time","Works offline - no cloud required"These should all use translation keys.
apps/frontend/src/renderer/components/onboarding/FirstSpecStep.tsx (2)
52-73: Hardcoded tip strings should use translation keys.The
tipsarray contains hardcoded user-facing text that violates the i18n coding guidelines:
"Be Descriptive","Start Small","Include Context","Let AI Help"- All description strings
As per coding guidelines: "Never use hardcoded strings in JSX/TSX files for user-facing text."
🔎 Suggested approach
const { t } = useTranslation('onboarding'); const tips = [ { icon: <PenLine className="h-4 w-4" />, title: t('firstSpec.tips.beDescriptive.title'), description: t('firstSpec.tips.beDescriptive.description') }, // ... similar for other tips ];Add corresponding keys to
en/onboarding.json,fr/onboarding.json, andde/onboarding.json.
94-100: More hardcoded strings requiring translation.
"Create Your First Task"(line 95)"Describe what you want to build and let Auto Claude handle the rest"(line 98)
♻️ Duplicate comments (1)
apps/frontend/src/renderer/components/onboarding/wizard-step.schema.ts (1)
169-179: Unused priority constantsGITHUBandLINEAR.As noted in the previous review,
STEP_PRIORITIES.GITHUB(150) andSTEP_PRIORITIES.LINEAR(160) are defined but no corresponding steps appear to be registered inwizard-registry.ts. If these are planned for future use, consider adding a comment indicating they are reserved. Otherwise, remove them to avoid confusion.🔎 Optional: Add comment for reserved priorities
export const STEP_PRIORITIES = { WELCOME: 0, OAUTH: 100, - GITHUB: 150, - LINEAR: 160, + GITHUB: 150, // Reserved for future GitHub integration step + LINEAR: 160, // Reserved for future Linear integration step MEMORY: 300, GRAPHITI: 310, AGENT_CONFIG: 400, FIRST_SPEC: 450, COMPLETION: 999 } as const;Or remove them if not planned:
export const STEP_PRIORITIES = { WELCOME: 0, OAUTH: 100, - GITHUB: 150, - LINEAR: 160, MEMORY: 300, GRAPHITI: 310, AGENT_CONFIG: 400, FIRST_SPEC: 450, COMPLETION: 999 } as const;
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
⛔ Files ignored due to path filters (1)
apps/frontend/package-lock.jsonis excluded by!**/package-lock.json,!**/package-lock.json
📒 Files selected for processing (32)
CLAUDE.mdapps/frontend/src/renderer/App.tsxapps/frontend/src/renderer/components/FeatureOverview/FeatureOverview.tsxapps/frontend/src/renderer/components/FeatureOverview/index.tsapps/frontend/src/renderer/components/KanbanBoard.tsxapps/frontend/src/renderer/components/Sidebar.tsxapps/frontend/src/renderer/components/TerminalGrid.tsxapps/frontend/src/renderer/components/common/EmptyState.tsxapps/frontend/src/renderer/components/onboarding/CompletionStep.tsxapps/frontend/src/renderer/components/onboarding/FirstSpecStep.tsxapps/frontend/src/renderer/components/onboarding/GraphitiStep.tsxapps/frontend/src/renderer/components/onboarding/MemoryStep.tsxapps/frontend/src/renderer/components/onboarding/OAuthStep.tsxapps/frontend/src/renderer/components/onboarding/OnboardingWizard.tsxapps/frontend/src/renderer/components/onboarding/README.mdapps/frontend/src/renderer/components/onboarding/WelcomeStep.tsxapps/frontend/src/renderer/components/onboarding/wizard-step.schema.tsapps/frontend/src/renderer/components/tour/TourOverlay.tsxapps/frontend/src/renderer/components/tour/index.tsapps/frontend/src/renderer/components/tour/tour-steps.tsapps/frontend/src/renderer/contexts/TourContext.tsxapps/frontend/src/renderer/hooks/useTour.tsapps/frontend/src/shared/i18n/index.tsapps/frontend/src/shared/i18n/locales/de/common.jsonapps/frontend/src/shared/i18n/locales/de/tour.jsonapps/frontend/src/shared/i18n/locales/en/common.jsonapps/frontend/src/shared/i18n/locales/en/tour.jsonapps/frontend/src/shared/i18n/locales/fr/common.jsonapps/frontend/src/shared/i18n/locales/fr/onboarding.jsonapps/frontend/src/shared/i18n/locales/fr/settings.jsonapps/frontend/src/shared/i18n/locales/fr/tour.jsonapps/frontend/src/vite-env.d.ts
🧰 Additional context used
📓 Path-based instructions (3)
apps/frontend/src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
apps/frontend/src/**/*.{ts,tsx}: Always use translation keys withuseTranslation()for all user-facing text in React/TypeScript frontend components - use formatnamespace:section.key(e.g.,navigation:items.githubPRs)
Never use hardcoded strings in JSX/TSX files for user-facing text - always reference translation keys fromapps/frontend/src/shared/i18n/locales/
Files:
apps/frontend/src/vite-env.d.tsapps/frontend/src/renderer/components/Sidebar.tsxapps/frontend/src/renderer/components/onboarding/CompletionStep.tsxapps/frontend/src/renderer/components/FeatureOverview/FeatureOverview.tsxapps/frontend/src/renderer/hooks/useTour.tsapps/frontend/src/renderer/components/tour/tour-steps.tsapps/frontend/src/renderer/components/onboarding/OAuthStep.tsxapps/frontend/src/renderer/App.tsxapps/frontend/src/renderer/components/KanbanBoard.tsxapps/frontend/src/shared/i18n/index.tsapps/frontend/src/renderer/components/onboarding/wizard-step.schema.tsapps/frontend/src/renderer/components/common/EmptyState.tsxapps/frontend/src/renderer/components/tour/TourOverlay.tsxapps/frontend/src/renderer/contexts/TourContext.tsxapps/frontend/src/renderer/components/tour/index.tsapps/frontend/src/renderer/components/onboarding/FirstSpecStep.tsxapps/frontend/src/renderer/components/onboarding/WelcomeStep.tsxapps/frontend/src/renderer/components/onboarding/GraphitiStep.tsxapps/frontend/src/renderer/components/TerminalGrid.tsxapps/frontend/src/renderer/components/onboarding/OnboardingWizard.tsxapps/frontend/src/renderer/components/onboarding/MemoryStep.tsxapps/frontend/src/renderer/components/FeatureOverview/index.ts
apps/frontend/**/*.{ts,tsx}
⚙️ CodeRabbit configuration file
apps/frontend/**/*.{ts,tsx}: Review React patterns and TypeScript type safety.
Check for proper state management and component composition.
Files:
apps/frontend/src/vite-env.d.tsapps/frontend/src/renderer/components/Sidebar.tsxapps/frontend/src/renderer/components/onboarding/CompletionStep.tsxapps/frontend/src/renderer/components/FeatureOverview/FeatureOverview.tsxapps/frontend/src/renderer/hooks/useTour.tsapps/frontend/src/renderer/components/tour/tour-steps.tsapps/frontend/src/renderer/components/onboarding/OAuthStep.tsxapps/frontend/src/renderer/App.tsxapps/frontend/src/renderer/components/KanbanBoard.tsxapps/frontend/src/shared/i18n/index.tsapps/frontend/src/renderer/components/onboarding/wizard-step.schema.tsapps/frontend/src/renderer/components/common/EmptyState.tsxapps/frontend/src/renderer/components/tour/TourOverlay.tsxapps/frontend/src/renderer/contexts/TourContext.tsxapps/frontend/src/renderer/components/tour/index.tsapps/frontend/src/renderer/components/onboarding/FirstSpecStep.tsxapps/frontend/src/renderer/components/onboarding/WelcomeStep.tsxapps/frontend/src/renderer/components/onboarding/GraphitiStep.tsxapps/frontend/src/renderer/components/TerminalGrid.tsxapps/frontend/src/renderer/components/onboarding/OnboardingWizard.tsxapps/frontend/src/renderer/components/onboarding/MemoryStep.tsxapps/frontend/src/renderer/components/FeatureOverview/index.ts
apps/frontend/src/shared/i18n/locales/**/*.json
📄 CodeRabbit inference engine (CLAUDE.md)
Add new translation keys to ALL language files (minimum:
en/*.jsonandfr/*.json) inapps/frontend/src/shared/i18n/locales/
Files:
apps/frontend/src/shared/i18n/locales/fr/common.jsonapps/frontend/src/shared/i18n/locales/fr/onboarding.jsonapps/frontend/src/shared/i18n/locales/fr/tour.jsonapps/frontend/src/shared/i18n/locales/en/common.jsonapps/frontend/src/shared/i18n/locales/en/tour.jsonapps/frontend/src/shared/i18n/locales/fr/settings.jsonapps/frontend/src/shared/i18n/locales/de/tour.jsonapps/frontend/src/shared/i18n/locales/de/common.json
🧠 Learnings (4)
📚 Learning: 2025-12-25T18:29:32.954Z
Learnt from: CR
Repo: AndyMik90/Auto-Claude PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-25T18:29:32.954Z
Learning: Applies to apps/frontend/src/shared/i18n/locales/**/*.json : Add new translation keys to ALL language files (minimum: `en/*.json` and `fr/*.json`) in `apps/frontend/src/shared/i18n/locales/`
Applied to files:
apps/frontend/src/shared/i18n/locales/fr/common.jsonapps/frontend/src/shared/i18n/locales/fr/onboarding.jsonapps/frontend/src/shared/i18n/locales/fr/tour.jsonapps/frontend/src/shared/i18n/locales/en/common.jsonCLAUDE.mdapps/frontend/src/shared/i18n/index.tsapps/frontend/src/shared/i18n/locales/en/tour.jsonapps/frontend/src/shared/i18n/locales/fr/settings.jsonapps/frontend/src/shared/i18n/locales/de/tour.jsonapps/frontend/src/shared/i18n/locales/de/common.json
📚 Learning: 2025-12-25T18:29:32.954Z
Learnt from: CR
Repo: AndyMik90/Auto-Claude PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-25T18:29:32.954Z
Learning: Applies to apps/frontend/src/**/*.{ts,tsx} : Never use hardcoded strings in JSX/TSX files for user-facing text - always reference translation keys from `apps/frontend/src/shared/i18n/locales/`
Applied to files:
apps/frontend/src/renderer/App.tsxCLAUDE.mdapps/frontend/src/shared/i18n/index.tsapps/frontend/src/shared/i18n/locales/en/tour.jsonapps/frontend/src/shared/i18n/locales/de/tour.jsonapps/frontend/src/shared/i18n/locales/de/common.json
📚 Learning: 2025-12-25T18:29:32.954Z
Learnt from: CR
Repo: AndyMik90/Auto-Claude PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-25T18:29:32.954Z
Learning: Applies to apps/frontend/src/**/*.{ts,tsx} : Always use translation keys with `useTranslation()` for all user-facing text in React/TypeScript frontend components - use format `namespace:section.key` (e.g., `navigation:items.githubPRs`)
Applied to files:
apps/frontend/src/renderer/App.tsxCLAUDE.mdapps/frontend/src/shared/i18n/index.ts
📚 Learning: 2025-12-25T18:29:32.954Z
Learnt from: CR
Repo: AndyMik90/Auto-Claude PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-25T18:29:32.954Z
Learning: Use git worktrees for isolated builds with branch naming convention `auto-claude/{spec-name}` - do NOT automatically push to GitHub
Applied to files:
CLAUDE.md
🧬 Code graph analysis (10)
apps/frontend/src/renderer/components/onboarding/CompletionStep.tsx (1)
apps/frontend/src/renderer/components/onboarding/wizard-step.schema.ts (1)
WizardStepProps(39-56)
apps/frontend/src/renderer/components/FeatureOverview/FeatureOverview.tsx (1)
apps/frontend/src/renderer/contexts/TourContext.tsx (1)
useTourContext(59-65)
apps/frontend/src/renderer/hooks/useTour.ts (2)
apps/frontend/src/renderer/components/tour/TourOverlay.tsx (1)
TourStep(14-27)apps/frontend/src/renderer/components/tour/index.ts (1)
TourStep(5-5)
apps/frontend/src/renderer/components/onboarding/OAuthStep.tsx (1)
apps/frontend/src/renderer/components/onboarding/wizard-step.schema.ts (1)
WizardStepProps(39-56)
apps/frontend/src/renderer/components/common/EmptyState.tsx (1)
apps/frontend/src/renderer/contexts/TourContext.tsx (1)
useTourContext(59-65)
apps/frontend/src/renderer/components/tour/TourOverlay.tsx (4)
apps/frontend/src/renderer/components/tour/index.ts (2)
TourStep(5-5)TourOverlay(5-5).design-system/src/lib/utils.ts (1)
cn(4-6).design-system/src/lib/icons.ts (4)
Sparkles(33-33)X(37-37)ChevronLeft(22-22)ChevronRight(23-23).design-system/src/components/Button.tsx (1)
Button(10-44)
apps/frontend/src/renderer/contexts/TourContext.tsx (4)
apps/frontend/src/renderer/hooks/useTour.ts (2)
UseTourReturn(53-74)useTour(76-162)apps/frontend/src/renderer/components/tour/index.ts (5)
FEATURE_TOURS(6-6)MAIN_TOUR_STEPS(6-6)QUICK_TOUR_STEPS(6-6)TourStep(5-5)TourOverlay(5-5)apps/frontend/src/renderer/components/tour/tour-steps.ts (3)
FEATURE_TOURS(92-127)MAIN_TOUR_STEPS(14-68)QUICK_TOUR_STEPS(73-87)apps/frontend/src/renderer/components/tour/TourOverlay.tsx (2)
TourStep(14-27)TourOverlay(45-278)
apps/frontend/src/renderer/components/onboarding/WelcomeStep.tsx (1)
apps/frontend/src/renderer/components/onboarding/wizard-step.schema.ts (1)
WizardStepProps(39-56)
apps/frontend/src/renderer/components/onboarding/GraphitiStep.tsx (1)
apps/frontend/src/renderer/components/onboarding/wizard-step.schema.ts (1)
WizardStepProps(39-56)
apps/frontend/src/renderer/components/onboarding/MemoryStep.tsx (1)
apps/frontend/src/renderer/components/onboarding/wizard-step.schema.ts (1)
WizardStepProps(39-56)
🪛 Biome (2.1.2)
apps/frontend/src/renderer/components/FeatureOverview/FeatureOverview.tsx
[error] 40-43: Provide an explicit type prop for the button element.
The default type of a button is submit, which causes the submission of a form when placed inside a form element. This is likely not the behaviour that you want inside a React application.
Allowed button types are: submit, button or reset
(lint/a11y/useButtonType)
[error] 118-119: Provide an explicit type prop for the button element.
The default type of a button is submit, which causes the submission of a form when placed inside a form element. This is likely not the behaviour that you want inside a React application.
Allowed button types are: submit, button or reset
(lint/a11y/useButtonType)
apps/frontend/src/renderer/components/common/EmptyState.tsx
[error] 84-85: Provide an explicit type prop for the button element.
The default type of a button is submit, which causes the submission of a form when placed inside a form element. This is likely not the behaviour that you want inside a React application.
Allowed button types are: submit, button or reset
(lint/a11y/useButtonType)
[error] 88-89: Provide an explicit type prop for the button element.
The default type of a button is submit, which causes the submission of a form when placed inside a form element. This is likely not the behaviour that you want inside a React application.
Allowed button types are: submit, button or reset
(lint/a11y/useButtonType)
apps/frontend/src/renderer/components/tour/TourOverlay.tsx
[error] 190-190: Static Elements should not be interactive.
To add interactivity such as a mouse or key event listener to a static element, give the element an appropriate role value.
(lint/a11y/noStaticElementInteractions)
[error] 190-190: Enforce to have the onClick mouse event with the onKeyUp, the onKeyDown, or the onKeyPress keyboard event.
Actions triggered using mouse events should have corresponding keyboard events to account for keyboard-only navigation.
(lint/a11y/useKeyWithClickEvents)
🪛 markdownlint-cli2 (0.18.1)
CLAUDE.md
344-344: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
355-355: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
361-361: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
528-528: Fenced code blocks should be surrounded by blank lines
(MD031, blanks-around-fences)
538-538: Fenced code blocks should be surrounded by blank lines
(MD031, blanks-around-fences)
549-549: Fenced code blocks should be surrounded by blank lines
(MD031, blanks-around-fences)
🔇 Additional comments (49)
apps/frontend/src/vite-env.d.ts (1)
1-11: LGTM!Standard Vite environment type declaration. The interface definitions correctly augment TypeScript's global
ImportMetatype to provide type safety for Vite's environment variables (DEV,PROD,MODE). This enables type-checked access toimport.meta.envthroughout the frontend codebase and aligns with Vite's conventions.apps/frontend/src/renderer/components/Sidebar.tsx (1)
288-288: LGTM! Clean tour system integration.The added
data-tourattributes properly integrate the Sidebar with the new tour system. These are internal identifiers (not user-facing text), so hardcoded strings are appropriate. All user-facing text continues to use proper translation keys, maintaining i18n compliance.Also applies to: 340-340, 367-367
apps/frontend/src/renderer/components/TerminalGrid.tsx (1)
285-285: LGTM! Tour system integration is clean.The
data-tour="terminals"attributes enable the new guided tour system to target these UI sections without any functional changes.Also applies to: 312-312
apps/frontend/src/renderer/components/KanbanBoard.tsx (1)
353-353: Tour ID correctly matches configuration.The
data-tour="kanban-board"attribute correctly targets the tour step defined intour-steps.ts(line 30). The selector and component instrumentation are properly aligned.apps/frontend/src/renderer/App.tsx (1)
55-55: LGTM! TourProvider integration is correct.The TourProvider is properly integrated to wrap the entire application, providing global tour context. The placement inside TooltipProvider but around all app content is appropriate for tour functionality.
Also applies to: 563-563, 867-867
apps/frontend/src/renderer/components/onboarding/GraphitiStep.tsx (1)
30-33: LGTM! Prop type standardization aligns with wizard schema.The change from
GraphitiStepPropstoGraphitiStepPropsInternalaligns GraphitiStep with the new wizard-step schema pattern introduced in this PR. This standardization ensures consistent prop interfaces across all onboarding steps.Also applies to: 110-110
apps/frontend/src/renderer/components/FeatureOverview/index.ts (1)
1-2: LGTM! Standard barrel export pattern.This barrel export allows consumers to use either named or default imports of FeatureOverview, which is a common and flexible pattern.
apps/frontend/src/renderer/components/onboarding/OnboardingWizard.tsx (1)
146-146: LGTM! Prop name standardization for consistency.The change from
onGetStartedtoonNextstandardizes the WelcomeStep prop naming to match the pattern used by other wizard steps. This improves consistency across the onboarding wizard component API.apps/frontend/src/shared/i18n/locales/de/common.json (1)
102-190: All translation sections properly added to required language files.The
emptyStatesandfeatureOverviewsections are correctly present inen/common.json,fr/common.json, andde/common.jsonwith fully matching key structures across all three languages. No action needed.Likely an incorrect or invalid review comment.
apps/frontend/src/shared/i18n/locales/en/tour.json (1)
1-77: Tour namespace is properly configured across all languages and i18n registration.Verification confirms tour.json exists in all required languages (en, fr, de), all keys are present and consistent across language files, and the tour namespace is properly registered in the i18n configuration with imports and namespace declaration.
apps/frontend/src/shared/i18n/locales/fr/onboarding.json (1)
68-82: All required translation keys are present in en/onboarding.json and fr/onboarding.json. The following keys have been verified as present in both files:steps.graphiti,steps.firstSpec,steps.github,steps.linear,steps.agentConfig,graphiti.title,graphiti.description,firstSpec.title, andfirstSpec.description. The German translation file (de/onboarding.json) also contains all matching keys.apps/frontend/src/renderer/components/onboarding/WelcomeStep.tsx (3)
6-9: LGTM! Type-safe props derivation.The internal typing pattern using
Pick<WizardStepProps, ...>is consistent with the broader onboarding refactor and ensures type safety.
39-63: LGTM! Proper i18n usage.All user-facing text correctly uses translation keys via
useTranslation('onboarding')with the namespace:section.key pattern. No hardcoded strings detected.
97-115: LGTM! Correct prop usage and i18n.The action buttons correctly use the new
onNextandonSkipprops, and all button labels are properly internationalized using translation keys.apps/frontend/src/renderer/components/tour/tour-steps.ts (3)
70-87: LGTM! Consistent pattern.The quick tour follows the same i18n pattern as the main tour, properly using translation keys.
89-127: LGTM! Type-safe feature tours.The feature-specific tours use
as constfor proper TypeScript type narrowing and consistently apply translation keys. The categorization (tasks, ideation, roadmap) aligns with the application's feature structure.
14-68: Add missingdata-tourattributes to Ideation and Roadmap componentsThe translation keys are properly implemented and all 26 keys exist in the locale files. However, the FEATURE_TOURS for ideation and roadmap reference
data-tour="ideation"anddata-tour="roadmap"attributes that don't exist on the actual components. The Ideation.tsx and Roadmap.tsx components lack these attributes, so the tour highlighting will fail when users try to run feature-specific tours for those sections.Add
data-tour="ideation"to the root container inapps/frontend/src/renderer/components/ideation/Ideation.tsxanddata-tour="roadmap"to the root container inapps/frontend/src/renderer/components/Roadmap.tsxto enable proper tour targeting.⛔ Skipped due to learnings
Learnt from: CR Repo: AndyMik90/Auto-Claude PR: 0 File: CLAUDE.md:0-0 Timestamp: 2025-12-25T18:29:32.954Z Learning: Applies to apps/frontend/src/**/*.{ts,tsx} : Always use translation keys with `useTranslation()` for all user-facing text in React/TypeScript frontend components - use format `namespace:section.key` (e.g., `navigation:items.githubPRs`)Learnt from: CR Repo: AndyMik90/Auto-Claude PR: 0 File: CLAUDE.md:0-0 Timestamp: 2025-12-25T18:29:32.954Z Learning: Applies to apps/frontend/src/**/*.{ts,tsx} : Never use hardcoded strings in JSX/TSX files for user-facing text - always reference translation keys from `apps/frontend/src/shared/i18n/locales/`apps/frontend/src/shared/i18n/locales/de/tour.json (4)
1-8: LGTM! Navigation translations complete.The navigation section includes all required keys with proper German translations and interpolation placeholders.
43-77: LGTM! Feature tours and actions complete.The quick tour, feature-specific tours (tasks, ideation, roadmap), and action labels are all properly translated in German and match the expected structure from
tour-steps.ts.
1-77: No action needed. All locale files (en/tour.json,fr/tour.json, andde/tour.json) have identical key structures and are already consistent across all nesting levels.Likely an incorrect or invalid review comment.
9-42: Translations are complete and consistent across all language files.All 8 main tour steps and their translations are correctly present in all three required locale files (en, fr, and de). The following keys are verified in
steps,quick, andfeaturesnamespaces:
- steps: welcome, sidebar, kanban, createTask, taskFlow, terminals, settings, ready
- quick: whatsNew
- features: tasks, ideation, roadmap
apps/frontend/src/renderer/components/onboarding/OAuthStep.tsx (1)
31-34: LGTM! Consistent type pattern.The internal props typing using
Pick<WizardStepProps, ...>is consistent with the broader onboarding refactor pattern.apps/frontend/src/shared/i18n/locales/fr/tour.json (1)
1-77: LGTM! French tour translations complete.The French tour localization file has the same structure as the German version, with all required sections (navigation, steps, quick, features, actions) properly translated. The interpolation placeholders (e.g.,
{{current}},{{total}}) are correctly preserved.The cross-locale verification script from the
de/tour.jsonreview will also validate this file's consistency.apps/frontend/src/renderer/components/onboarding/README.md (3)
1-70: LGTM! Clear documentation for adding wizard steps.The quick start guide provides a clear 3-step process with code examples. The translation example correctly emphasizes adding keys to all locale files, which aligns with the coding guidelines.
Note: The past review comment requesting English has been addressed - the README is now in English.
72-111: LGTM! Well-defined priority schema and conditional logic.The priority ranges provide clear guidance for step ordering (0-99 welcome, 100-199 auth, etc.), and the conditional steps pattern with
StepConditionContextoffers flexibility for showing steps based on runtime conditions.
113-129: LGTM! Helpful categories and debugging utilities.The step categories are well-defined and align with the priority schema. The
debugSteps()utility provides helpful debugging capabilities for developers working with the wizard registry.apps/frontend/src/shared/i18n/index.ts (5)
12-12: LGTM! English tour translations imported.The English tour translations are properly imported to support the new tour feature.
22-22: LGTM! French tour translations imported.The French tour translations are properly imported.
24-32: LGTM! Complete German translation imports.All German translation namespaces are properly imported, including the new tour namespace. This provides full German language support across all application areas.
36-67: LGTM! Complete resources configuration for all locales.The resources object is properly configured with:
- Tour namespace added to English and French
- Complete German locale with all 8 namespaces (common, navigation, settings, tasks, welcome, onboarding, dialogs, tour)
The symmetric structure across all three locales ensures consistent i18n behavior.
69-83: LGTM! i18n initialization includes tour namespace.The i18n initialization properly includes the 'tour' namespace in the
nsarray, enabling the tour feature to access translations viauseTranslation('tour').apps/frontend/src/shared/i18n/locales/fr/common.json (2)
102-133: Translation keys complete across all locales.The
emptyStatessection and all its nested keys are present inen/common.json,de/common.json, andfr/common.jsonwith consistent structure and proper localization.
134-190: No issues found. ThefeatureOverviewsection and all nested keys are present in all locale files (en/common.json,fr/common.json, andde/common.json). Translation keys are complete and consistent across all languages.apps/frontend/src/renderer/components/FeatureOverview/FeatureOverview.tsx (1)
51-111: LGTM - Good use of translation keys for all user-facing text.The component correctly uses
useTranslation('common')and references all user-facing strings via thet()function with proper namespaced keys. The features array structure with translation keys is well-organized.apps/frontend/src/renderer/components/onboarding/MemoryStep.tsx (1)
27-30: Type refactor aligns well with the wizard schema system.The internal type alias using
Pick<WizardStepProps, 'onNext' | 'onBack'>correctly constrains the props to only the navigation callbacks needed by this step.apps/frontend/src/renderer/components/onboarding/FirstSpecStep.tsx (2)
15-18: Type refactor correctly includes all required props.The internal type picks the appropriate props (
onNext,onBack,onSkip,onOpenTaskCreator) for this step's functionality.
75-78: Good use of optional chaining for the callback.Using
onOpenTaskCreator?.()is defensive and handles cases where the callback might not be provided.apps/frontend/src/renderer/hooks/useTour.ts (1)
76-161: Well-structured hook with proper React patterns.Good implementation:
useCallbackensures stable function references for consumers- Effect correctly persists state changes
endTourproperly marks completion based on tour typeArray.from(new Set(...))prevents duplicate feature tour IDs- Clean separation between active tour state and persisted completion state
apps/frontend/src/renderer/components/onboarding/CompletionStep.tsx (2)
13-16: Type refactor correctly constrains props for the completion step.The internal type picks
onFinish,onOpenTaskCreator, andonOpenSettings- exactly what this final step needs.
60-87: Excellent i18n implementation.All user-facing strings correctly use
useTranslation('onboarding')with proper translation keys. This is the pattern that should be followed inMemoryStep.tsxandFirstSpecStep.tsx.apps/frontend/src/renderer/components/tour/index.ts (1)
1-6: Clean barrel export for the tour module.The index file provides a well-organized public API, exporting both the component (
TourOverlay), type (TourStep), and constants (MAIN_TOUR_STEPS,QUICK_TOUR_STEPS,FEATURE_TOURS).apps/frontend/src/renderer/contexts/TourContext.tsx (3)
21-57: Well-structured tour context provider.Good patterns:
- Extends the base
useTourhook with convenient high-level methodsstartFeatureTourcorrectly validates steps exist before starting- Single
TourOverlayinstance at provider level prevents duplicates- Context properly typed with
TourContextValue | null
49-54: Clarify: BothonCloseandonCompletecallendTour.Both props call the same
endTourfunction. This is likely intentional (closing early vs completing should both end the tour), but consider if different behavior is needed (e.g.,onClosemight not mark the tour as "seen" if the user dismisses early).If early dismissal should not mark the tour as completed, you may need to add a parameter to
endTour:// In useTour.ts const endTour = useCallback((markAsCompleted = true) => { setIsActive(false); if (markAsCompleted && activeTourId === 'main') { // ... mark as seen } // ... }, [activeTourId]);
59-65: Good error boundary for context usage.The
useTourContexthook correctly throws a descriptive error when used outside ofTourProvider, making debugging easier for developers.apps/frontend/src/shared/i18n/locales/en/common.json (1)
102-190: No action required. The newemptyStatesandfeatureOverviewtranslation keys have been properly added to all language files (en/common.json, fr/common.json, and de/common.json).apps/frontend/src/renderer/components/onboarding/wizard-step.schema.ts (1)
1-204: Well-designed schema system for extensible wizard steps.The schema-based approach with auto-discovery and conditional visibility is excellent. The type definitions are comprehensive, the JSDoc comments are clear, and the helper functions (
defineWizardStep,conditionalStep) provide good ergonomics for step registration.Key strengths:
- Clear separation between step definition and runtime state
- Flexible condition system for dynamic step visibility
- Priority-based ordering with documented ranges
- Type-safe component props via
WizardStepPropsapps/frontend/src/shared/i18n/locales/fr/settings.json (1)
76-88: LGTM! French translations for new path settings added and localized across all language files.The French translations for the new path configuration features (projectBasePath, pathMode, and related descriptions) have been properly added to fr/settings.json. Verification confirms all 13 new keys are also present in en/settings.json and de/settings.json, meeting the requirement to maintain consistent translations across all supported locales.
apps/frontend/src/renderer/components/tour/TourOverlay.tsx (1)
261-273: All required translation keys are properly defined in the locale files (en/tour.json,fr/tour.json,de/tour.json).apps/frontend/src/renderer/components/common/EmptyState.tsx (1)
17-91: All EmptyState translation keys are properly configured in locale files.Verification confirms that all translation keys referenced in the EmptyState component (
emptyStates.kanban.*,emptyStates.ideation.*,emptyStates.roadmap.*,emptyStates.terminals.*,emptyStates.tipsTitle, andemptyStates.takeTour) are present in all locale files:en/common.json,fr/common.json, andde/common.json. The component follows the translation key pattern correctly with theuseTranslation()hook.
| <button className="empty-state-action-primary" onClick={onAction}> | ||
| {t(config.actionKey)} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add explicit type="button" to button elements.
Both buttons are missing the explicit type attribute. In HTML, buttons default to type="submit", which can cause unintended form submissions if this component is rendered inside a form.
🔎 Proposed fix
{config.actionKey && onAction && (
- <button className="empty-state-action-primary" onClick={onAction}>
+ <button type="button" className="empty-state-action-primary" onClick={onAction}>
{t(config.actionKey)}
</button>
)}
- <button className="empty-state-action-secondary" onClick={startMainTour}>
+ <button type="button" className="empty-state-action-secondary" onClick={startMainTour}>
{t('emptyStates.takeTour')}
</button>Also applies to: 88-89
🧰 Tools
🪛 Biome (2.1.2)
[error] 84-85: Provide an explicit type prop for the button element.
The default type of a button is submit, which causes the submission of a form when placed inside a form element. This is likely not the behaviour that you want inside a React application.
Allowed button types are: submit, button or reset
(lint/a11y/useButtonType)
🤖 Prompt for AI Agents
In apps/frontend/src/renderer/components/common/EmptyState.tsx around lines
84-85 and 88-89, the two button elements lack an explicit type attribute and
will default to type="submit" causing accidental form submissions; update both
button elements to include type="button" (e.g., <button type="button" ...>) to
prevent unintended form submission while keeping existing className and onClick
handlers unchanged.
| <style>{` | ||
| .empty-state { | ||
| display: flex; | ||
| flex-direction: column; | ||
| align-items: center; | ||
| justify-content: center; | ||
| padding: 48px 24px; | ||
| text-align: center; | ||
| max-width: 480px; | ||
| margin: 0 auto; | ||
| } | ||
| .empty-state-icon { | ||
| font-size: 64px; | ||
| margin-bottom: 16px; | ||
| opacity: 0.8; | ||
| } | ||
| .empty-state-title { | ||
| font-size: 24px; | ||
| font-weight: 600; | ||
| color: var(--text-primary, #1a1a1a); | ||
| margin: 0 0 8px 0; | ||
| } | ||
| .empty-state-description { | ||
| font-size: 16px; | ||
| color: var(--text-secondary, #666); | ||
| margin: 0 0 24px 0; | ||
| line-height: 1.5; | ||
| } | ||
| .empty-state-tips { | ||
| background: var(--bg-secondary, #f5f5f5); | ||
| border-radius: 12px; | ||
| padding: 16px 24px; | ||
| margin-bottom: 24px; | ||
| width: 100%; | ||
| text-align: left; | ||
| } | ||
| .empty-state-tips h4 { | ||
| font-size: 14px; | ||
| font-weight: 600; | ||
| color: var(--text-primary, #1a1a1a); | ||
| margin: 0 0 12px 0; | ||
| } | ||
| .empty-state-tips ul { | ||
| margin: 0; | ||
| padding-left: 20px; | ||
| } | ||
| .empty-state-tips li { | ||
| font-size: 14px; | ||
| color: var(--text-secondary, #666); | ||
| margin-bottom: 8px; | ||
| line-height: 1.4; | ||
| } | ||
| .empty-state-tips li:last-child { | ||
| margin-bottom: 0; | ||
| } | ||
| .empty-state-actions { | ||
| display: flex; | ||
| gap: 12px; | ||
| flex-wrap: wrap; | ||
| justify-content: center; | ||
| } | ||
| .empty-state-action-primary { | ||
| background: var(--primary-color, #6366f1); | ||
| color: white; | ||
| border: none; | ||
| border-radius: 8px; | ||
| padding: 12px 24px; | ||
| font-size: 14px; | ||
| font-weight: 500; | ||
| cursor: pointer; | ||
| transition: background 0.2s; | ||
| } | ||
| .empty-state-action-primary:hover { | ||
| background: var(--primary-hover, #4f46e5); | ||
| } | ||
| .empty-state-action-secondary { | ||
| background: transparent; | ||
| color: var(--primary-color, #6366f1); | ||
| border: 1px solid var(--primary-color, #6366f1); | ||
| border-radius: 8px; | ||
| padding: 12px 24px; | ||
| font-size: 14px; | ||
| font-weight: 500; | ||
| cursor: pointer; | ||
| transition: all 0.2s; | ||
| } | ||
| .empty-state-action-secondary:hover { | ||
| background: var(--primary-color, #6366f1); | ||
| color: white; | ||
| } | ||
| `}</style> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick | 🔵 Trivial
Consider replacing inline <style> with a proper CSS solution.
Using a <style> tag inside a component creates scoped styles but is not a React best practice. This approach can lead to:
- Style duplication if the component is rendered multiple times
- Difficulty in theming and maintaining consistent design tokens
- No type safety or autocomplete for CSS properties
Consider using CSS Modules, styled-components, or Tailwind CSS classes instead, which align better with the project's existing styling patterns (the codebase already uses Tailwind as seen in TourOverlay.tsx).
🤖 Prompt for AI Agents
In apps/frontend/src/renderer/components/common/EmptyState.tsx around lines
93–196 the component embeds a large inline <style> block; replace this with the
project's preferred styling approach (Tailwind utility classes or a CSS Module)
to avoid duplication and improve maintainability: move the CSS rules into a new
CSS module file (e.g., EmptyState.module.css) or convert rules to Tailwind
classes, keep the existing element classNames (or rename consistently), remove
the inline <style> tag, import the CSS module (or apply Tailwind classes) in the
component, and ensure responsive/variant styles (hover, last-child) are ported
correctly and tested.
| <button | ||
| className="feature-tour-button" | ||
| onClick={() => startFeatureTour(tourId)} | ||
| > | ||
| {t('featureOverview.learnMore')} | ||
| </button> | ||
| )} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add explicit type="button" to prevent unintended form submission.
The button element defaults to type="submit", which can cause unexpected form submissions if this component is rendered inside a form.
🔎 Proposed fix
{tourId && (
<button
+ type="button"
className="feature-tour-button"
onClick={() => startFeatureTour(tourId)}
>
{t('featureOverview.learnMore')}
</button>
)}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| <button | |
| className="feature-tour-button" | |
| onClick={() => startFeatureTour(tourId)} | |
| > | |
| {t('featureOverview.learnMore')} | |
| </button> | |
| )} | |
| <button | |
| type="button" | |
| className="feature-tour-button" | |
| onClick={() => startFeatureTour(tourId)} | |
| > | |
| {t('featureOverview.learnMore')} | |
| </button> | |
| )} |
🧰 Tools
🪛 Biome (2.1.2)
[error] 40-43: Provide an explicit type prop for the button element.
The default type of a button is submit, which causes the submission of a form when placed inside a form element. This is likely not the behaviour that you want inside a React application.
Allowed button types are: submit, button or reset
(lint/a11y/useButtonType)
🤖 Prompt for AI Agents
In apps/frontend/src/renderer/components/FeatureOverview/FeatureOverview.tsx
around lines 40 to 46, the <button> used for "learn more" lacks an explicit type
and will default to type="submit" when nested in a form; update the button to
include type="button" to prevent unintended form submissions and keep the
onClick behavior intact.
| <button className="start-tour-button" onClick={startMainTour}> | ||
| {t('featureOverview.startTour')} | ||
| </button> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add explicit type="button" to the start tour button.
Same issue as the feature tour button - missing explicit button type.
🔎 Proposed fix
- <button className="start-tour-button" onClick={startMainTour}>
+ <button type="button" className="start-tour-button" onClick={startMainTour}>
{t('featureOverview.startTour')}
</button>📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| <button className="start-tour-button" onClick={startMainTour}> | |
| {t('featureOverview.startTour')} | |
| </button> | |
| <button type="button" className="start-tour-button" onClick={startMainTour}> | |
| {t('featureOverview.startTour')} | |
| </button> |
🧰 Tools
🪛 Biome (2.1.2)
[error] 118-119: Provide an explicit type prop for the button element.
The default type of a button is submit, which causes the submission of a form when placed inside a form element. This is likely not the behaviour that you want inside a React application.
Allowed button types are: submit, button or reset
(lint/a11y/useButtonType)
🤖 Prompt for AI Agents
In apps/frontend/src/renderer/components/FeatureOverview/FeatureOverview.tsx
around lines 118-120, the start-tour button is missing an explicit type
attribute which can cause it to act as a submit button in forms; update the JSX
to add type="button" to the <button> element (i.e., <button type="button"
className="start-tour-button" onClick={startMainTour}>...) so it behaves as a
non-submit control.
| <style>{` | ||
| .feature-overview { | ||
| max-width: 1200px; | ||
| margin: 0 auto; | ||
| padding: 32px 24px; | ||
| } | ||
| .feature-overview-header { | ||
| text-align: center; | ||
| margin-bottom: 48px; | ||
| } | ||
| .feature-overview-header h1 { | ||
| font-size: 32px; | ||
| font-weight: 700; | ||
| color: var(--text-primary, #1a1a1a); | ||
| margin: 0 0 8px 0; | ||
| } | ||
| .feature-overview-subtitle { | ||
| font-size: 18px; | ||
| color: var(--text-secondary, #666); | ||
| margin: 0 0 24px 0; | ||
| } | ||
| .start-tour-button { | ||
| background: var(--primary-color, #6366f1); | ||
| color: white; | ||
| border: none; | ||
| border-radius: 8px; | ||
| padding: 14px 28px; | ||
| font-size: 16px; | ||
| font-weight: 500; | ||
| cursor: pointer; | ||
| transition: background 0.2s; | ||
| } | ||
| .start-tour-button:hover { | ||
| background: var(--primary-hover, #4f46e5); | ||
| } | ||
| .feature-overview-intro { | ||
| background: linear-gradient(135deg, var(--primary-color, #6366f1) 0%, #8b5cf6 100%); | ||
| color: white; | ||
| padding: 32px; | ||
| border-radius: 16px; | ||
| margin-bottom: 48px; | ||
| } | ||
| .feature-overview-intro h2 { | ||
| font-size: 24px; | ||
| margin: 0 0 12px 0; | ||
| } | ||
| .feature-overview-intro p { | ||
| font-size: 16px; | ||
| line-height: 1.6; | ||
| margin: 0; | ||
| opacity: 0.95; | ||
| } | ||
| .feature-cards { | ||
| display: grid; | ||
| grid-template-columns: repeat(auto-fit, minmax(340px, 1fr)); | ||
| gap: 24px; | ||
| margin-bottom: 48px; | ||
| } | ||
| .feature-card { | ||
| background: var(--bg-primary, white); | ||
| border: 1px solid var(--border-color, #e5e5e5); | ||
| border-radius: 12px; | ||
| padding: 24px; | ||
| transition: transform 0.2s, box-shadow 0.2s; | ||
| } | ||
| .feature-card:hover { | ||
| transform: translateY(-4px); | ||
| box-shadow: 0 12px 24px rgba(0, 0, 0, 0.1); | ||
| } | ||
| .feature-card-header { | ||
| display: flex; | ||
| align-items: center; | ||
| gap: 12px; | ||
| margin-bottom: 12px; | ||
| } | ||
| .feature-icon { | ||
| font-size: 32px; | ||
| } | ||
| .feature-card-header h3 { | ||
| font-size: 20px; | ||
| font-weight: 600; | ||
| color: var(--text-primary, #1a1a1a); | ||
| margin: 0; | ||
| } | ||
| .feature-description { | ||
| font-size: 14px; | ||
| color: var(--text-secondary, #666); | ||
| line-height: 1.5; | ||
| margin: 0 0 16px 0; | ||
| } | ||
| .feature-steps { | ||
| background: var(--bg-secondary, #f5f5f5); | ||
| border-radius: 8px; | ||
| padding: 16px; | ||
| margin-bottom: 16px; | ||
| } | ||
| .feature-steps h4 { | ||
| font-size: 12px; | ||
| font-weight: 600; | ||
| color: var(--text-secondary, #666); | ||
| text-transform: uppercase; | ||
| letter-spacing: 0.5px; | ||
| margin: 0 0 12px 0; | ||
| } | ||
| .feature-steps ol { | ||
| margin: 0; | ||
| padding-left: 20px; | ||
| } | ||
| .feature-steps li { | ||
| font-size: 14px; | ||
| color: var(--text-primary, #1a1a1a); | ||
| margin-bottom: 8px; | ||
| line-height: 1.4; | ||
| } | ||
| .feature-steps li:last-child { | ||
| margin-bottom: 0; | ||
| } | ||
| .feature-tour-button { | ||
| background: transparent; | ||
| color: var(--primary-color, #6366f1); | ||
| border: 1px solid var(--primary-color, #6366f1); | ||
| border-radius: 6px; | ||
| padding: 8px 16px; | ||
| font-size: 14px; | ||
| cursor: pointer; | ||
| transition: all 0.2s; | ||
| width: 100%; | ||
| } | ||
| .feature-tour-button:hover { | ||
| background: var(--primary-color, #6366f1); | ||
| color: white; | ||
| } | ||
| .feature-overview-footer { | ||
| background: var(--bg-secondary, #f5f5f5); | ||
| border-radius: 16px; | ||
| padding: 32px; | ||
| text-align: center; | ||
| } | ||
| .feature-overview-footer h2 { | ||
| font-size: 24px; | ||
| font-weight: 600; | ||
| color: var(--text-primary, #1a1a1a); | ||
| margin: 0 0 8px 0; | ||
| } | ||
| .feature-overview-footer > p { | ||
| font-size: 16px; | ||
| color: var(--text-secondary, #666); | ||
| margin: 0 0 24px 0; | ||
| } | ||
| .quick-start-steps { | ||
| display: flex; | ||
| justify-content: center; | ||
| gap: 32px; | ||
| flex-wrap: wrap; | ||
| } | ||
| .quick-start-step { | ||
| display: flex; | ||
| align-items: center; | ||
| gap: 12px; | ||
| } | ||
| .step-number { | ||
| width: 32px; | ||
| height: 32px; | ||
| background: var(--primary-color, #6366f1); | ||
| color: white; | ||
| border-radius: 50%; | ||
| display: flex; | ||
| align-items: center; | ||
| justify-content: center; | ||
| font-weight: 600; | ||
| font-size: 14px; | ||
| } | ||
| .quick-start-step span:last-child { | ||
| font-size: 14px; | ||
| color: var(--text-primary, #1a1a1a); | ||
| } | ||
| `}</style> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick | 🔵 Trivial
Consider extracting inline styles to a CSS module or Tailwind classes.
The component embeds ~200 lines of CSS via a <style> tag. While functional, this approach:
- Injects styles into the DOM on every render
- Doesn't benefit from CSS extraction/minification during build
- Makes the component harder to maintain
Consider migrating to CSS modules, a separate stylesheet, or Tailwind utility classes for better maintainability and performance.
| default: | ||
| return { | ||
| position: 'fixed', | ||
| top: targetRect.bottom + padding, | ||
| left: targetRect.left + targetRect.width / 2, | ||
| transform: 'translateX(-50%)' | ||
| }; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick | 🔵 Trivial
Remove duplicate code in default case.
The default case in the switch statement (lines 177-184) is identical to the 'bottom' case (lines 156-162). Since JavaScript switch statements fall through to default when no case matches, this duplication is unnecessary.
🔎 Proposed refactor
case 'right':
return {
position: 'fixed',
top: targetRect.top + targetRect.height / 2,
left: targetRect.right + padding,
transform: 'translateY(-50%)'
};
- default:
- return {
- position: 'fixed',
- top: targetRect.bottom + padding,
- left: targetRect.left + targetRect.width / 2,
- transform: 'translateX(-50%)'
- };
+ default:
+ // Falls through to 'bottom' behavior
+ return getTooltipStyle();
}
};Or simply remove the default case since 'bottom' is already handled and you have a fallback position assignment on line 146.
Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In apps/frontend/src/renderer/components/tour/TourOverlay.tsx around lines
177-184, the switch's default case duplicates the 'bottom' case logic at lines
156-162; remove the redundant default block (or collapse it to fall through to
the 'bottom' case) so the switch relies on the existing 'bottom' case and the
existing fallback at line 146, keeping behavior unchanged and eliminating
duplicate code.
| return ( | ||
| <div className="fixed inset-0 z-[100]"> | ||
| {/* Dark overlay with cutout for target */} | ||
| <div className="absolute inset-0 bg-black/60" onClick={handleClose} /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add keyboard handler and role for accessibility.
The dark overlay is interactive but lacks keyboard event handling and an appropriate ARIA role. Users navigating with keyboards cannot dismiss the tour by clicking the overlay.
🔎 Proposed fix
- <div className="absolute inset-0 bg-black/60" onClick={handleClose} />
+ <div
+ className="absolute inset-0 bg-black/60"
+ onClick={handleClose}
+ onKeyDown={(e) => {
+ if (e.key === 'Enter' || e.key === ' ') {
+ e.preventDefault();
+ handleClose();
+ }
+ }}
+ role="button"
+ tabIndex={0}
+ aria-label="Close tour"
+ />📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| <div className="absolute inset-0 bg-black/60" onClick={handleClose} /> | |
| <div | |
| className="absolute inset-0 bg-black/60" | |
| onClick={handleClose} | |
| onKeyDown={(e) => { | |
| if (e.key === 'Enter' || e.key === ' ') { | |
| e.preventDefault(); | |
| handleClose(); | |
| } | |
| }} | |
| role="button" | |
| tabIndex={0} | |
| aria-label="Close tour" | |
| /> |
🧰 Tools
🪛 Biome (2.1.2)
[error] 190-190: Static Elements should not be interactive.
To add interactivity such as a mouse or key event listener to a static element, give the element an appropriate role value.
(lint/a11y/noStaticElementInteractions)
[error] 190-190: Enforce to have the onClick mouse event with the onKeyUp, the onKeyDown, or the onKeyPress keyboard event.
Actions triggered using mouse events should have corresponding keyboard events to account for keyboard-only navigation.
(lint/a11y/useKeyWithClickEvents)
🤖 Prompt for AI Agents
In apps/frontend/src/renderer/components/tour/TourOverlay.tsx around line 190,
the dark overlay div is clickable but not accessible via keyboard or screen
readers; update the div to be focusable and expose an ARIA role and label, e.g.
add role="button", tabIndex={0}, and aria-label="Close tour overlay"; implement
an onKeyDown handler that calls handleClose when Enter or Space (and optionally
Escape) is pressed (prevent default for Space), and keep the existing onClick
behavior so keyboard and assistive tech users can dismiss the tour.
| function loadTourState(): TourState { | ||
| try { | ||
| const stored = localStorage.getItem(TOUR_STORAGE_KEY); | ||
| if (stored) { | ||
| const state = JSON.parse(stored) as TourState; | ||
| // Reset if version changed (new features added) | ||
| if (state.lastTourVersion !== CURRENT_TOUR_VERSION) { | ||
| return { ...defaultState, lastTourVersion: CURRENT_TOUR_VERSION }; | ||
| } | ||
| return state; | ||
| } | ||
| } catch (e) { | ||
| console.error('Failed to load tour state:', e); | ||
| } | ||
| return defaultState; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick | 🔵 Trivial
Add runtime validation for localStorage data.
The parsed JSON is directly cast to TourState without validating its structure. Corrupted or tampered localStorage data could cause runtime errors.
🔎 Proposed fix with validation
function loadTourState(): TourState {
try {
const stored = localStorage.getItem(TOUR_STORAGE_KEY);
if (stored) {
const state = JSON.parse(stored) as TourState;
+ // Validate required properties exist
+ if (
+ typeof state.hasSeenMainTour !== 'boolean' ||
+ typeof state.hasSeenQuickTour !== 'boolean' ||
+ !Array.isArray(state.completedFeatureTours) ||
+ typeof state.lastTourVersion !== 'string'
+ ) {
+ console.warn('Invalid tour state in localStorage, resetting');
+ return defaultState;
+ }
// Reset if version changed (new features added)
if (state.lastTourVersion !== CURRENT_TOUR_VERSION) {
return { ...defaultState, lastTourVersion: CURRENT_TOUR_VERSION };
}
return state;
}
} catch (e) {
console.error('Failed to load tour state:', e);
}
return defaultState;
}🤖 Prompt for AI Agents
In apps/frontend/src/renderer/hooks/useTour.ts around lines 28 to 43, the code
JSON-parses localStorage and casts to TourState without validating shape, which
can lead to runtime errors if data is corrupted; add a small runtime
validation/type-guard that checks required properties (e.g., lastTourVersion is
a string/number as expected and any other fields in TourState have correct
types) before accepting the parsed object, and if validation fails log a warning
and return defaultState (or the reset-with-current-version object when
appropriate); implement the validator as a local function
(isValidTourState(obj): obj is TourState) and use it after JSON.parse to guard
the cast and avoid throwing on bad data.
| ### ⚠️ CRITICAL RULES - READ FIRST | ||
|
|
||
| **These rules MUST be followed at all times:** | ||
|
|
||
| #### 1. Language & Localization Rules | ||
| - **README.md**: ALWAYS in English - never translate to other languages | ||
| - **Git commits**: ALWAYS in English - use descriptive commit messages | ||
| - **Code comments**: English preferred for maintainability | ||
| - **i18n translations**: MUST always update ALL 3 languages when adding/changing user-facing text: | ||
| - English (`locales/en/*.json`) - PRIMARY | ||
| - German (`locales/de/*.json`) | ||
| - French (`locales/fr/*.json`) | ||
|
|
||
| **NEVER add a new translation key without adding it to all 3 language files!** | ||
|
|
||
| #### 2. Documentation Rules | ||
| - **Technical docs**: English only (README.md, CLAUDE.md, guides/) | ||
| - **In-app text**: Use i18n translation keys, update all 3 languages | ||
| - **PR descriptions**: English only | ||
| - **Code review comments**: English preferred | ||
|
|
||
| #### 3. Git Workflow Rules | ||
| - **NEVER** add Claude/AI attribution to commits (no "Generated with Claude Code") | ||
| - **NEVER** add Co-Authored-By headers for AI | ||
| - Commits should be clean, professional, and describe the actual change | ||
| - Use conventional commit format when possible: `feat:`, `fix:`, `docs:`, etc. | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix markdown formatting issues around headings.
Static analysis tools flagged missing blank lines around headings. While these are minor formatting issues, fixing them improves readability and consistency with markdown best practices.
🔎 Proposed formatting fixes
### ⚠️ CRITICAL RULES - READ FIRST
+
**These rules MUST be followed at all times:**
+
#### 1. Language & Localization Rules
+
- **README.md**: ALWAYS in English - never translate to other languages
- **Git commits**: ALWAYS in English - use descriptive commit messages
- **Code comments**: English preferred for maintainability
- **i18n translations**: MUST always update ALL 3 languages when adding/changing user-facing text:
- English (`locales/en/*.json`) - PRIMARY
- German (`locales/de/*.json`)
- French (`locales/fr/*.json`)
**NEVER add a new translation key without adding it to all 3 language files!**
+
#### 2. Documentation Rules
+
- **Technical docs**: English only (README.md, CLAUDE.md, guides/)
- **In-app text**: Use i18n translation keys, update all 3 languages
- **PR descriptions**: English only
- **Code review comments**: English preferred
+
#### 3. Git Workflow Rules
+
- **NEVER** add Claude/AI attribution to commits (no "Generated with Claude Code")
- **NEVER** add Co-Authored-By headers for AI
- Commits should be clean, professional, and describe the actual change
- Use conventional commit format when possible: `feat:`, `fix:`, `docs:`, etc.📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| ### ⚠️ CRITICAL RULES - READ FIRST | |
| **These rules MUST be followed at all times:** | |
| #### 1. Language & Localization Rules | |
| - **README.md**: ALWAYS in English - never translate to other languages | |
| - **Git commits**: ALWAYS in English - use descriptive commit messages | |
| - **Code comments**: English preferred for maintainability | |
| - **i18n translations**: MUST always update ALL 3 languages when adding/changing user-facing text: | |
| - English (`locales/en/*.json`) - PRIMARY | |
| - German (`locales/de/*.json`) | |
| - French (`locales/fr/*.json`) | |
| **NEVER add a new translation key without adding it to all 3 language files!** | |
| #### 2. Documentation Rules | |
| - **Technical docs**: English only (README.md, CLAUDE.md, guides/) | |
| - **In-app text**: Use i18n translation keys, update all 3 languages | |
| - **PR descriptions**: English only | |
| - **Code review comments**: English preferred | |
| #### 3. Git Workflow Rules | |
| - **NEVER** add Claude/AI attribution to commits (no "Generated with Claude Code") | |
| - **NEVER** add Co-Authored-By headers for AI | |
| - Commits should be clean, professional, and describe the actual change | |
| - Use conventional commit format when possible: `feat:`, `fix:`, `docs:`, etc. | |
| ### ⚠️ CRITICAL RULES - READ FIRST | |
| **These rules MUST be followed at all times:** | |
| #### 1. Language & Localization Rules | |
| - **README.md**: ALWAYS in English - never translate to other languages | |
| - **Git commits**: ALWAYS in English - use descriptive commit messages | |
| - **Code comments**: English preferred for maintainability | |
| - **i18n translations**: MUST always update ALL 3 languages when adding/changing user-facing text: | |
| - English (`locales/en/*.json`) - PRIMARY | |
| - German (`locales/de/*.json`) | |
| - French (`locales/fr/*.json`) | |
| **NEVER add a new translation key without adding it to all 3 language files!** | |
| #### 2. Documentation Rules | |
| - **Technical docs**: English only (README.md, CLAUDE.md, guides/) | |
| - **In-app text**: Use i18n translation keys, update all 3 languages | |
| - **PR descriptions**: English only | |
| - **Code review comments**: English preferred | |
| #### 3. Git Workflow Rules | |
| - **NEVER** add Claude/AI attribution to commits (no "Generated with Claude Code") | |
| - **NEVER** add Co-Authored-By headers for AI | |
| - Commits should be clean, professional, and describe the actual change | |
| - Use conventional commit format when possible: `feat:`, `fix:`, `docs:`, etc. |
🧰 Tools
🪛 markdownlint-cli2 (0.18.1)
344-344: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
355-355: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
361-361: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
🤖 Prompt for AI Agents
In CLAUDE.md around lines 340 to 366, there are Markdown headings that lack the
required blank lines before and/or after them, causing static analyzers to flag
formatting issues; fix by inserting a single blank line above each heading and
ensure there is a blank line after the heading text or preceding content as
appropriate so headings are separated from surrounding paragraphs/lists, then
run a Markdown linter or preview to confirm no other adjacent heading spacing
issues remain.
| ## GitHub Integration & PR Feedback | ||
|
|
||
| ### Checking PR Feedback | ||
|
|
||
| When working on a forked repository, regularly check for PR feedback from the upstream maintainer: | ||
|
|
||
| ```bash | ||
| # Fetch PR comments and reviews | ||
| gh pr view <PR_NUMBER> --repo <ORIGINAL_OWNER>/<REPO> --comments | ||
|
|
||
| # View PR review comments | ||
| gh api repos/<ORIGINAL_OWNER>/<REPO>/pulls/<PR_NUMBER>/reviews | ||
|
|
||
| # View inline code comments | ||
| gh api repos/<ORIGINAL_OWNER>/<REPO>/pulls/<PR_NUMBER>/comments | ||
| ``` | ||
|
|
||
| **Example for this project:** | ||
| ```bash | ||
| # Check PR feedback from upstream (AndyMik90/Auto-Claude) | ||
| gh pr view 345 --repo AndyMik90/Auto-Claude --comments | ||
| ``` | ||
|
|
||
| ### Automated PR Feedback Workflow | ||
|
|
||
| To automatically process PR feedback, you can use this workflow: | ||
|
|
||
| 1. **Fetch PR comments:** | ||
| ```bash | ||
| gh api repos/AndyMik90/Auto-Claude/pulls/345/comments --jq '.[] | {user: .user.login, body: .body, path: .path}' | ||
| ``` | ||
|
|
||
| 2. **Process feedback items as tasks:** | ||
| - Each comment should be analyzed | ||
| - Create todo items for requested changes | ||
| - Update all 3 languages if translation changes are requested | ||
| - Test changes before pushing | ||
|
|
||
| 3. **Respond to feedback:** | ||
| ```bash | ||
| # After making changes, push and comment | ||
| git push origin <branch> | ||
| gh pr comment 345 --repo AndyMik90/Auto-Claude --body "Addressed feedback: [description]" | ||
| ``` | ||
|
|
||
| ### Pre-commit Checklist | ||
|
|
||
| Before committing changes, verify: | ||
|
|
||
| - [ ] All user-facing text uses i18n translation keys | ||
| - [ ] Translation keys exist in all 3 languages (en, de, fr) | ||
| - [ ] README.md is in English | ||
| - [ ] Commit message is in English | ||
| - [ ] No Claude/AI attribution in commit | ||
| - [ ] TypeScript compiles without errors (`npx tsc --noEmit`) | ||
| - [ ] All tests pass | ||
|
|
||
| ### i18n Translation Validation | ||
|
|
||
| To check for missing translations: | ||
|
|
||
| ```bash | ||
| # Check if all languages have the same keys | ||
| cd apps/frontend/src/shared/i18n/locales | ||
|
|
||
| # Compare English vs German | ||
| diff <(jq -r 'paths(scalars) | join(".")' en/common.json | sort) \ | ||
| <(jq -r 'paths(scalars) | join(".")' de/common.json | sort) | ||
|
|
||
| # Compare English vs French | ||
| diff <(jq -r 'paths(scalars) | join(".")' en/common.json | sort) \ | ||
| <(jq -r 'paths(scalars) | join(".")' fr/common.json | sort) | ||
| ``` | ||
|
|
||
| This helps identify missing translations before pushing changes. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix markdown formatting issues around code blocks.
Static analysis flagged missing blank lines around fenced code blocks. These should be fixed for consistency.
🔎 Proposed formatting fixes
## GitHub Integration & PR Feedback
### Checking PR Feedback
When working on a forked repository, regularly check for PR feedback from the upstream maintainer:
```bash
# Fetch PR comments and reviews
gh pr view <PR_NUMBER> --repo <ORIGINAL_OWNER>/<REPO> --comments
# View PR review comments
gh api repos/<ORIGINAL_OWNER>/<REPO>/pulls/<PR_NUMBER>/reviews
# View inline code comments
gh api repos/<ORIGINAL_OWNER>/<REPO>/pulls/<PR_NUMBER>/commentsExample for this project:
+
# Check PR feedback from upstream (AndyMik90/Auto-Claude)
gh pr view 345 --repo AndyMik90/Auto-Claude --commentsAutomated PR Feedback Workflow
To automatically process PR feedback, you can use this workflow:
- Fetch PR comments:
-
gh api repos/AndyMik90/Auto-Claude/pulls/345/comments --jq '.[] | {user: .user.login, body: .body, path: .path}'
-
Process feedback items as tasks:
- Each comment should be analyzed
- Create todo items for requested changes
- Update all 3 languages if translation changes are requested
- Test changes before pushing
-
Respond to feedback:
-
# After making changes, push and comment git push origin <branch> gh pr comment 345 --repo AndyMik90/Auto-Claude --body "Addressed feedback: [description]"
</details>
<details>
<summary>🧰 Tools</summary>
<details>
<summary>🪛 markdownlint-cli2 (0.18.1)</summary>
528-528: Fenced code blocks should be surrounded by blank lines
(MD031, blanks-around-fences)
---
538-538: Fenced code blocks should be surrounded by blank lines
(MD031, blanks-around-fences)
---
549-549: Fenced code blocks should be surrounded by blank lines
(MD031, blanks-around-fences)
</details>
</details>
<details>
<summary>🤖 Prompt for AI Agents</summary>
In CLAUDE.md around lines 510 to 584, fenced code blocks are missing required
blank lines before and after them which breaks Markdown rendering and triggers
static-analysis warnings; fix by adding a blank line before each opening and a blank line after each closing throughout this section (including the
example and the Automated PR Feedback Workflow code blocks and the snippet
inside the details block), and ensure indentation/spacing inside the fenced
blocks is consistent (remove stray leading plus signs and stray language labels
outside the opening fence).
</details>
<!-- fingerprinting:phantom:poseidon:puma -->
<!-- This is an auto-generated comment by CodeRabbit -->
AndyMik90
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🤖 Auto Claude PR Review
Merge Verdict: 🔴 BLOCKED
Blocked by 5 critical issues
Risk Assessment
| Factor | Level | Notes |
|---|---|---|
| Complexity | High | Based on lines changed |
| Security Impact | None | Based on security findings |
| Scope Coherence | Good | Based on structural review |
🚨 Blocking Issues (Must Fix)
- Critical: German language not in SupportedLanguage type (apps/frontend/src/shared/constants/i18n.ts:6)
- Critical: German not in AVAILABLE_LANGUAGES array (apps/frontend/src/shared/constants/i18n.ts:8)
- Critical: German locale imports missing from i18n configuration (apps/frontend/src/shared/i18n/index.ts:None)
- Critical: Missing 'de' key in resources object (apps/frontend/src/shared/i18n/index.ts:26)
- Critical: Missing 'tour' namespace in ns array (apps/frontend/src/shared/i18n/index.ts:56)
Findings Summary
- Critical: 5 issue(s)
Generated by Auto Claude PR Review
Findings (5 selected of 5 total)
🔴 [CRITICAL] German language not in SupportedLanguage type
📁 apps/frontend/src/shared/constants/i18n.ts:6
The SupportedLanguage type is defined as 'en' | 'fr' and does NOT include 'de'. This will cause TypeScript compilation errors when users attempt to set language to German in settings.
Suggested fix:
Update type to: export type SupportedLanguage = 'en' | 'fr' | 'de';
🔴 [CRITICAL] German not in AVAILABLE_LANGUAGES array
📁 apps/frontend/src/shared/constants/i18n.ts:8
The AVAILABLE_LANGUAGES array only contains English and French. German must be added for users to see and select it in the language settings dropdown.
Suggested fix:
Add { value: 'de' as const, label: 'German', nativeLabel: 'Deutsch' } to AVAILABLE_LANGUAGES
🔴 [CRITICAL] German locale imports missing from i18n configuration
📁 apps/frontend/src/shared/i18n/index.ts:null
The i18n/index.ts file currently imports only English and French locale files. German imports (deCommon, deNavigation, deSettings, etc.) are completely missing. Without these imports, German translations will not be available at runtime.
Suggested fix:
Add German import statements after French imports: import deCommon from './locales/de/common.json'; import deNavigation from './locales/de/navigation.json'; etc. for all locale files
🔴 [CRITICAL] Missing 'de' key in resources object
📁 apps/frontend/src/shared/i18n/index.ts:26
The resources object only contains 'en' and 'fr' keys. A 'de' key with all German namespace mappings must be added for i18next to serve German translations.
Suggested fix:
Add 'de: { common: deCommon, navigation: deNavigation, settings: deSettings, tasks: deTasks, welcome: deWelcome, onboarding: deOnboarding, dialogs: deDialogs, taskReview: deTaskReview }' to resources
🔴 [CRITICAL] Missing 'tour' namespace in ns array
📁 apps/frontend/src/shared/i18n/index.ts:56
The PR adds tour.json files for all locales, but the ns (namespaces) array does not include 'tour'. This means tour translations will not be loaded by i18next even if the files exist.
Suggested fix:
Add 'tour' to the ns array: ns: ['common', 'navigation', 'settings', 'tasks', 'welcome', 'onboarding', 'dialogs', 'taskReview', 'tour']
This review was generated by Auto Claude.
Re-Review RequestThe Auto Claude PR Review flagged 5 critical issues, but I've verified that all issues are already fixed in the current code: Verification Results
The review may have been triggered on an older commit. Current HEAD is Could you please re-run the review or manually verify the files? Verification performed by checking local files against remote branch |
|
|
German Language Support:
Schema-Based Wizard System:
The new wizard system allows adding new steps by:
Steps are automatically sorted by priority and filtered by conditions. No changes to the main wizard component needed when adding new features.
Priority ranges:
Base Branch
developbranch (required for all feature/fix PRs)main(hotfix only - maintainers)Description
Related Issue
Closes #
Type of Change
Area
Commit Message Format
Follow conventional commits:
<type>: <subject>Types: feat, fix, docs, style, refactor, test, chore
Example:
feat: add user authentication systemChecklist
developbranchCI/Testing Requirements
Screenshots
Feature Toggle
use_feature_nameBreaking Changes
Breaking: Yes / No
Details:
Summary by CodeRabbit
New Features
Localization
Documentation
✏️ Tip: You can customize this high-level summary in your review settings.