A fullstack two-pane selector designed to remain responsive while working with 1,000,000 records.
The application combines server-side selection state, cursor pagination, virtualized rendering, search, drag-and-drop ordering, and idempotent batch mutations.
Rendering or transferring a million records at once is impractical:
- the browser cannot mount the full collection efficiently;
- deep offset pagination becomes increasingly expensive;
- one-request-per-item mutations create excessive network overhead;
- selection and ordering must remain consistent across requests.
Infinity List addresses these constraints by keeping the backend as the source of truth and loading only the data required by the current viewport.
flowchart LR
User[User] --> React[React application]
React --> Query[TanStack React Query]
React --> UIState[Zustand UI state]
React --> Virtualization[React Virtuoso]
React --> DragDrop[dnd-kit]
Query --> API[Express REST API]
API --> Available[Available-item queries]
API --> Selected[Selected-item queries]
API --> Mutations[Batch selection mutations]
Available --> State[Server-side item state]
Selected --> State
Mutations --> State
Contracts[Shared Zod contracts] --> React
Contracts --> API
Frontend
- React 18
- TypeScript
- Vite
- TanStack React Query
- Zustand
- React Virtuoso
- dnd-kit
Backend
- Node.js
- Express
- TypeScript
- Zod
- OpenAPI
- Swagger UI
- Helmet
- Express Rate Limit
Tooling
- npm workspaces
- Docker
- Docker Compose
├── backend/ # Express API
├── frontend/ # React application
├── libs/
│ └── common/ # Shared contracts and validation schemas
├── docker-compose.yml
├── package.json
└── README.md
cp .env.example .env
npm install
npm run devdocker compose up --buildAfter startup:
- Frontend: http://localhost:8080
- Backend: http://localhost:3000
- Swagger UI: http://localhost:3000/docs
| Method | Path | Purpose |
|---|---|---|
GET |
/api/items/available |
Left panel - cursor pagination: ?cursor&limit&search |
GET |
/api/items/selected |
Right panel - offset pagination: ?offset&limit&search |
POST |
/api/items |
Idempotent batch insertion of new IDs |
POST |
/api/selection/mutations |
Batched select, deselect, and reorder operations |