Floorscape is an AI-assisted architectural visualization app that converts uploaded 2D floor plans into rendered top-down 3D interiors. The frontend is built with React Router 7, React 19, Vite, and Tailwind CSS v4, while authentication, file hosting, AI image generation, and project persistence are handled through Puter services.
Live demo: https://floorscape.netlify.app/
The application is designed around a simple workflow:
- Sign in with Puter.
- Upload a floor plan image.
- Generate a photorealistic 3D render from the plan.
- Review the result in a visualizer with before/after comparison.
- Export the generated image and revisit saved projects.
The codebase includes both:
- A React Router frontend for the user interface
- A Puter worker script that exposes project persistence endpoints
- Puter-based authentication
- Drag-and-drop floor plan upload
- AI-powered 2D-to-3D floor plan rendering
- Automatic project creation and persistence
- Hosted asset upload for source and rendered images
- Project listing on the home page
- Project detail route at
visualizer/:id - Before/after image comparison with
react-compare-slider - Render export as a local PNG download
- Docker support for containerized builds
- React 19
- React Router 7
- TypeScript
- Vite 7
- Tailwind CSS 4
lucide-reactreact-compare-slider
- Puter SDK (
@heyputer/puter.js) - Puter Auth
- Puter KV
- Puter Hosting
- Puter Workers
- Puter AI image generation
- Node.js 20+
- npm
- Docker
- Node.js 20 or newer
- npm
- A Puter account
- A deployed Puter worker URL for project persistence
git clone https://github.com/arbaz93/FloorScape.git
cd FloorScape
npm installCreate .env.local in the project root with:
VITE_PUTER_WORKER_URL=https://your-worker.puter.workVITE_PUTER_WORKER_URL is required for saving, listing, and fetching projects.
npm run devnpm run buildnpm run start- Open the app.
- Click
Log Inand authenticate with Puter. - Upload a
.jpg,.jpeg,.png, or.webpfloor plan image. - Wait for the visualizer route to generate the 3D render.
- Compare the original plan and generated render.
- Export the final image.
npm install
npm run devThen open the local Vite/React Router dev URL shown in the terminal.
Build the container:
docker build -t floorscape .Run the container:
docker run -p 3000:3000 floorscapenpm run devstarts the development servernpm run buildbuilds the React Router appnpm run startserves the built app from./build/server/index.jsnpm run typecheckruns route type generation and TypeScript checks
npm run typecheckcurrently fails atapp/routes/visualizer.$id.tsx:213becausestring | null | undefinedis passed to a prop expectingstring | undefined.
roomify/
├── app/
│ ├── app.css
│ ├── root.tsx
│ ├── routes.ts
│ └── routes/
│ ├── home.tsx
│ └── visualizer.$id.tsx
├── components/
│ ├── Navbar.tsx
│ ├── Upload.tsx
│ └── ui/
│ └── Button.tsx
├── lib/
│ ├── ai.action.ts
│ ├── constants.ts
│ ├── puter.action.ts
│ ├── puter.hosting.tsx
│ ├── puter.worker.js
│ └── utils.tsx
├── public/
├── build/
├── Dockerfile
├── package.json
├── react-router.config.ts
├── tsconfig.json
├── type.d.ts
└── vite.config.ts
Detected routes:
/renders the home page with upload and project listing/visualizer/:idrenders the project visualizer and generation workflow
The repository contains a Puter worker implementation in lib/puter.worker.js. The frontend calls these endpoints through puter.workers.exec(...).
${VITE_PUTER_WORKER_URL}
Saves or updates a project.
Request body:
{
"project": {
"id": "1741330123456",
"name": "Floorscape plan 1741330123456",
"sourceImage": "data:image/png;base64,...",
"renderedImage": "data:image/png;base64,...",
"timestamp": 1741330123456
},
"visibility": "private"
}Success response:
{
"saved": true,
"id": "1741330123456",
"project": {
"id": "1741330123456",
"name": "Floorscape plan 1741330123456",
"sourceImage": "https://...",
"renderedImage": "https://...",
"timestamp": 1741330123456,
"updatedAt": "2026-03-10T00:00:00.000Z"
}
}Returns saved projects for the authenticated user context.
Success response:
{
"projects": [
{
"id": "1741330123456",
"name": "Floorscape plan 1741330123456",
"sourceImage": "https://...",
"renderedImage": "https://...",
"timestamp": 1741330123456,
"isPublic": true
}
]
}Fetches one project by ID.
Success response:
{
"project": {
"id": "1741330123456",
"name": "Floorscape plan 1741330123456",
"sourceImage": "https://...",
"renderedImage": "https://...",
"timestamp": 1741330123456
}
}All detected worker endpoints require a valid Puter-authenticated user. The worker returns 401 when authentication fails.
The render pipeline is implemented in lib/ai.action.ts:
- Accepts a source image as a data URL or hosted URL
- Converts it to base64
- Sends it to Puter AI using the Gemini image model
- Returns a rendered image for display and persistence
The prompt in lib/constants.ts instructs the model to:
- preserve the original floor-plan geometry
- remove labels and plan text
- keep a strict top-down perspective
- produce a realistic architectural visualization
Contributions should stay consistent with the current architecture:
- Fork the repository and create a feature branch.
- Keep changes scoped and focused.
- Update documentation when behavior or setup changes.
- Run
npm run typecheckbefore opening a pull request. - Include screenshots or short notes for UI changes.
- Describe any Puter worker or environment variable changes in the PR.
Example workflow:
git checkout -b feat/improve-visualizer
npm run typecheck
git commit -m "Improve visualizer render handling"No license file was detected in this repository at the time of writing. If you intend to distribute or open-source the project, add a license file such as LICENSE and update this section accordingly.

