Survival LLM
A free AI assistant and survival library (1.5 million offline articles) that runs on your own computer, with no internet. Shows the source of every answer. Mac and Windows.
The site is still in the dark. Bring your own light.
OtherTypeScript · CSSGitHub @HeresharshadOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
Coming soon page for heresharshad.com
Translation pending
Taken from the repository README
Loading the full README.
Read the full README ↗Personal portfolio for Harshad, built with Next.js. The homepage is a scroll-driven 3D studio: a hanging bulb on a pull chain (Three.js) lights an architectural wall and the DOM typography in front of it. About, Work, Experiments and Contact pages sit alongside it.
The current theme and global styling are temporary. The website will receive a future visual redesign, so avoid introducing a large design system or treating the current CSS as permanent architecture.
Next.js (App Router) · React · TypeScript · Tailwind CSS v4 · shadcn/ui · GSAP + @gsap/react · Three.js + React Three Fiber + Drei · Remix Icon (@remixicon/react, re-exported from src/components/icons.tsx)
npm install # install dependencies
npm run dev # dev server at http://localhost:3000
npm run lint # ESLint
npx tsc --noEmit # type check
npm run build # production build
npm run start # serve the production build
src/
├── app/
│ ├── layout.tsx, globals.css, home.css root layout, global + homepage styles
│ ├── page.tsx homepage
│ ├── (site)/ pages that share header/footer
│ │ ├── about/ work/ work/[slug]/ contact/
│ │ └── layout.tsx, loading.tsx
│ ├── (rooms)/ pages that are rooms of the 3D world
│ │ ├── experiments/
│ │ └── layout.tsx
│ ├── not-found.tsx, error.tsx 404 and error states
├── components/
│ ├── world/ the shared 3D world: persistent canvas, room registry, transitions
│ ├── home/ homepage: the studio scene, pendant, sections
│ ├── layout/ header, footer, nav, page heading
│ ├── experiments/ Three.js demos + registry
│ ├── work/ project card
│ └── ui/ shadcn/ui components
├── config/site.ts site info, nav, social links
├── data/projects.ts project data
├── hooks/, lib/, types/
public/ static assets
The portfolio is one continuous 3D space. The root layout mounts WorldLayer (src/components/world/world-layer.tsx): a single React Three Fiber canvas that is created the first time a page declares a room and then survives every route change. Pages never touch the canvas; they only say which room they are:
HomeExperience) calls useDeclareEnvironment("studio");/experiments wraps its content in <RoomPage id="experiments">.src/components/world/store.ts is the single source of truth (declared room, mounted rooms, the active room, the transition in flight, who owns the camera). registry.ts lists every room: its route, a lazy scene module, its rest camera pose and, optionally, an EntryTransition describing how you get in from the studio. controller.ts sequences a journey with one GSAP timeline that tweens a TransitionProgress object the scenes read each frame; the route is pushed once the camera is through the opening, the room you left is disposed once you have settled. Pages outside the world ((site)) leave the canvas hidden and idle; direct loads, refreshes and back/forward cut between rooms through a short dip to dark.
On a fresh load of the homepage, src/components/home/intro-curtain.tsx covers the page with a small HTML/CSS loader (a warming filament where the pendant hangs, and a status line) until the world has drawn its first complete frame of the studio, then lifts it outward from the bulb. Its steps are the world's real ones: hydration (booted), the renderer (camera), the studio fetched, built and compiled (ready), and the first frame (firstFrame). An inline script switches it on while the HTML is parsed, so it never appears on a client-side navigation and never without JavaScript; a CSS failsafe lifts it if the app's JavaScript never arrives, and after 9 s of visible waiting it offers a way in. No WebGL, or a world that fails to start (failed, caught by the boundary in world-layer.tsx), lifts it at once onto the still fallback.
The world draws nothing until the active room is ready (Present in world-canvas.tsx), and rooms compile with gl.compileAsync before calling onReady(), so shaders compile in parallel off the main thread instead of on the first draw. Keep three.js out of anything the root layout imports at runtime (type imports are fine): it would ship in every page's first load.
Scene: an R3F component taking EnvironmentProps (src/components/world/types.ts), e.g. src/components/world/environments/about/room.tsx. Build its geometry and lights, call onReady() once gl.compileAsync(scene, camera) resolves (the world will not draw the room before then), dispose what you create. Read world.get().transition?.progress for choreography.
Config: a small config.ts next to it with restPose(viewport) and, if it is entered through the studio wall, an EntryTransition (kind: "wall-opening", the door cut in the wall, camera path keyframes, timing; a narrow variant for phones). environments/experiments/config.ts is the worked example.
Register: add it to rooms in registry.ts:
about: { id: "about", route: "/about", load: () => import("./environments/about/room"), camera: { rest: aboutRest }, entry: aboutEntry },
Page: move it under src/app/(rooms)/about/page.tsx and wrap its content in <RoomPage id="about">. Links from the homepage use TransitionLink, which turns a plain click on a registered route into the journey and falls back to ordinary navigation (modifier keys, reduced motion, no WebGL, a transition already running).
A new transition kind (a light switch, panels sliding apart) is a new EntryTransition["kind"], a studio-side mechanism next to environments/studio-door.tsx, and a case in the controller's timeline; rooms and pages stay as they are.
src/app/(site)/<name>/page.tsx (gets the header/footer), and a link in navLinks in src/config/site.ts.src/data/projects.ts. Set caseStudy: true to get a /work/[slug] page. Unknown slugs return a 404. While the list is empty, /work shows an "under construction" message.src/config/site.ts. Unset (null) links are hidden and flagged on the contact page.src/components/home/home-sections.tsx (server-rendered; each [data-scene] is one camera stop) and home-header.tsx.studio-scene.tsx (the studio as a room of the world: camera rig, scroll keyframes per scene; the canvas, base lights and quality tier are the world's), studio-room.tsx (wall, floor, annotations), studio-tiles.ts (procedural stone-panel cladding: setting-out, joints, bevels, grain), cursor-light.tsx (the cursor as a raking torch, cast into the room), pendant.tsx + pendant-physics.ts (verlet cord, bulb and pull chain).src/components/world/device.ts sorts devices into high (desktop: shadows, reflective floors, up to 1.75x), mid (a capable phone or tablet: the same materials and antialiasing at up to 2x, without shadows or reflections), low (little memory or few cores: simpler materials at 1.4x) and none (no WebGL: the still fallback). The canvas steps its resolution down by 0.25 while frames run under 40 fps and back up when they recover (Resolution in world-canvas.tsx). The noise, braid and glow textures are computed into pixel arrays, not drawn on a canvas, because Safari adds random colour noise to canvas pixels it hands to WebGL.mechanism.tsx is the fly system that moves the bulb: ceiling beam, two pulleys, two hemp lines to the bridle ring, a sandbag counterweight on the right and the operator's gallery on the left. Rope lengths drive pulley rotation, rope weave, sandbag height and the operator's hands, so it always agrees with where the ring is. operator-figure.ts is the mannequin (two-bone IK arms, hand-over-hand pull).home-experience.tsx maps scroll to a scene index, owns the pull chain button, cursor and GSAP scroll choreography. is the shared state between DOM and WebGL.studio-state.tssrc/app/home.css; colour variables in src/app/globals.css. The hero type is lit by CSS variables the scene writes each frame (--gx, --gy, --li, --sx, --sy).WIDE / NARROW keyframes at the top of studio-scene.tsx, and the pulley positions are PULLEYS. Both are in screen (NDC) coordinates so the rig frames every viewport the same way. Content alternates sides (work left, experiments right, about left, contact right) and the ring sits opposite.src/lib/animations/use-page-reveal.ts; mark elements with data-reveal.src/components/experiments/; register new ones in registry.tsx (title, stack, type, status, source path). /experiments shows each as a card (experiment-card.tsx) with a "Next up" row of open slots (OPEN_SLOTS), and /experiments/[slug] shows one at full width. Scenes load client-side only and respect reduced motion.src/components/world/environments/experiments/ (config.ts door, camera path and rest pose; room.tsx the painted walls, the cyan floor strip and the blue fluorescent batten; workbench.tsx the garage workbench, pegboard, laptop and clamp lamp). The concealed slab in the studio wall is src/components/world/environments/studio-door.tsx; the cladding shader's uDoor cuts the wall and uTileOffset lets the slab keep its own panels as it moves.