# Project export: LumaLens

This document was generated by HackStack to give an AI agent context about a hackathon project. Sections are labeled with their provenance; content marked as truncated was cut to keep this document small.

## Project metadata

- Hackathon: UC Berkeley AI Hackathon 2026
- Tagline: LumaLens - Photo/Video into 3D landscape lighting environments
- Devpost: https://devpost.com/software/lumalens
- GitHub: https://github.com/cai-py/LumaLens
- Team: 1 GitHub contributor(s) — Cairo Flores (1 commits)

## Devpost submission (written by the team)

No Devpost description available.

## README (from the GitHub repository)

This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app).

## Getting Started

First, run the development server:

```bash
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun dev
```

Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.

You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.

This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel.

## Learn More

To learn more about Next.js, take a look at the following resources:

- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.

You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!

## Deploy on Vercel

The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.

Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.


## Detected evidence (automated analysis)

Indexed codebase: 11 recognized source files, 13 KB.
- CSS (language) — detected in the code
- Next.js (technology) — detected in the code
- React (technology) — detected in the code
- Tailwind CSS (technology) — detected in the code
- TypeScript (language) — detected in the code
- AI coding agent: Claude Code — evidence: config files committed to the repository
- AI coding agent: Codex — evidence: config files committed to the repository

## Codebase structure (from repository index)

### Files (17 of 17)

```
.gitignore
AGENTS.md
app/globals.css
app/layout.tsx
app/page.tsx
CLAUDE.md
components/Scene.tsx
components/SceneWrapper.tsx
components/TemplateHouse.tsx
eslint.config.mjs
lib/house.ts
next.config.ts
package.json
postcss.config.mjs
README.md
temp/DevTrackContext.txt
tsconfig.json
```

### Dependencies

- package.json: @tailwindcss/postcss@^4, @types/node@^20, @types/react@^19, @types/react-dom@^19, eslint@^9, eslint-config-next@16.2.9, next@16.2.9, react@19.2.4, react-dom@19.2.4, tailwindcss@^4, typescript@^5

### Recent commits (newest first)

- Use TemplateHouse model and expand Scene to full viewport
- Add SceneWrapper client component and render Scene on homepage
- Replace Next/Vercel logos with LumaLens logo
- Initial commit: Next.js + 3D house scene with lighting presets

## Key source files (fetched from GitHub, selected and truncated for size)

### CLAUDE.md

```markdown
@AGENTS.md

```

### AGENTS.md

```markdown
<!-- BEGIN:nextjs-agent-rules -->
# This is NOT the Next.js you know

This version has breaking changes — APIs, conventions, and file structure may all differ from your training data. Read the relevant guide in `node_modules/next/dist/docs/` before writing any code. Heed deprecation notices.
<!-- END:nextjs-agent-rules -->

```

### package.json

```
{
  "name": "luma-lens",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "eslint"
  },
  "dependencies": {
    "next": "16.2.9",
    "react": "19.2.4",
    "react-dom": "19.2.4"
  },
  "devDependencies": {
    "@tailwindcss/postcss": "^4",
    "@types/node": "^20",
    "@types/react": "^19",
    "@types/react-dom": "^19",
    "eslint": "^9",
    "eslint-config-next": "16.2.9",
    "tailwindcss": "^4",
    "typescript": "^5"
  }
}

```

### app/layout.tsx

```typescript
import type { Metadata } from "next";
import { Geist, Geist_Mono } from "next/font/google";
import "./globals.css";

const geistSans = Geist({
  variable: "--font-geist-sans",
  subsets: ["latin"],
});

const geistMono = Geist_Mono({
  variable: "--font-geist-mono",
  subsets: ["latin"],
});

export const metadata: Metadata = {
  title: "Create Next App",
  description: "Generated by create next app",
};

export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
    <html
      lang="en"
      className={`${geistSans.variable} ${geistMono.variable} h-full antialiased`}
    >
      <body className="min-h-full flex flex-col">{children}</body>
    </html>
  );
}

```

### app/page.tsx

```typescript
import Image from "next/image";
import SceneWrapper from "../components/SceneWrapper";

export default function Home() {
  return (
    <div className="flex flex-col flex-1 items-center justify-center bg-zinc-50 font-sans dark:bg-black">
      <main className="flex flex-1 w-full max-w-3xl flex-col items-center justify-between py-32 px-16 bg-white dark:bg-black sm:items-start">
        <Image
          className="dark:invert"
          src="/lumalens_logo.svg"
          alt="LumaLens logo"
          width={120}
          height={28}
          priority
        />
        <div className="flex flex-col items-center gap-6 text-center sm:items-start sm:text-left">
          <h1 className="max-w-xs text-3xl font-semibold leading-10 tracking-tight text-black dark:text-zinc-50">
            LumaLens — real-time house preview
          </h1>
          <p className="max-w-md text-lg leading-8 text-zinc-600 dark:text-zinc-400">
            Live 3D preview of procedural house geometry with selectable
            lighting presets.
          </p>
        </div>
        <div className="w-full mt-8">
          <SceneWrapper />
        </div>
        <div className="flex flex-col gap-4 text-base font-medium sm:flex-row">
          <a
            className="flex h-12 w-full items-center justify-center gap-2 rounded-full bg-foreground px-5 text-background transition-colors hover:bg-[#383838] dark:hover:bg-[#ccc] md:w-[158px]"
            href="https://vercel.com/new?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
            target="_blank"
            rel="noopener noreferrer"
          >
            <Image
              className="dark:invert"
              src="/lumalens_logo.svg"
              alt="LumaLens logo"
              width={16}
              height={16}
            />
            Deploy Now
          </a>
          <a
            className="flex h-12 w-full items-center justify-center rounded-full border border-solid border-black/[.08] px-5 transition-colors hover:border-transparent hover:bg-black/[.04] dark:border-white/[.145] dark:hover:bg-[#1a1a1a] md:w-[158px]"
            href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
            target="_blank"
            rel="noopener noreferrer"
          >
            Documentation
          </a>
        </div>
      </main>
    </div>
  );
}

```

### next.config.ts

```typescript
import type { NextConfig } from "next";

const nextConfig: NextConfig = {
  /* config options here */
};

export default nextConfig;

```

### components/SceneWrapper.tsx

```typescript
"use client";

import Scene from "./Scene";
import { sampleHouseGeometry } from "../lib/house";

export default function SceneWrapper() {
  return (
    <div className="w-full h-screen">
      <Scene house={sampleHouseGeometry} lightingScenario={"Curb Appeal"} />
    </div>
  );
}

```

### app/globals.css

```css
@import "tailwindcss";

:root {
  --background: #ffffff;
  --foreground: #171717;
}

@theme inline {
  --color-background: var(--background);
  --color-foreground: var(--foreground);
  --font-sans: var(--font-geist-sans);
  --font-mono: var(--font-geist-mono);
}

@media (prefers-color-scheme: dark) {
  :root {
    --background: #0a0a0a;
    --foreground: #ededed;
  }
}

body {
  background: var(--background);
  color: var(--foreground);
  font-family: Arial, Helvetica, sans-serif;
}

```

### lib/house.ts

```typescript
export type RoofShape = "gabled" | "hipped" | "flat";

export interface HouseFeatures {
  garage: boolean;
  porch: boolean;
  columns: number;
  chimney: boolean;
}

export interface HouseGeometry {
  stories: number;
  facadeWidth: number;
  roofShape: RoofShape;
  materials: string[];
  features: HouseFeatures;
}

export type LightingScenario =
  | "Curb Appeal"
  | "Security"
  | "Dramatic"
  | "Minimal";

export const LIGHTING_SCENARIOS: LightingScenario[] = [
  "Curb Appeal",
  "Security",
  "Dramatic",
  "Minimal",
];

export const MAX_PHOTOS = 5;

export const sampleHouseGeometry: HouseGeometry = {
  stories: 2,
  facadeWidth: 5,
  roofShape: "gabled",
  materials: ["brick", "wood siding", "shingle roof"],
  features: {
    garage: true,
    porch: true,
    columns: 2,
    chimney: true,
  },
};

```

### components/TemplateHouse.tsx

```typescript
import { useMemo } from "react";

export default function TemplateHouse() {
  const wallMat = useMemo(() => ({ color: "#e9e4db", roughness: 0.8 }), []);
  const roofMat = useMemo(() => ({ color: "#7b4f3b", roughness: 0.7 }), []);

  return (
    <group rotation={[0, Math.PI / 8, 0]} position={[0, 0.6, 0]}>
      {/* Main volume */}
      <mesh position={[0, 1.1, 0]} castShadow receiveShadow>
        <boxGeometry args={[4, 2.2, 3]} />
        <meshStandardMaterial {...wallMat} />
      </mesh>

      {/* Gabled roof */}
      <mesh position={[0, 2.4, 0]} rotation={[0, 0, 0]} castShadow>
        <coneGeometry args={[2.6, 1.2, 4]} />
        <meshStandardMaterial {...roofMat} />
      </mesh>

      {/* Door */}
      <mesh position={[0, 0.3, 1.51]} castShadow>
        <boxGeometry args={[0.7, 1.2, 0.08]} />
        <meshStandardMaterial color="#5b3a29" />
      </mesh>

      {/* Windows */}
      <mesh position={[-1.1, 1.1, 1.51]} castShadow>
        <boxGeometry args={[0.6, 0.6, 0.05]} />
        <meshStandardMaterial color="#cfe8ff" metalness={0.1} roughness={0.3} />
      </mesh>
      <mesh position={[1.1, 1.1, 1.51]} castShadow>
        <boxGeometry args={[0.6, 0.6, 0.05]} />
        <meshStandardMaterial color="#cfe8ff" metalness={0.1} roughness={0.3} />
      </mesh>

      {/* Garage */}
      <mesh position={[2.1, 0.55, -0.2]} castShadow>
        <boxGeometry args={[1.2, 1.1, 1.6]} />
        <meshStandardMaterial color="#d0d0d0" />
      </mesh>

      {/* Chimney */}
      <mesh position={[-1.3, 2.1, -0.3]} castShadow>
        <boxGeometry args={[0.25, 0.9, 0.25]} />
        <meshStandardMaterial color="#6b5b4b" />
      </mesh>
    </group>
  );
}

```

[1 more indexed source files omitted to keep this export small. The full file list is in the Codebase structure section above.]