Interactive 3D visualization of the Fractional Fill Theory framework, built with React, Three.js, and a Node/Express backend on Neon Postgres.
- Client: React 18 + TypeScript, Vite, Three.js / @react-three/fiber, Tailwind CSS
- Server: Express, Drizzle ORM
- Database: Neon (serverless Postgres)
- Deployment: Railway (Railpack builder)
.
├── client/ # Frontend application
│ ├── index.html # Vite entry HTML
│ ├── public/ # Static assets
│ │ ├── fonts/
│ │ ├── geometries/
│ │ ├── sounds/
│ │ └── textures/
│ └── src/
│ ├── App.tsx # Root component
│ ├── main.tsx # React entry point
│ ├── index.css # Tailwind directives + global/canvas styles
│ ├── components/ # Visualization & UI components
│ ├── hooks/ # Custom React hooks
│ ├── lib/ # Client-side utilities
│ ├── pages/ # Route-level views
│ └── shaders/ # GLSL shader files
├── server/ # Backend application
│ ├── index.ts # Server entry point, listens on process.env.PORT
│ ├── routes.ts # API route definitions
│ ├── storage.ts # Data access layer
│ └── vite.ts # Vite middleware (dev) / static serving (prod)
├── shared/
│ └── schema.ts # Shared types/schema between client and server
├── dist/ # Build output (gitignored)
├── drizzle.config.ts # Drizzle ORM configuration
├── railway.json # Railway deploy configuration
├── tailwind.config.ts
├── tsconfig.json
└── vite.config.ts
- Node.js 22.x
- A Neon Postgres database (or compatible Postgres connection string)
npm installCreate a .env file at the project root (never commit this):
DATABASE_URL=postgresql://user:password@host/dbname?sslmode=require
Note: the server reads
DATABASE_URL— make sure your environment variable name matches exactly. Variable naming mismatches (e.g.BASE_URLvsDATABASE_URL) are a common source of silent connection failures.
npm run devRuns the Express server with tsx, serving the Vite dev middleware for the client.
npm run buildRuns vite build (outputs to dist/public) followed by esbuild bundling of the server (outputs to dist/index.js).
npm startRuns node dist/index.js. The server reads the port from process.env.PORT (falling back to 5000 for local use) and binds to 0.0.0.0 — required for the app to be reachable when deployed behind Railway's proxy.
- Builder: Railpack (auto-detected Node project)
- Build command:
npm run build(auto-detected frompackage.json) - Start command:
npm start(auto-detected frompackage.json) - Config-as-code: see
railway.jsonfor restart policy and replica settings - Healthcheck Path: not currently configured — consider adding one (e.g. a simple
/healthroute) so failed deployments are caught before serving traffic, rather than relying on the container simply not crashing.
| Variable | Description |
|---|---|
DATABASE_URL |
Neon Postgres pooled connection string, with ?sslmode=require |
PORT |
Set automatically by Railway — do not hardcode this in code |
- The client (
client/) and server (server/) are built and deployed as a single service — the Express server serves the built static client in production (seeserver/vite.ts). - Path aliases:
@→client/src,@shared→shared/(seevite.config.ts). - Visualization components under
client/src/components/implement the Fractional Fill Theory geometry and rendering logic and may contain proprietary algorithmic implementations — see.gitignoreand internal documentation before sharing or open-sourcing specific files. neon-railway-example/is a standalone reference example and is not part of the deployed application.
MIT — see LICENSE.