Repository navigation
Conversation
…oyment errors Add install_command and output_dir project columns (migration 0008) and wire them through the railpack config generator. Summarize deployment and rollback failures to the most actionable line instead of the full raw stderr transcript.
📝 WalkthroughWalkthroughThe pull request replaces the multi-step project creation flow with a single-page form. It adds framework presets, reusable selectors, source uploads, environment-variable staging, Compose mappings, project settings fields, and expanded Railpack static-project handling. ChangesProject creation and configuration
Estimated code review effort: 5 (Critical) | ~90 minutes Possibly related PRs
Sequence Diagram(s)sequenceDiagram
participant CreateProjectPage
participant SourceSelectionSection
participant uploadSourceZip
participant ProjectAPI
participant setEnvVar
SourceSelectionSection->>CreateProjectPage: select source
CreateProjectPage->>uploadSourceZip: upload ZIP when selected
uploadSourceZip->>ProjectAPI: POST multipart data to /upload
ProjectAPI-->>CreateProjectPage: return filePath
CreateProjectPage->>ProjectAPI: create project
CreateProjectPage->>setEnvVar: create staged variables sequentially
setEnvVar->>ProjectAPI: create environment variable
ProjectAPI-->>CreateProjectPage: return project id
CreateProjectPage->>CreateProjectPage: navigate to deployments tab
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (3 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 18
🧹 Nitpick comments (11)
apps/web/src/components/project/create/SourceSelectionSection.tsx (1)
55-55: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueRemove nonessential JSX section comments. The adjacent JSX already identifies these sections.
apps/web/src/components/project/create/SourceSelectionSection.tsx#L55-L55: delete the section comments at Lines 55, 102, and 154.apps/web/src/components/project/create/ApplicationPresetSection.tsx#L32-L32: delete the section comment at Line 32.apps/web/src/components/project/create/BuildStrategySection.tsx#L76-L76: delete the section comments at Lines 76, 123, 126, 137, 187, and 266.As per coding guidelines, “No comments in source code unless absolutely necessary.”
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/web/src/components/project/create/SourceSelectionSection.tsx` at line 55, Remove the nonessential JSX section comments from SourceSelectionSection.tsx at lines 55, 102, and 154; ApplicationPresetSection.tsx at line 32; and BuildStrategySection.tsx at lines 76, 123, 126, 137, 187, and 266. Leave the surrounding JSX and behavior unchanged.Source: Coding guidelines
apps/web/src/components/ui/DatabaseSelect.tsx (2)
60-98: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd
aria-expandedand Escape-key dismissal.The trigger button exposes no expanded state to assistive technology. The dropdown also cannot be closed with the keyboard. Add
aria-expanded={isOpen}andaria-haspopup="listbox"on the trigger, and close on Escape. Attach the outside-click listener only whenisOpenis true.♻️ Proposed fix
useEffect(() => { + if (!isOpen) return; function handleClickOutside(event: MouseEvent) { if (containerRef.current && !containerRef.current.contains(event.target as Node)) { setIsOpen(false); } } + function handleKeyDown(event: KeyboardEvent) { + if (event.key === 'Escape') setIsOpen(false); + } document.addEventListener('mousedown', handleClickOutside); - return () => document.removeEventListener('mousedown', handleClickOutside); - }, []); + document.addEventListener('keydown', handleKeyDown); + return () => { + document.removeEventListener('mousedown', handleClickOutside); + document.removeEventListener('keydown', handleKeyDown); + }; + }, [isOpen]);<button type="button" + aria-expanded={isOpen} + aria-haspopup="listbox" onClick={() => setIsOpen(!isOpen)}🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/web/src/components/ui/DatabaseSelect.tsx` around lines 60 - 98, Update the trigger button in DatabaseSelect to include aria-expanded={isOpen} and aria-haspopup="listbox". Modify the outside-click useEffect to register its listener only while isOpen, and add Escape-key handling that calls setIsOpen(false) when the dropdown is open; ensure cleanup removes any registered listeners.
14-45: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winReuse
DATABASE_ENGINESfor default versions.
apps/web/src/components/databases/CreateDatabaseDialog.tsx(lines 32-34) repeats these same defaults in a nested ternary. Two sources of truth will drift. Derive the version from this catalog in the dialog.♻️ Proposed change in `apps/web/src/components/databases/CreateDatabaseDialog.tsx`
- useEffect(() => { - setVersion(type === "postgresql" ? "16" : type === "mysql" ? "8.4" : type === "redis" ? "7.4" : type === "mongodb" ? "7.0" : "11.4"); - }, [type]); + useEffect(() => { + const engine = DATABASE_ENGINES.find((item) => item.type === type); + if (engine) setVersion(engine.defaultVersion); + }, [type]);🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/web/src/components/ui/DatabaseSelect.tsx` around lines 14 - 45, Update CreateDatabaseDialog’s default-version selection to derive the matching defaultVersion from the DATABASE_ENGINES catalog instead of using the duplicated nested ternary. Reuse the database type selected by the dialog and preserve the existing behavior for supported engines.apps/web/src/types/index.ts (1)
30-31: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueAlign optionality with the sibling command fields.
buildCommandandstartCommandare declared as required and nullable. MarkinginstallCommandandoutputDiroptional makes consumers handleundefinedas well asnull. If the API always returns these fields, drop the?.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/web/src/types/index.ts` around lines 30 - 31, Update the type declaration containing installCommand and outputDir to remove the optional ? markers, matching the required-but-nullable declarations of the sibling buildCommand and startCommand fields; keep their string | null value types unchanged.apps/web/src/routes/CreateProjectPage.tsx (2)
167-170: 🩺 Stability & Availability | 🔵 Trivial | 💤 Low valueThe navigation timer is not cleared.
setTimeoutis not stored, so it cannot be cleared if the user leaves the page during the one-second delay. Store the id and clear it in an effect cleanup.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/web/src/routes/CreateProjectPage.tsx` around lines 167 - 170, Update the project-creation navigation flow around setSubmittingStatus and navigate to store the setTimeout handle, then add effect cleanup that clears the handle when the component unmounts or the pending timer is replaced. Preserve the existing one-second delay and navigation target.
20-46: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueRemove the decorative section comments.
The coding guidelines forbid comments in source unless absolutely necessary. The state groups and JSX blocks here use purely decorative labels (for example lines 20, 30, 35, 46, 69, 72, and the JSX comments at lines 179-272). The variable names already convey the grouping.
As per coding guidelines: "No comments in source code unless absolutely necessary".
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/web/src/routes/CreateProjectPage.tsx` around lines 20 - 46, Remove the decorative section comments throughout CreateProjectPage, including the state-group labels and JSX block comments around the source, form, build/runtime, and Docker Compose sections. Leave all state declarations and JSX behavior unchanged.Source: Coding guidelines
apps/web/src/components/project/create/ProjectNameSection.tsx (1)
40-54: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueUse a non-label element for the static scope block, and drop the decorative comments.
Line 42 renders a
labelelement, but no form control is associated with it. Use aspanorpinstead. The JSX comments at lines 40, 56, 71, and 85 restate the markup below them.As per coding guidelines: "No comments in source code unless absolutely necessary".
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/web/src/components/project/create/ProjectNameSection.tsx` around lines 40 - 54, In ProjectNameSection, replace the static scope block’s label element with a non-label element such as span or p, since it is not associated with a form control. Remove the decorative JSX comments identifying the scope, project name, description, and related sections, while leaving the rendered content unchanged.Source: Coding guidelines
apps/web/src/components/project/create/BuildSettingsSection.tsx (2)
68-107: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAssociate the labels with the inputs, and remove the conflicting
blockclass.None of the
labelelements usehtmlFor, and noInputhas anid. Screen readers cannot announce the field names. The class lists also combineblockandflex; only one display utility applies.♻️ Proposed fix for the build command field
- <label className="block text-xs font-semibold text-zinc-300 flex items-center gap-1.5"> + <label htmlFor="build-command-input" className="text-xs font-semibold text-zinc-300 flex items-center gap-1.5"> <Terminal className="h-3.5 w-3.5 text-orange-400" /> Build Command </label> <Input + id="build-command-input" value={buildCommand}🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/web/src/components/project/create/BuildSettingsSection.tsx` around lines 68 - 107, Update the Build Command, Output Directory, and Install Command fields so each label’s htmlFor matches a unique id on its corresponding Input, enabling accessible label association. Remove the conflicting block utility from each label while preserving the existing flex alignment classes.
65-151: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winRemove the unused
BuildSettingsSection.
BuildSettingsSectionhas no consumers outside its own file, whileBuildStrategySectionalready renders the same build command, install command, output directory, port, and root directory inputs. Remove this duplicate component to keep the create project flow maintainable.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/web/src/components/project/create/BuildSettingsSection.tsx` around lines 65 - 151, Remove the unused BuildSettingsSection component and its associated state, imports, and rendering from the create project flow. Keep BuildStrategySection as the sole owner of the overlapping build, install, output directory, port, and root directory inputs.apps/web/src/components/project/settings/ProjectSettingsTab.tsx (2)
369-369: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winRemove the new JSX section comments.
The visible labels already identify these sections, so the comments at Lines [369], [403], and [420] are not necessary.
As per coding guidelines,
**/*.{ts,tsx,js,jsx}files must have no comments unless absolutely necessary.Also applies to: 403-403, 420-420
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/web/src/components/project/settings/ProjectSettingsTab.tsx` at line 369, Remove the JSX section comments around the Install Command Override and the corresponding sections near the visible labels in ProjectSettingsTab, including all three referenced comment markers. Leave the surrounding JSX and section labels unchanged.Source: Coding guidelines
45-46: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick winReplace the remaining
anyreads with directProjectproperty access.
installCommandandoutputDirare already onProject, so lines 45-46 can useproject.installCommandandproject.outputDir. Also replace the broaderbuildType,composeService,composePort, andcomposeServicesreads with properProjecttyping so future API contract changes fail at compile time.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/web/src/components/project/settings/ProjectSettingsTab.tsx` around lines 45 - 46, Replace the `any` casts in the project settings state initialization with direct typed access on `project`, including `installCommand`, `outputDir`, `buildType`, `composeService`, `composePort`, and `composeServices`. Ensure the `project` value is typed as `Project` so these properties are checked against the model and existing fallback behavior is preserved.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/web/src/api/client.ts`:
- Around line 575-576: Update setEnvVar to call createEnvVar with projectId and
a single data object containing key, value, and optional environment, matching
createEnvVar’s signature. Preserve the existing setEnvVar parameters and ensure
staged environment variable creation receives the object-shaped request body.
In `@apps/web/src/components/databases/CreateDatabaseDialog.tsx`:
- Around line 69-71: Update the “Attach to project” and “Database Engine”
controls in the CreateDatabaseDialog JSX to use stable unique identifiers and
associate each visible label with its corresponding custom select control via
htmlFor/appropriate control labeling. Ensure DatabaseSelect and the project
Select expose or consume the identifiers so both rendered controls are
accessible by their labels.
In `@apps/web/src/components/project/create/BuildSettingsSection.tsx`:
- Around line 40-63: Make both collapsible headers keyboard-operable by removing
the toggle onClick from the wrapper div and placing the existing isExpanded
toggle handler on each chevron button; add aria-expanded={isExpanded} to the
buttons in apps/web/src/components/project/create/BuildSettingsSection.tsx lines
40-63 and apps/web/src/components/project/create/EnvVarsSection.tsx lines
87-110.
In `@apps/web/src/components/project/create/BuildStrategySection.tsx`:
- Around line 141-183: Update the Web Service and Static Site buttons in the
project type selector so changing projectType also keeps selectedPresetId and
its command settings consistent. Either make the project type selection
authoritative by clearing/replacing the incompatible preset, or select the
established explicit custom preset when users change type manually; preserve
preset-driven behavior for compatible selections.
In `@apps/web/src/components/project/create/EnvVarsSection.tsx`:
- Around line 37-51: Update parseEnvContent to remove an optional leading
“export” prefix before extracting each key, and de-duplicate entries by key so
repeated variables produce only one staged environment entry. Preserve the
existing value trimming and quote removal behavior, with the final keys
containing only the variable name.
- Around line 61-83: Update handleFileUpload to clear the file input’s value
after capturing the selected file, ensuring selecting the same file again
triggers a change event while preserving the existing FileReader flow.
In `@apps/web/src/components/project/create/ProjectNameSection.tsx`:
- Around line 21-23: Extract the duplicated project-name normalization into a
shared slugifyProjectName helper, and use it in both ProjectNameSection and
CreateProjectPage. Ensure the helper lowercases names, replaces invalid
characters with hyphens, collapses consecutive hyphens, and trims leading or
trailing hyphens before constructing the domain preview.
In `@apps/web/src/components/project/create/SourceSelectionSection.tsx`:
- Around line 165-168: Update the submit handler in CreateProjectPage to reject
submission when sourceType is "upload" and zipFile is null, before creating the
project or calling uploadSourceZip. Also update the source-type change handling
in SourceSelectionSection to clear incompatible source state, including removing
zipFile when switching away from upload and clearing other source selections
when switching types.
In `@apps/web/src/components/project/create/StepBasics.tsx`:
- Around line 187-191: Update the StepBasics component’s FrameworkSelect
integration to persist the selected preset ID separately from projectType. Add
parent state and pass it through selectedPresetId, then have onSelectPreset
update both the preset ID and preset.projectType so selections such as Nuxt and
Astro remain selected after rerenders.
- Around line 182-194: Refactor StepBasics into focused child components before
adding more controls, moving the Application Framework Preset and related
general-settings UI and logic out of the 656-line component. Group the extracted
components in an appropriate feature folder, preserve the existing projectType
state and FrameworkSelect behavior, and keep StepBasics under 500 lines.
In `@apps/web/src/components/project/settings/ProjectSettingsTab.tsx`:
- Around line 159-194: Add aria-pressed to both project type buttons in the
projectType selector, binding it to whether projectType equals each button’s
value. Preserve the existing click handlers and styling while exposing the
active selection to assistive technology.
- Around line 154-197: Update the project type selector around the Web Service
and Static Site / SPA buttons to hide it when the selected build type is
Compose, and ensure the form’s save payload normalizes Compose projects to
projectType "web" even if the local projectType state is "static".
- Line 169: Replace every unsupported text-zinc-250 class in the
ProjectSettingsTab markup, including the elements near lines 169, 187, 214, and
232, with a supported zinc shade such as text-zinc-200; do not add a custom
Tailwind token.
In `@apps/web/src/components/ui/DatabaseSelect.tsx`:
- Line 141: Update the badge span’s invalid py-0.2 Tailwind class to a valid
spacing utility, preferably py-0.5, or use an equivalent arbitrary value such as
py-[0.2rem] or py-[2px] while preserving the intended padding.
In `@apps/web/src/routes/CreateProjectPage.tsx`:
- Around line 160-175: Update the submission flow around the stagedEnvs
setEnvVar loop so a failed environment-variable write does not leave an
unreported orphaned project. Track which variables were successfully stored and
include that information in the error handling, or delete the newly created
project when any setEnvVar call fails; preserve the existing success navigation
for fully successful submissions.
- Around line 326-334: Update the submission error handling in the function
containing handleSubmit so a failed deployment resets submittingStatus to
'idle', or adjust the launch Button disabled condition to permit retries when
the status is 'error'; preserve the disabled behavior while submitting and when
the project name is empty.
- Around line 115-130: Update handleSubmit to validate the selected source
before setting the submitting state: require a non-empty repoUrl when sourceType
is 'git', and require zipFile when sourceType is 'upload'. Set an appropriate
error message and return for invalid selections, while preserving the existing
name validation and upload flow.
- Around line 140-158: Replace the any annotation on projectPayload in the
CreateProjectPage submission flow with the shared CreateProjectInput type.
Update the createProject web client mutation/request signature to accept that
same API shape, including buildType, installCommand, outputDir, and
composeServices, so the payload is validated consistently and contract changes
are caught by TypeScript.
---
Nitpick comments:
In `@apps/web/src/components/project/create/BuildSettingsSection.tsx`:
- Around line 68-107: Update the Build Command, Output Directory, and Install
Command fields so each label’s htmlFor matches a unique id on its corresponding
Input, enabling accessible label association. Remove the conflicting block
utility from each label while preserving the existing flex alignment classes.
- Around line 65-151: Remove the unused BuildSettingsSection component and its
associated state, imports, and rendering from the create project flow. Keep
BuildStrategySection as the sole owner of the overlapping build, install, output
directory, port, and root directory inputs.
In `@apps/web/src/components/project/create/ProjectNameSection.tsx`:
- Around line 40-54: In ProjectNameSection, replace the static scope block’s
label element with a non-label element such as span or p, since it is not
associated with a form control. Remove the decorative JSX comments identifying
the scope, project name, description, and related sections, while leaving the
rendered content unchanged.
In `@apps/web/src/components/project/create/SourceSelectionSection.tsx`:
- Line 55: Remove the nonessential JSX section comments from
SourceSelectionSection.tsx at lines 55, 102, and 154;
ApplicationPresetSection.tsx at line 32; and BuildStrategySection.tsx at lines
76, 123, 126, 137, 187, and 266. Leave the surrounding JSX and behavior
unchanged.
In `@apps/web/src/components/project/settings/ProjectSettingsTab.tsx`:
- Line 369: Remove the JSX section comments around the Install Command Override
and the corresponding sections near the visible labels in ProjectSettingsTab,
including all three referenced comment markers. Leave the surrounding JSX and
section labels unchanged.
- Around line 45-46: Replace the `any` casts in the project settings state
initialization with direct typed access on `project`, including
`installCommand`, `outputDir`, `buildType`, `composeService`, `composePort`, and
`composeServices`. Ensure the `project` value is typed as `Project` so these
properties are checked against the model and existing fallback behavior is
preserved.
In `@apps/web/src/components/ui/DatabaseSelect.tsx`:
- Around line 60-98: Update the trigger button in DatabaseSelect to include
aria-expanded={isOpen} and aria-haspopup="listbox". Modify the outside-click
useEffect to register its listener only while isOpen, and add Escape-key
handling that calls setIsOpen(false) when the dropdown is open; ensure cleanup
removes any registered listeners.
- Around line 14-45: Update CreateDatabaseDialog’s default-version selection to
derive the matching defaultVersion from the DATABASE_ENGINES catalog instead of
using the duplicated nested ternary. Reuse the database type selected by the
dialog and preserve the existing behavior for supported engines.
In `@apps/web/src/routes/CreateProjectPage.tsx`:
- Around line 167-170: Update the project-creation navigation flow around
setSubmittingStatus and navigate to store the setTimeout handle, then add effect
cleanup that clears the handle when the component unmounts or the pending timer
is replaced. Preserve the existing one-second delay and navigation target.
- Around line 20-46: Remove the decorative section comments throughout
CreateProjectPage, including the state-group labels and JSX block comments
around the source, form, build/runtime, and Docker Compose sections. Leave all
state declarations and JSX behavior unchanged.
In `@apps/web/src/types/index.ts`:
- Around line 30-31: Update the type declaration containing installCommand and
outputDir to remove the optional ? markers, matching the required-but-nullable
declarations of the sibling buildCommand and startCommand fields; keep their
string | null value types unchanged.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: df1fc480-d8f9-46bf-8515-089b6e464f90
📒 Files selected for processing (19)
apps/web/src/api/client.tsapps/web/src/components/databases/CreateDatabaseDialog.tsxapps/web/src/components/logos/DatabaseLogos.tsxapps/web/src/components/logos/FrameworkLogos.tsxapps/web/src/components/project/create/ApplicationPresetSection.tsxapps/web/src/components/project/create/BuildSettingsSection.tsxapps/web/src/components/project/create/BuildStrategySection.tsxapps/web/src/components/project/create/EnvVarsSection.tsxapps/web/src/components/project/create/ImportHeaderCard.tsxapps/web/src/components/project/create/ProjectNameSection.tsxapps/web/src/components/project/create/SourceSelectionSection.tsxapps/web/src/components/project/create/StepBasics.tsxapps/web/src/components/project/deployments/deployment-logs.tsxapps/web/src/components/project/settings/ProjectSettingsTab.tsxapps/web/src/components/ui/DatabaseSelect.tsxapps/web/src/components/ui/FrameworkSelect.tsxapps/web/src/routes/CreateProjectPage.tsxapps/web/src/types/index.tsapps/web/src/utils/presets.ts
| <div | ||
| className="flex items-center justify-between cursor-pointer select-none" | ||
| onClick={() => setIsExpanded(!isExpanded)} | ||
| > | ||
| <div> | ||
| <h3 className="text-sm font-bold text-zinc-100 flex items-center gap-2"> | ||
| <Terminal className="h-4 w-4 text-orange-500" /> | ||
| Build & Output Settings | ||
| </h3> | ||
| <p className="text-xs text-zinc-400 mt-1"> | ||
| Pre-configured from preset. Expand to inspect or override build commands. | ||
| </p> | ||
| </div> | ||
| <button | ||
| type="button" | ||
| className="p-1.5 rounded-lg bg-[#14141a] border border-[#22222c] text-zinc-400 hover:text-white" | ||
| > | ||
| <ChevronDown | ||
| className={`h-4 w-4 transition-transform ${ | ||
| isExpanded ? 'transform rotate-180 text-orange-400' : '' | ||
| }`} | ||
| /> | ||
| </button> | ||
| </div> |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win
Collapsible section headers are not keyboard operable. Both sections place the toggle onClick on a non-focusable div and render an inner button with no handler. Keyboard and screen-reader users cannot expand or collapse either panel.
apps/web/src/components/project/create/BuildSettingsSection.tsx#L40-L63: moveonClick={() => setIsExpanded(!isExpanded)}from the wrapperdivto the chevronbuttonand addaria-expanded={isExpanded}.apps/web/src/components/project/create/EnvVarsSection.tsx#L87-L110: apply the same change to the chevronbuttonin this header.
📍 Affects 2 files
apps/web/src/components/project/create/BuildSettingsSection.tsx#L40-L63(this comment)apps/web/src/components/project/create/EnvVarsSection.tsx#L87-L110
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@apps/web/src/components/project/create/BuildSettingsSection.tsx` around lines
40 - 63, Make both collapsible headers keyboard-operable by removing the toggle
onClick from the wrapper div and placing the existing isExpanded toggle handler
on each chevron button; add aria-expanded={isExpanded} to the buttons in
apps/web/src/components/project/create/BuildSettingsSection.tsx lines 40-63 and
apps/web/src/components/project/create/EnvVarsSection.tsx lines 87-110.
| <button | ||
| type="button" | ||
| onClick={() => setProjectType('web')} | ||
| className={cn( | ||
| 'p-4 rounded-xl border text-left transition-all space-y-1.5', | ||
| projectType === 'web' | ||
| ? 'bg-orange-500/10 border-orange-500/40 text-orange-400' | ||
| : 'bg-[#121215] border-[#22222a] text-zinc-400 hover:border-zinc-700' | ||
| )} | ||
| > | ||
| <div className="flex items-center justify-between"> | ||
| <Globe className="h-5 w-5 text-orange-500" /> | ||
| <span className="text-[10px] font-bold uppercase tracking-wider px-2 py-0.5 rounded bg-orange-500/20 text-orange-300"> | ||
| Dynamic Server | ||
| </span> | ||
| </div> | ||
| <div className="font-bold text-xs text-zinc-100">Web Service</div> | ||
| <p className="text-[11px] text-zinc-400"> | ||
| Node.js, Elysia, Express, Next.js (SSR), Go, Python server container. | ||
| </p> | ||
| </button> | ||
|
|
||
| <button | ||
| type="button" | ||
| onClick={() => setProjectType('static')} | ||
| className={cn( | ||
| 'p-4 rounded-xl border text-left transition-all space-y-1.5', | ||
| projectType === 'static' | ||
| ? 'bg-emerald-500/10 border-emerald-500/40 text-emerald-400' | ||
| : 'bg-[#121215] border-[#22222a] text-zinc-400 hover:border-zinc-700' | ||
| )} | ||
| > | ||
| <div className="flex items-center justify-between"> | ||
| <FolderCode className="h-5 w-5 text-emerald-500" /> | ||
| <span className="text-[10px] font-bold uppercase tracking-wider px-2 py-0.5 rounded bg-emerald-500/20 text-emerald-300"> | ||
| Static Site | ||
| </span> | ||
| </div> | ||
| <div className="font-bold text-xs text-zinc-100">Static Site / SPA</div> | ||
| <p className="text-[11px] text-zinc-400"> | ||
| React, Vite, Astro, Vue static export served via lightweight HTTP file server. | ||
| </p> | ||
| </button> |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Keep preset state and project type consistent.
These buttons update only projectType. They do not clear or replace selectedPresetId or its commands.
If a user selects a static preset and then selects Web Service, the selector can still show the static preset while submission uses projectType: "web" and its static command settings.
Make preset selection authoritative, or select an explicit custom preset when the user changes project type manually.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@apps/web/src/components/project/create/BuildStrategySection.tsx` around lines
141 - 183, Update the Web Service and Static Site buttons in the project type
selector so changing projectType also keeps selectedPresetId and its command
settings consistent. Either make the project type selection authoritative by
clearing/replacing the incompatible preset, or select the established explicit
custom preset when users change type manually; preserve preset-driven behavior
for compatible selections.
| const parseEnvContent = (content: string) => { | ||
| const lines = content.split(/\r?\n/); | ||
| const newEnvs: StagedEnv[] = []; | ||
| lines.forEach((line) => { | ||
| const trimmed = line.trim(); | ||
| if (!trimmed || trimmed.startsWith('#')) return; | ||
| const eqIdx = trimmed.indexOf('='); | ||
| if (eqIdx !== -1) { | ||
| const k = trimmed.slice(0, eqIdx).trim(); | ||
| const v = trimmed.slice(eqIdx + 1).trim().replace(/^["']|["']$/g, ''); | ||
| if (k) newEnvs.push({ key: k, value: v }); | ||
| } | ||
| }); | ||
| return newEnvs; | ||
| }; |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Strip the export prefix and de-duplicate keys.
A .env file commonly contains export KEY=VALUE. The parser produces the key export KEY, which is not a valid variable name. Repeated keys are also appended twice; CreateProjectPage.tsx then posts both, and the second request can fail on a server-side uniqueness constraint.
🐛 Proposed fix
const parseEnvContent = (content: string) => {
const lines = content.split(/\r?\n/);
const newEnvs: StagedEnv[] = [];
+ const seen = new Set<string>();
lines.forEach((line) => {
- const trimmed = line.trim();
+ const trimmed = line.trim().replace(/^export\s+/, '');
if (!trimmed || trimmed.startsWith('#')) return;
const eqIdx = trimmed.indexOf('=');
if (eqIdx !== -1) {
const k = trimmed.slice(0, eqIdx).trim();
const v = trimmed.slice(eqIdx + 1).trim().replace(/^["']|["']$/g, '');
- if (k) newEnvs.push({ key: k, value: v });
+ if (k && !seen.has(k)) {
+ seen.add(k);
+ newEnvs.push({ key: k, value: v });
+ }
}
});
return newEnvs;
};📝 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 parseEnvContent = (content: string) => { | |
| const lines = content.split(/\r?\n/); | |
| const newEnvs: StagedEnv[] = []; | |
| lines.forEach((line) => { | |
| const trimmed = line.trim(); | |
| if (!trimmed || trimmed.startsWith('#')) return; | |
| const eqIdx = trimmed.indexOf('='); | |
| if (eqIdx !== -1) { | |
| const k = trimmed.slice(0, eqIdx).trim(); | |
| const v = trimmed.slice(eqIdx + 1).trim().replace(/^["']|["']$/g, ''); | |
| if (k) newEnvs.push({ key: k, value: v }); | |
| } | |
| }); | |
| return newEnvs; | |
| }; | |
| const parseEnvContent = (content: string) => { | |
| const lines = content.split(/\r?\n/); | |
| const newEnvs: StagedEnv[] = []; | |
| const seen = new Set<string>(); | |
| lines.forEach((line) => { | |
| const trimmed = line.trim().replace(/^export\s+/, ''); | |
| if (!trimmed || trimmed.startsWith('#')) return; | |
| const eqIdx = trimmed.indexOf('='); | |
| if (eqIdx !== -1) { | |
| const k = trimmed.slice(0, eqIdx).trim(); | |
| const v = trimmed.slice(eqIdx + 1).trim().replace(/^["']|["']$/g, ''); | |
| if (k && !seen.has(k)) { | |
| seen.add(k); | |
| newEnvs.push({ key: k, value: v }); | |
| } | |
| } | |
| }); | |
| return newEnvs; | |
| }; |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@apps/web/src/components/project/create/EnvVarsSection.tsx` around lines 37 -
51, Update parseEnvContent to remove an optional leading “export” prefix before
extracting each key, and de-duplicate entries by key so repeated variables
produce only one staged environment entry. Preserve the existing value trimming
and quote removal behavior, with the final keys containing only the variable
name.
and configuration - Replace `Staticfile` with `dequel-serve.js` for all static site deployments - Automatically generate a root `package.json` for static apps to standardize runtime configuration - Remove build-time environment variable filtering to allow full access to deployment environment variables - Update framework presets with correct default ports - Remove unused `env-filter` utility and tests
components - Refactor `StepBasics` to use `StepBasicsGeneralSettings` and `StepBasicsSourceSection` for better organization. - Remove redundant preset and build settings components. - Add `slugifyProjectName` helper. - Update `CreateProjectInput` type definitions.
There was a problem hiding this comment.
Actionable comments posted: 9
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
apps/api/src/orchestrator/railpack-config-utils.ts (1)
562-572: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick winDo not serve source dotfiles.
The handler returns every existing path below
staticDir. WhenstaticDiris the source directory, a request for/.envcan expose deployment secrets included in the uploaded source. Reject dotfile path segments and verify that the resolved request path remains inside the resolved static root before callingBun.file.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/api/src/orchestrator/railpack-config-utils.ts` around lines 562 - 572, Update the static-file handler around filePath and Bun.file to reject any decodedPathname segment beginning with "." before accessing the filesystem, and resolve both the requested path and staticDir to verify the request remains within the resolved static root. Only call Bun.file after these checks, preserving normal index.html handling for allowed paths.
♻️ Duplicate comments (1)
apps/web/src/routes/CreateProjectPage.tsx (1)
348-356: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winThe launch button shows "Deploying..." after a failure.
submittingStatusis'error'after a failed submission, so the label stays "Deploying..." and the button stays disabled. The user must find the retry control inCreationStatusOverlayto reset the state. Treat'error'as an idle-equivalent state for the button.🐛 Proposed fix
- disabled={!name.trim() || submittingStatus !== 'idle'} + disabled={!name.trim() || (submittingStatus !== 'idle' && submittingStatus !== 'error')} className="w-full bg-gradient-to-r from-orange-600 to-amber-500 hover:from-orange-500 hover:to-amber-400 text-white font-bold h-11 text-xs rounded-xl shadow-lg shadow-orange-500/20 flex items-center justify-center gap-2 mt-4" > <Rocket className="h-4 w-4" /> - {submittingStatus === 'idle' ? 'Launch Deployment' : 'Deploying...'} + {submittingStatus === 'idle' || submittingStatus === 'error' ? 'Launch Deployment' : 'Deploying...'}🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/web/src/routes/CreateProjectPage.tsx` around lines 348 - 356, Update the launch Button rendering and disabled logic in CreateProjectPage so submittingStatus === 'error' is treated like 'idle': re-enable the button when the name is valid and display “Launch Deployment,” allowing users to retry directly after a failed submission.
🧹 Nitpick comments (5)
apps/web/src/components/project/create/StepBasicsSourceSection.tsx (2)
346-365: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueThe
"image"branch is unreachable.
sourceOptionsat lines 9-28 defines only"git","upload", and"compose". No control setssourceTypeto"image", so this block never renders. Remove it, or add the corresponding source option if container-image deployment is intended.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/web/src/components/project/create/StepBasicsSourceSection.tsx` around lines 346 - 365, Remove the unreachable sourceType === "image" rendering branch from the source selection UI, since sourceOptions only supports "git", "upload", and "compose" and no control can select "image".
43-45: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winTwo props represent one GitHub connection state.
StepBasicsSourceSectiondeclaresgithubConnected: booleanandonGithubConnected: () => boolean, reads only the callback, and the parent supplies both.
apps/web/src/components/project/create/StepBasicsSourceSection.tsx#L43-L45: delete theonGithubConnectedprop, and setconst connected = githubConnected;at line 66.apps/web/src/components/project/create/StepBasics.tsx#L94-L95: pass onlygithubConnected={onGithubConnected()}and remove theonGithubConnectedprop.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/web/src/components/project/create/StepBasicsSourceSection.tsx` around lines 43 - 45, Remove the redundant onGithubConnected prop from StepBasicsSourceSection and set connected directly from githubConnected. In apps/web/src/components/project/create/StepBasicsSourceSection.tsx lines 43-45, delete the callback prop and update the connected initialization near line 66; in apps/web/src/components/project/create/StepBasics.tsx lines 94-95, pass only githubConnected={onGithubConnected()} and remove the callback prop.apps/web/src/components/project/create/StepBasicsGeneralSettings.tsx (1)
33-40: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win
handleTypeChangehas two identical branches.Both paths call
setProjectType(type). TheFRAMEWORK_PRESETSlookup has no effect, and theFRAMEWORK_PRESETSimport exists only for it. If the intent is to clear a preset that conflicts with the manually selected type, the component needs a preset-reset callback. Otherwise, reduce the handler to the setter.♻️ Proposed simplification
- const handleTypeChange = (type: string) => { - const preset = FRAMEWORK_PRESETS.find((p) => p.id === selectedPresetId); - if (preset && preset.projectType === type) { - setProjectType(type); - return; - } - setProjectType(type); - }; -Then call
setProjectTypedirectly at lines 102 and 120, and drop theFRAMEWORK_PRESETSimport.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/web/src/components/project/create/StepBasicsGeneralSettings.tsx` around lines 33 - 40, Remove the redundant FRAMEWORK_PRESETS lookup and conditional from handleTypeChange, reducing it to directly call setProjectType(type). Update the callers around the existing handler usage to invoke setProjectType directly, then remove the now-unused FRAMEWORK_PRESETS import.apps/web/src/components/project/create/CreateProjectDialog.tsx (1)
66-67: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy liftThis file exceeds the 500-line limit.
CreateProjectDialog.tsxis 568 lines and this change adds more state and props. Split the step rendering and the submit flow into separate files under acreate/feature folder.As per coding guidelines, "No file should be above 500 lines of code; if it is, refactor and split into smaller files with proper feature grouping in a folder rather than scattered across the codebase".
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/web/src/components/project/create/CreateProjectDialog.tsx` around lines 66 - 67, Refactor CreateProjectDialog by moving its step-rendering logic and submit flow into focused modules under the create/ feature folder, keeping CreateProjectDialog responsible for orchestration and shared state. Preserve the existing behavior and props while reducing the file below 500 lines, and keep the extracted files grouped with the create feature.Source: Coding guidelines
apps/web/src/components/project/create/ProjectNameSection.tsx (1)
18-18: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueSimplify the props type instead of using
Omit.
ProjectNameSectionPropsstill declaresbaseDomainandsetBaseDomain, but no consumer passes them.CreateProjectPage.tsxline 253 passes onlyname,setName,description, andsetDescription. Remove the unused fields from the interface and use the interface directly.♻️ Proposed refactor
-}: Omit<ProjectNameSectionProps, 'baseDomain' | 'setBaseDomain'>) { +}: ProjectNameSectionProps) {Update the interface declaration accordingly to drop
baseDomainandsetBaseDomain.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/web/src/components/project/create/ProjectNameSection.tsx` at line 18, Update ProjectNameSectionProps to remove the unused baseDomain and setBaseDomain fields, then replace the Omit<ProjectNameSectionProps, 'baseDomain' | 'setBaseDomain'> parameter type in ProjectNameSection with ProjectNameSectionProps directly.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/api/src/orchestrator/pipeline.ts`:
- Line 446: Update the build-variable loading near environmentVariables to use
the same deployment.environment selection as the runtime variables instead of
always using "production". Ensure non-production deployments receive matching
build-time URLs and credentials.
In `@apps/api/src/orchestrator/railpack-config-utils.ts`:
- Around line 609-631: The files exceed the repository’s 500-line limit and need
feature-based extraction. In apps/api/src/orchestrator/railpack-config-utils.ts
lines 609-631, extract static-server configuration and command-override
generation into dedicated feature-specific modules, preserving the existing
behavior around install, build, and start overrides. In
apps/api/src/orchestrator/pipeline.ts lines 446-449, extract build preparation
and deployment execution responsibilities into appropriate feature-specific
modules; update imports and callers so both original flows remain unchanged.
- Line 519: Update the conditional in the railpack configuration flow so an
explicit projectType of "static" selects bun dequel-serve.js even when
configured is already true from Node detection. Keep the existing detected
build-step behavior unchanged, and retain the index.html checks for non-explicit
project types.
- Line 223: Update the build command in the source-directory branch of the
railpack configuration utility to quote cleanSourceDir and chain the directory
change and package-manager build with &&, ensuring the build only runs after
entering the intended source directory and supports paths containing spaces.
In `@apps/web/src/api/client.ts`:
- Around line 562-563: Resolve the missing upload route by either implementing
and registering the /upload server endpoint expected by uploadSourceZip, or
removing uploadSourceZip and its callers in favor of the supported flow. Ensure
the selected path allows project creation to complete without invoking an
unregistered endpoint.
In `@apps/web/src/components/project/create/CreateProjectDialog.tsx`:
- Around line 122-127: Update handleSelectPreset in CreateProjectDialog to apply
the preset’s build configuration fields—buildCommand, installCommand,
startCommand, outputDir, and defaultPort—in addition to selectedPresetId and
projectType, matching CreateProjectPage behavior.
In `@apps/web/src/components/project/deployments/DeploymentsTab.tsx`:
- Around line 57-58: Split DeploymentsTab.tsx into feature-focused files within
a dedicated deployment feature folder, moving the deployment source form,
webhook logic, and deployment history orchestration into appropriate components
or hooks. Keep DeploymentsTab as the coordinating container and reduce it below
the 500-line limit without scattering related code across the codebase.
In `@apps/web/src/routes/CreateProjectPage.tsx`:
- Around line 361-368: Update the CreateProjectPage rendering around
CreationStatusOverlay so the status panel is visible during submission by
placing it in a fixed-position container or scrolling it into view whenever
submittingStatus is not idle. Remove the obsolete hasDb and dbType props from
this usage and from CreationStatusOverlay’s parameter handling if they are no
longer used elsewhere.
- Around line 184-191: Update the environment-variable error handling in the
submission loop around the envErr catch to retain the variable currently being
processed and use its key in setErrorMessage. Remove the stagedEnvs.find
fallback so failures report the actual variable that caused the error, while
preserving the existing cleanup and error-status behavior.
---
Outside diff comments:
In `@apps/api/src/orchestrator/railpack-config-utils.ts`:
- Around line 562-572: Update the static-file handler around filePath and
Bun.file to reject any decodedPathname segment beginning with "." before
accessing the filesystem, and resolve both the requested path and staticDir to
verify the request remains within the resolved static root. Only call Bun.file
after these checks, preserving normal index.html handling for allowed paths.
---
Duplicate comments:
In `@apps/web/src/routes/CreateProjectPage.tsx`:
- Around line 348-356: Update the launch Button rendering and disabled logic in
CreateProjectPage so submittingStatus === 'error' is treated like 'idle':
re-enable the button when the name is valid and display “Launch Deployment,”
allowing users to retry directly after a failed submission.
---
Nitpick comments:
In `@apps/web/src/components/project/create/CreateProjectDialog.tsx`:
- Around line 66-67: Refactor CreateProjectDialog by moving its step-rendering
logic and submit flow into focused modules under the create/ feature folder,
keeping CreateProjectDialog responsible for orchestration and shared state.
Preserve the existing behavior and props while reducing the file below 500
lines, and keep the extracted files grouped with the create feature.
In `@apps/web/src/components/project/create/ProjectNameSection.tsx`:
- Line 18: Update ProjectNameSectionProps to remove the unused baseDomain and
setBaseDomain fields, then replace the Omit<ProjectNameSectionProps,
'baseDomain' | 'setBaseDomain'> parameter type in ProjectNameSection with
ProjectNameSectionProps directly.
In `@apps/web/src/components/project/create/StepBasicsGeneralSettings.tsx`:
- Around line 33-40: Remove the redundant FRAMEWORK_PRESETS lookup and
conditional from handleTypeChange, reducing it to directly call
setProjectType(type). Update the callers around the existing handler usage to
invoke setProjectType directly, then remove the now-unused FRAMEWORK_PRESETS
import.
In `@apps/web/src/components/project/create/StepBasicsSourceSection.tsx`:
- Around line 346-365: Remove the unreachable sourceType === "image" rendering
branch from the source selection UI, since sourceOptions only supports "git",
"upload", and "compose" and no control can select "image".
- Around line 43-45: Remove the redundant onGithubConnected prop from
StepBasicsSourceSection and set connected directly from githubConnected. In
apps/web/src/components/project/create/StepBasicsSourceSection.tsx lines 43-45,
delete the callback prop and update the connected initialization near line 66;
in apps/web/src/components/project/create/StepBasics.tsx lines 94-95, pass only
githubConnected={onGithubConnected()} and remove the callback prop.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: e568053b-0a1e-46fa-acf1-cf003e23deb5
📒 Files selected for processing (21)
apps/api/src/orchestrator/__tests__/railpack-config.test.tsapps/api/src/orchestrator/pipeline.tsapps/api/src/orchestrator/railpack-config-utils.tsapps/api/src/utils/__tests__/env-filter.test.tsapps/api/src/utils/env-filter.tsapps/web/src/api/client.tsapps/web/src/components/databases/CreateDatabaseDialog.tsxapps/web/src/components/project/create/CreateProjectDialog.tsxapps/web/src/components/project/create/ProjectNameSection.tsxapps/web/src/components/project/create/SourceSelectionSection.tsxapps/web/src/components/project/create/StepBasics.tsxapps/web/src/components/project/create/StepBasicsGeneralSettings.tsxapps/web/src/components/project/create/StepBasicsSourceSection.tsxapps/web/src/components/project/deployments/DeploymentsTab.tsxapps/web/src/components/project/settings/ProjectSettingsTab.tsxapps/web/src/components/ui/DatabaseSelect.tsxapps/web/src/routes/CreateProjectPage.tsxapps/web/src/types/index.tsapps/web/src/utils/presets.tsapps/web/src/utils/slugify.tsdocker-compose.yml
💤 Files with no reviewable changes (2)
- apps/api/src/utils/tests/env-filter.test.ts
- apps/api/src/utils/env-filter.ts
🚧 Files skipped from review as they are similar to previous changes (5)
- apps/web/src/types/index.ts
- apps/web/src/components/ui/DatabaseSelect.tsx
- apps/web/src/utils/presets.ts
- apps/web/src/components/databases/CreateDatabaseDialog.tsx
- apps/web/src/components/project/settings/ProjectSettingsTab.tsx
| if (buildCommandOverride || startCommandOverride || installCommandOverride) { | ||
| await onLog("Applying custom build/start/install settings"); | ||
| if (installCommandOverride) { | ||
| const hasCustomInstall = installCommandOverride !== "npm install" && installCommandOverride !== "npm ci" && installCommandOverride !== "pnpm install" && installCommandOverride !== "yarn install" && installCommandOverride !== "bun install"; | ||
| if (hasCustomInstall) { | ||
| config.steps.install = config.steps.install || {}; | ||
| config.steps.install.commands = [installCommandOverride]; | ||
| } | ||
| } | ||
| if (buildCommandOverride) { | ||
| config.steps.build = config.steps.build || {}; | ||
| config.steps.build.commands = [ | ||
| cleanSourceDir | ||
| ? `cd ${cleanSourceDir} && ${buildCommandOverride}` | ||
| : buildCommandOverride, | ||
| ]; | ||
| } | ||
| if (startCommandOverride) { | ||
| config.deploy.startCommand = cleanSourceDir | ||
| ? `cd ${cleanSourceDir} && ${startCommandOverride}` | ||
| : startCommandOverride; | ||
| } | ||
| } |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy lift
Split the TypeScript files that exceed the repository size limit.
apps/api/src/orchestrator/railpack-config-utils.ts#L609-L631: extract static-server configuration and command-override generation into feature-specific modules.apps/api/src/orchestrator/pipeline.ts#L446-L449: extract build preparation and deployment execution responsibilities into feature-specific modules.
As per coding guidelines, “No file should be above 500 lines of code; if it is, refactor and split into smaller files with proper feature grouping in a folder rather than scattered across the codebase”.
📍 Affects 2 files
apps/api/src/orchestrator/railpack-config-utils.ts#L609-L631(this comment)apps/api/src/orchestrator/pipeline.ts#L446-L449
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@apps/api/src/orchestrator/railpack-config-utils.ts` around lines 609 - 631,
The files exceed the repository’s 500-line limit and need feature-based
extraction. In apps/api/src/orchestrator/railpack-config-utils.ts lines 609-631,
extract static-server configuration and command-override generation into
dedicated feature-specific modules, preserving the existing behavior around
install, build, and start overrides. In apps/api/src/orchestrator/pipeline.ts
lines 446-449, extract build preparation and deployment execution
responsibilities into appropriate feature-specific modules; update imports and
callers so both original flows remain unchanged.
Source: Coding guidelines
| export const setEnvVar = (projectId: string, key: string, value: string, environment?: string) => | ||
| createEnvVar(projectId, { key, value, environment }); |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Description: Locate the uploadSourceZip client helper and the matching API route.
set -euo pipefail
echo "## Client helper"
rg -n -C6 'uploadSourceZip' apps/web/src
echo "## API upload routes"
rg -n -C6 -g '!apps/web/**' '"/upload"|/upload\b|filePath' apps/api/src | head -80Repository: Lftobs/dequel
Length of output: 7622
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "## Upload-related files and symbols"
git ls-files | grep -Ei '(^|/)(route|router|upload|server|api|index|app)[^/]*\.(ts|tsx|js|jsx)$' | head -200
rg -n -i -C5 'uploadSourceZip|upload|multipart|FormData|filePath|formData|request\.formData|req\.file|file\.path|repoUrl' --glob '*.{ts,tsx,js,jsx}' . | head -300
echo "## API source outline"
if command -v ast-grep >/dev/null 2>&1; then
ast-grep outline apps/api/src
fiRepository: Lftobs/dequel
Length of output: 30738
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "## API route registration"
wc -l apps/api/src/index.ts apps/api/src/api/index.ts apps/api/src/orchestrator/source.ts
cat -n apps/api/src/index.ts
cat -n apps/api/src/api/index.ts
sed -n '1,130p' apps/api/src/orchestrator/source.ts
echo "## Deterministic endpoint scan"
python3 - <<'PY'
from pathlib import Path
import re
files = [Path(p) for p in __import__("subprocess").check_output(
["git", "ls-files", "*.ts", "*.tsx", "*.js", "*.jsx"], text=True
).splitlines()]
route_hits = []
upload_hits = []
file_path_hits = []
for path in files:
text = path.read_text(errors="replace")
if re.search(r'(?i)(?:["\'`]\/upload\b|(?:get|post|put|patch|delete)\s*\(\s*["\'`]\/upload\b|route\s*=\s*["\'`]\/upload\b)', text):
route_hits.append(str(path))
if re.search(r'(?i)(?:upload|multipart|formdata|request\.formdata|req\.file)', text):
upload_hits.append(str(path))
if re.search(r'\bfilePath\b', text):
file_path_hits.append(str(path))
print("route_matches:", route_hits)
print("upload_related_files:", upload_hits)
print("filePath_files:", file_path_hits)
PYRepository: Lftobs/dequel
Length of output: 11590
Add the /upload server endpoint or remove uploadSourceZip.
The API registers no upload route. The upload flow therefore fails before project creation.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@apps/web/src/api/client.ts` around lines 562 - 563, Resolve the missing
upload route by either implementing and registering the /upload server endpoint
expected by uploadSourceZip, or removing uploadSourceZip and its callers in
favor of the supported flow. Ensure the selected path allows project creation to
complete without invoking an unregistered endpoint.
| const [clearCache, setClearCache] = | ||
| useState(false); |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy lift
Split DeploymentsTab.tsx before merging.
The file reaches Line 527. Move the deployment source form, webhook logic, and deployment history orchestration into feature-focused components or hooks. Keep DeploymentsTab.tsx below the 500-line limit.
As per coding guidelines, no file should be above 500 lines of code; refactor and split it into smaller files with proper feature grouping in a folder rather than scattering code across the codebase.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@apps/web/src/components/project/deployments/DeploymentsTab.tsx` around lines
57 - 58, Split DeploymentsTab.tsx into feature-focused files within a dedicated
deployment feature folder, moving the deployment source form, webhook logic, and
deployment history orchestration into appropriate components or hooks. Keep
DeploymentsTab as the coordinating container and reduce it below the 500-line
limit without scattering related code across the codebase.
Source: Coding guidelines
| <CreationStatusOverlay | ||
| submittingStatus={submittingStatus} | ||
| errorMessage={errorMessage} | ||
| hasEnvs={stagedEnvs.length > 0} | ||
| hasDb={false} | ||
| dbType="postgresql" | ||
| onRetry={handleRetry} | ||
| /> |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
CreationStatusOverlay renders below the form, not over it.
The component returns a plain flow-layout block with no fixed or absolute positioning. During submission the form stays visible above it, and the status panel appears at the bottom of the page. The user may not see the progress or the retry control without scrolling. Wrap the component in a fixed-position container, or scroll it into view when submittingStatus leaves 'idle'.
Also, hasDb={false} and dbType="postgresql" are constants. Database provisioning no longer exists in this flow, so these props are dead parameters.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@apps/web/src/routes/CreateProjectPage.tsx` around lines 361 - 368, Update the
CreateProjectPage rendering around CreationStatusOverlay so the status panel is
visible during submission by placing it in a fixed-position container or
scrolling it into view whenever submittingStatus is not idle. Remove the
obsolete hasDb and dbType props from this usage and from CreationStatusOverlay’s
parameter handling if they are no longer used elsewhere.
deployment refinements - Allow custom build, install, and start commands in project creation - Enable environment-aware variable fetching for deployments - Improve directory handling in build scripts - Add retry logic and improved error tracking for project creation - Remove redundant database provisioning UI components
There was a problem hiding this comment.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
apps/web/src/components/project/create/CreateProjectDialog.tsx (2)
130-141: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winClear stale port state when a preset has no default port.
FrameworkPreset.defaultPortis optional, and thedockerandotherpresets omit it. Line 139 then leaves the previous preset's port in state. Selecting a custom preset after Vite can submit the old Vite port. UsesetPort(preset.defaultPort ?? ""), or track user-entered ports separately. (raw.githubusercontent.com)Proposed fix
- if (preset.defaultPort) setPort(String(preset.defaultPort)); + setPort(preset.defaultPort ?? "");🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/web/src/components/project/create/CreateProjectDialog.tsx` around lines 130 - 141, Update handleSelectPreset to always synchronize the port state with the selected FrameworkPreset by setting it to the default port string when present and clearing it when defaultPort is absent, preventing stale values from previously selected presets.
66-67: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winKeep
selectedPresetIdandprojectTypeconsistent.When a user selects a preset and then changes the project type manually, the selected preset and its commands remain active. The dialog can submit
projectType: "static"with web-preset commands. ClearselectedPresetIdand all preset-derived fields when the type changes, or route both actions through one state transition. (raw.githubusercontent.com)Also applies to: 130-141
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/web/src/components/project/create/CreateProjectDialog.tsx` around lines 66 - 67, Update the project type change handling in CreateProjectDialog so changing the type clears selectedPresetId and every preset-derived field, preventing stale preset commands from being submitted with the new type. Keep preset selection and type changes synchronized through the same state transition where applicable.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/web/src/components/project/create/CreateProjectDialog.tsx`:
- Around line 76-83: Expose the stored build settings in CreateProjectDialog by
passing buildCommand, installCommand, startCommand, and outputDir along with
their setters to StepBasics. Update StepBasics to accept these controlled props
and render BuildStrategySection so users can edit custom build settings, while
preserving the existing submission values for docker and other presets.
- Around line 76-83: Refactor CreateProjectDialog by extracting its form state
and submission lifecycle—including the buildCommand, installCommand,
startCommand, and outputDir state—into a dedicated hook or feature module. Keep
the dialog shell and step composition in CreateProjectDialog, preserving
existing behavior while reducing the file below 500 lines and grouping the
extracted logic with the feature.
- Around line 156-160: Update the dialog close/reset logic in
CreateProjectDialog so that when isOpen is false it also resets projectType,
stagedEnvs, submittingStatus, and errorMessage, alongside the existing preset
and command fields. Ensure each new dialog starts with default transient
creation state and no prior status or error.
---
Outside diff comments:
In `@apps/web/src/components/project/create/CreateProjectDialog.tsx`:
- Around line 130-141: Update handleSelectPreset to always synchronize the port
state with the selected FrameworkPreset by setting it to the default port string
when present and clearing it when defaultPort is absent, preventing stale values
from previously selected presets.
- Around line 66-67: Update the project type change handling in
CreateProjectDialog so changing the type clears selectedPresetId and every
preset-derived field, preventing stale preset commands from being submitted with
the new type. Keep preset selection and type changes synchronized through the
same state transition where applicable.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 2147431a-c9bf-4bc7-9ca0-52fcdc83c1b6
📒 Files selected for processing (5)
apps/api/src/orchestrator/pipeline.tsapps/api/src/orchestrator/railpack-config-utils.tsapps/web/src/components/project/create/CreateProjectDialog.tsxapps/web/src/components/project/create/CreationStatusOverlay.tsxapps/web/src/routes/CreateProjectPage.tsx
💤 Files with no reviewable changes (1)
- apps/web/src/components/project/create/CreationStatusOverlay.tsx
🚧 Files skipped from review as they are similar to previous changes (3)
- apps/api/src/orchestrator/pipeline.ts
- apps/web/src/routes/CreateProjectPage.tsx
- apps/api/src/orchestrator/railpack-config-utils.ts
| const [buildCommand, setBuildCommand] = | ||
| useState(""); | ||
| const [installCommand, setInstallCommand] = | ||
| useState(""); | ||
| const [startCommand, setStartCommand] = | ||
| useState(""); | ||
| const [outputDir, setOutputDir] = | ||
| useState(""); |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift
Expose the build settings in this dialog.
The dialog stores and submits buildCommand, installCommand, startCommand, and outputDir, but it passes none of those values or setters to StepBasics. StepBasics renders general settings, source settings, and port only. Users cannot enter custom commands in this dialog. The docker and other presets therefore submit empty command fields. Add controlled build props and render BuildStrategySection, or remove these fields from this dialog. (raw.githubusercontent.com)
Suggested wiring
<StepBasics
+ buildCommand={buildCommand}
+ setBuildCommand={setBuildCommand}
+ installCommand={installCommand}
+ setInstallCommand={setInstallCommand}
+ startCommand={startCommand}
+ setStartCommand={setStartCommand}
+ outputDir={outputDir}
+ setOutputDir={setOutputDir}
/>Also applies to: 454-458
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@apps/web/src/components/project/create/CreateProjectDialog.tsx` around lines
76 - 83, Expose the stored build settings in CreateProjectDialog by passing
buildCommand, installCommand, startCommand, and outputDir along with their
setters to StepBasics. Update StepBasics to accept these controlled props and
render BuildStrategySection so users can edit custom build settings, while
preserving the existing submission values for docker and other presets.
📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy lift
Split CreateProjectDialog before adding more state.
The file spans 595 lines. Extract the form state and submission lifecycle into a hook or feature module, and keep the dialog shell and step composition below 500 lines.
As per coding guidelines, “No file should be above 500 lines of code; if it is, refactor and split into smaller files with proper feature grouping in a folder rather than scattered across the codebase.”
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@apps/web/src/components/project/create/CreateProjectDialog.tsx` around lines
76 - 83, Refactor CreateProjectDialog by extracting its form state and
submission lifecycle—including the buildCommand, installCommand, startCommand,
and outputDir state—into a dedicated hook or feature module. Keep the dialog
shell and step composition in CreateProjectDialog, preserving existing behavior
while reducing the file below 500 lines and grouping the extracted logic with
the feature.
Source: Coding guidelines
| setSelectedPresetId(""); | ||
| setBuildCommand(""); | ||
| setInstallCommand(""); | ||
| setStartCommand(""); | ||
| setOutputDir(""); |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
Reset all transient creation state when the dialog closes.
The close path does not reset projectType, stagedEnvs, submittingStatus, or errorMessage. A later dialog can reopen with the old status overlay, retain a previous static project type, or attach prior environment variables to a new project. Reset these values when isOpen is false.
Proposed reset additions
setSelectedPresetId("");
+ setProjectType("web");
setBuildCommand("");
setInstallCommand("");
setStartCommand("");
setOutputDir("");
setPort("");
setZipFile(null);
+ setStagedEnvs([]);
+ setSubmittingStatus("idle");
+ setErrorMessage("");📝 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.
| setSelectedPresetId(""); | |
| setBuildCommand(""); | |
| setInstallCommand(""); | |
| setStartCommand(""); | |
| setOutputDir(""); | |
| setSelectedPresetId(""); | |
| setProjectType("web"); | |
| setBuildCommand(""); | |
| setInstallCommand(""); | |
| setStartCommand(""); | |
| setOutputDir(""); | |
| setPort(""); | |
| setZipFile(null); | |
| setStagedEnvs([]); | |
| setSubmittingStatus("idle"); | |
| setErrorMessage(""); |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@apps/web/src/components/project/create/CreateProjectDialog.tsx` around lines
156 - 160, Update the dialog close/reset logic in CreateProjectDialog so that
when isOpen is false it also resets projectType, stagedEnvs, submittingStatus,
and errorMessage, alongside the existing preset and command fields. Ensure each
new dialog starts with default transient creation state and no prior status or
error.
Summary by CodeRabbit
New Features
Bug Fixes