Skip to content

feat: generate 3D plans using gemini integration#7

Open
L0GI0 wants to merge 1 commit into
masterfrom
generating-3D-plans
Open

feat: generate 3D plans using gemini integration#7
L0GI0 wants to merge 1 commit into
masterfrom
generating-3D-plans

Conversation

@L0GI0
Copy link
Copy Markdown
Owner

@L0GI0 L0GI0 commented May 21, 2026

Summary by CodeRabbit

  • New Features

    • Enhanced visualizer with automatic 3D view generation from source images
    • Added navigation bar with exit, export, and share actions in the visualizer
    • Displays loading state during rendering with fallback to original image preview
  • Chores

    • Updated product branding references throughout the codebase

Review Change Stack

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 21, 2026

📝 Walkthrough

Walkthrough

This PR adds end-to-end 3D visualization rendering: a new generate3DView helper that creates 3D images via Gemini AI, updates storage constants and render prompts from Roomify to Planly branding, passes the correct state key from home to visualizer, and builds a full visualizer component with generation logic, export controls, and image display.

Changes

Planly 3D Visualization Feature

Layer / File(s) Summary
AI rendering infrastructure and constants
lib/constants.ts, lib/ai.action.ts
Adds PLANLY_AI_RENDER_PROMPT constant and storage paths, implements fetchaDataUrl to convert images to base64 data URLs, and generate3DView to call puter.ai.txt2img with source images and return rendered 3D image URLs.
Navigation state alignment
app/routes/home.tsx
Home route now passes initialRender (renamed from initialRendered) in navigation state to the visualizer, derived from saved.renderedImage.
Visualizer component with generation and display
app/routes/visualizer.$id.tsx
Visualizer rewrites from a minimal view to a full editor: imports hooks and components, initializes UI state for mount/processing/current image, implements generation logic that calls generate3DView if no initial render exists, adds a topbar with exit, export/share buttons (export disabled until mounted and image exists), and a render area showing either rendered image, original fallback, or processing overlay.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • L0GI0/Planly-AI#4: Both PRs touch the React Router location.state flow between home and visualizer routes, with this PR's state key rename (initialRenderedinitialRender) synchronizing the navigation contract.
  • L0GI0/Planly-AI#3: This PR consumes types like Generate3DViewParams and VisualizerLocationState that are introduced in the retrieved PR.
  • L0GI0/Planly-AI#2: This PR rewrites the visualizer component to actually implement rendering and state consumption for the route that the retrieved PR originally added.

Poem

🐰 A Bunny's Vision Rendered

With Gemini's lens and prompts anew,
The visualizer springs to life in view—
From home to render, state flows clean,
Where 3D dreams come in between,
Export, share, or pause to see... 🎨✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title accurately describes the main change: integrating Gemini to generate 3D plans, which is reflected across all modified files including the new AI action module, constants updates, and visualizer component enhancements.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch generating-3D-plans

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint skipped: no ESLint configuration detected in root package.json. To enable, add eslint to devDependencies.


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

❤️ Share

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

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a 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

🧹 Nitpick comments (2)
app/routes/visualizer.$id.tsx (1)

45-55: 💤 Low value

runGeneration is not in the dependency array.

While the hasInitialGenerated ref prevents practical issues, ESLint's react-hooks/exhaustive-deps rule would flag this. Consider wrapping runGeneration in useCallback with proper dependencies, or inlining the generation logic within the effect.

🤖 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 `@app/routes/visualizer`.$id.tsx around lines 45 - 55, The effect uses
runGeneration but doesn't include it in its dependency array, triggering
react-hooks/exhaustive-deps; fix by either wrapping runGeneration in useCallback
(exporting a stable function reference) with all its internal dependencies
listed, then add runGeneration to the useEffect deps, or move the generation
logic directly into the useEffect body and remove the external runGeneration
reference; ensure hasInitialGenerated, initialImage, initialRender and
setCurrentImage remain referenced correctly and that the useCallback
dependencies mirror any state/props used inside runGeneration.
lib/ai.action.ts (1)

5-5: 💤 Low value

Typo in function name: fetchaDataUrl.

Should be fetchAsDataUrl or fetchDataUrl for clarity.

Proposed fix
-export const fetchaDataUrl = async (url: string): Promise<string> => {
+export const fetchAsDataUrl = async (url: string): Promise<string> => {

Also update the call sites on lines 20 and 39.

🤖 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 `@lib/ai.action.ts` at line 5, Rename the misspelled function fetchaDataUrl to
a clearer name (e.g., fetchAsDataUrl or fetchDataUrl) and update all usages and
exports to match; specifically change the function declaration export const
fetchaDataUrl to export const fetchAsDataUrl (or fetchDataUrl), update any
internal references/call sites that invoke fetchaDataUrl, and update any
exported name consumers/imports so builds/tests reference the new identifier
consistently.
🤖 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 `@app/routes/visualizer`.$id.tsx:
- Line 12: The component destructures name from location.state but the JSX still
renders a hardcoded "Untitled Project"; update the render to use the
destructured name (fallback to "Untitled Project" if name is falsy) so the
project title uses the passed-in value — locate the destructuring of
location.state (const { initialImage, initialRender, name } = location.state ||
{}) and replace the hardcoded 'Untitled Project' in the JSX with name ||
'Untitled Project' (or name ?? 'Untitled Project').

In `@lib/ai.action.ts`:
- Line 19: The generate3DView function signature uses an undefined type
Generate3DViewParams; add or import a proper type definition for
Generate3DViewParams (e.g., an interface with sourceImage: string | Buffer |
File depending on how images are passed) and export/import it where types are
centralized so TypeScript compiles; update the file to reference the new/renamed
type and ensure any callers match the property name sourceImage used by
generate3DView.

---

Nitpick comments:
In `@app/routes/visualizer`.$id.tsx:
- Around line 45-55: The effect uses runGeneration but doesn't include it in its
dependency array, triggering react-hooks/exhaustive-deps; fix by either wrapping
runGeneration in useCallback (exporting a stable function reference) with all
its internal dependencies listed, then add runGeneration to the useEffect deps,
or move the generation logic directly into the useEffect body and remove the
external runGeneration reference; ensure hasInitialGenerated, initialImage,
initialRender and setCurrentImage remain referenced correctly and that the
useCallback dependencies mirror any state/props used inside runGeneration.

In `@lib/ai.action.ts`:
- Line 5: Rename the misspelled function fetchaDataUrl to a clearer name (e.g.,
fetchAsDataUrl or fetchDataUrl) and update all usages and exports to match;
specifically change the function declaration export const fetchaDataUrl to
export const fetchAsDataUrl (or fetchDataUrl), update any internal
references/call sites that invoke fetchaDataUrl, and update any exported name
consumers/imports so builds/tests reference the new identifier consistently.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 6f641399-7251-4fb6-8d62-5971aedfc439

📥 Commits

Reviewing files that changed from the base of the PR and between 3f4febe and 61a0817.

⛔ Files ignored due to path filters (1)
  • assets/example-floor-plan-1.jpg is excluded by !**/*.jpg
📒 Files selected for processing (5)
  • app/routes/home.tsx
  • app/routes/visualizer.$id.tsx
  • lib/ai.action.ts
  • lib/ai.actions.ts
  • lib/constants.ts

return (
<section>
<h1>{name || 'Untitled Project'}</h1>
const { initialImage, initialRender, name } = location.state || {};
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

name is destructured but never used; hardcoded "Untitled Project" displayed instead.

Line 12 extracts name from location state but Line 73 ignores it and displays 'Untitled Project'.

Proposed fix
-                                <h2>{'Untitled Project'}</h2>
+                                <h2>{name || 'Untitled Project'}</h2>

Also applies to: 73-73

🤖 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 `@app/routes/visualizer`.$id.tsx at line 12, The component destructures name
from location.state but the JSX still renders a hardcoded "Untitled Project";
update the render to use the destructured name (fallback to "Untitled Project"
if name is falsy) so the project title uses the passed-in value — locate the
destructuring of location.state (const { initialImage, initialRender, name } =
location.state || {}) and replace the hardcoded 'Untitled Project' in the JSX
with name || 'Untitled Project' (or name ?? 'Untitled Project').

Comment thread lib/ai.action.ts
});
}

export const generate3DView = async ({sourceImage}: Generate3DViewParams) => {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Missing type definition for Generate3DViewParams.

The type is used but never defined or imported, causing a TypeScript compilation error.

Proposed fix: Add the type definition
 import {getImageExtension} from "./utils";
 import puter from "`@heyputer/puter.js`";
 import {PLANLY_AI_RENDER_PROMPT} from "./constants";
+
+interface Generate3DViewParams {
+    sourceImage: string;
+}
🤖 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 `@lib/ai.action.ts` at line 19, The generate3DView function signature uses an
undefined type Generate3DViewParams; add or import a proper type definition for
Generate3DViewParams (e.g., an interface with sourceImage: string | Buffer |
File depending on how images are passed) and export/import it where types are
centralized so TypeScript compiles; update the file to reference the new/renamed
type and ensure any callers match the property name sourceImage used by
generate3DView.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant