Powrót do strony głównej

Roomify: AI-renderowanie wnętrz na React Puter

Roomify — aplikacja webowa do generowania 3D-renderów wnętrz z planów 2D z użyciem React i Puter. Architektura na serverless workers eliminuje backend. Podano kod workers, hooki frontendu i rozwiązania problemów.

Stwórz AI-wizualizator jak Roomify na React+Puter
Advertisement 728x90

Roomify: Wdrożenie AI-wizualizatora wnętrz z React i serverless Puter

Roomify przekształca dwuwymiarowy plan pomieszczenia w fotorealistyczny render 3D w ciągu sekund. Aplikacja wykorzystuje React 19 z TypeScript na frontendzie oraz platformę Puter do logiki serverless, przechowywania danych i generowania AI. Bez własnego backendu frontend komunikuje się bezpośrednio z API Puter przez SDK puter.js.

Architektura eliminuje tradycyjny serwer: przesyłanie plików, tworzenie projektów i wywoływanie AI odbywa się w workers. Upraszcza to wdrożenie i skalowanie dla programistów średniego i zaawansowanego poziomu.

Stos technologiczny i jego rola

  • React 19 + TypeScript: typowany frontend z HMR przez Vite.
  • React Router 7: routing dla strony głównej i wizualizatora.
  • Tailwind CSS: style użytkowe bez własnego CSS.
  • Lucide React: ikony do interfejsu użytkownika.
  • Puter.js: dostęp do przechowywania plików, KV, workers i modeli AI z poziomu przeglądarki.

Puter dostarcza serverless workers, przechowywanie KV i trwałe przechowywanie plików. Workers są wywoływane przez puter.action, AI — przez puter.ai.generate.

Google AdInline article slot

Architektura: od przesyłania do renderowania

Proces przetwarzania:

  • Przesłanie planu przez puter.file.write.
  • Uzyskanie publicznego URL pliku.
  • Wywołanie worker project.create do zapisu metadanych w KV.
  • Generowanie przez worker ai.render3d: załadowanie obrazu, sformułowanie promptu, wywołanie Claude/Gemini, zapisanie wyniku.
  • Aktualizacja KV z URL renderu i zwrot na frontend.

Frontend wyświetla oryginalny plan i render z użyciem react-compare-slider do porównania.

Funkcje workers: kod i logika

Funkcje workers w JavaScript są ładowane przez Puter CLI.

Google AdInline article slot

Tworzenie projektu:

// lib/puter.action.ts
export async function createProject({ item, visibility }) {
  const result = await puter.action('project.create', {
    item,
    visibility,
  });
  return result;
}

export async function getProjects() {
  return await puter.action('project.list');
}

export async function getProjectById({ id }) {
  return await puter.action('project.get', { id });
}

Generowanie renderu:

// worker: ai.render3d
export default async ({ sourceImage, style = 'photorealistic' }) => {
  const imageUrl = typeof sourceImage === 'string' ? sourceImage : await puter.file.url(sourceImage);
  
  const prompt = `
    Przekształć ten plan pomieszczenia w ${style} render 3D wnętrza.
    Obraz przedstawia układ pomieszczenia ze ścianami, oknami i drzwiami.
    Wygeneruj realistyczny widok z perspektywy, która najlepiej prezentuje przestrzeń.
    Dodaj odpowiednie meble, tekstury, oświetlenie i cienie.
    Spraw, aby wyglądało jak profesjonalna wizualizacja architektoniczna.
  `;
  
  const result = await puter.ai.generate({
    model: 'claude-3-sonnet',
    prompt,
    images: [imageUrl],
    responseFormat: 'image'
  });
  
  const renderedPath = `/projects/${projectId}/rendered.png`;
  await puter.file.write(renderedPath, result.image);
  
  const key = `project:${projectId}`;
  const project = JSON.parse(await puter.kv.get(key));
  project.renderedImage = puter.file.url(renderedPath);
  await puter.kv.set(key, JSON.stringify(project));
  
  return {
    renderedImage: project.renderedImage,
    renderedPath
  };
};

KV przechowuje metadane: nazwa projektu, właściciel, prywatność, linki do plików.

Google AdInline article slot

Frontend: komponenty i hooki

Strona główna (Home) pokazuje listę projektów. Komponent Upload konwertuje plik na base64:

// components/Upload.tsx
const handleFileChange = async (e) => {
  const file = e.target.files[0];
  if (!file) return;
  const base64 = await toBase64(file);
  onComplete(base64);
};

Wizualizator (VisualizerId) używa useEffect do autogeneracji:

useEffect(() => {
  if (isProjectLoading || hasInitialGenerated.current || !project?.sourceImage) return;
  if (project.renderedImage) {
    setCurrentImage(project.renderedImage);
    hasInitialGenerated.current = true;
    return;
  }
  hasInitialGenerated.current = true;
  void runGeneration(project);
}, [project, isProjectLoading]);

useRef zapobiega powtórnym wywołaniom. Stan jest lokalny, bez Redux.

Rozwiązanie typowych problemów

  • CORS: proxy Vite w trybie deweloperskim.
  • Rozmiar base64: zapis pliku osobno, link w KV.
  • Podwójne generowanie: useRef + sprawdzenia.
  • Asynchroniczność: stany ładowania, skeleton loadery.
  • UI mobilny: responsywność Tailwind, obsługa dotyku dla suwaka.

Walidacja: pliki do 10 MB, JPG/PNG. Loadery dla 10-15 sekund generowania.

Co jest ważne

  • Puter zastępuje backend: workers, KV, pliki, AI w jednym SDK.
  • Hooki React zarządzają stanem bez zewnętrznych bibliotek.
  • Prompt decyduje o jakości: detale ścian, mebli, oświetlenia.
  • Architektura skalowalna dla produkcji bez DevOps.
  • Kod otwarty, nadaje się do forków i eksperymentów.

— Editorial Team

Advertisement 728x90

Czytaj dalej