A production-ready Next.js application that calculates rental subletting scenarios by auto-filling one unknown variable among rent, price per room, reserved rooms, target profit, and total rooms.
- Smart Calculator: Automatically solves for any one unknown variable (R, P, S, K, N)
- Real-time Results: Instant calculations with profit analysis and target validation
- URL State Management: Shareable URLs that preserve calculator state
- Responsive Design: Clean, modern UI built with TailwindCSS
- Type Safety: Full TypeScript implementation with strict mode
- Comprehensive Testing: Vitest test suite covering all calculation scenarios
- R: Monthly rent + all expenses (€)
- P: Average monthly rent per rentable room (€)
- S: Rooms reserved for you (integer)
- K: Target monthly profit after expenses (€)
- N: Total number of rooms in property (integer)
- Node.js 18+
- pnpm (recommended) or npm
# Clone or navigate to the project directory
cd sublet-calc
# Install dependencies
pnpm install
# or
npm install
# Start development server
pnpm dev
# or
npm run dev
Open http://localhost:3000 to view the application.
# Build for production
pnpm build
# or
npm run build
# Start production server
pnpm start
# or
npm start
# Run tests
pnpm test
# or
npm test
# Watch mode
pnpm test:watch
# or
npm run test:watch
- Monthly rent: €3,500
- Price per room: €725
- Reserved rooms: 2
- Target profit: €1,500
- Result: Need 9 total rooms (profit: €1,575)
Shareable URL: http://localhost:3000/?R=3500&P=725&S=2&K=1500&unknown=N
- Monthly rent: €3,500
- Total rooms: 8
- Reserved rooms: 2
- Target profit: €1,500
- Result: Need €833.33 per room
Shareable URL: http://localhost:3000/?R=3500&S=2&K=1500&N=8&unknown=P
- Monthly rent: €4,500
- Price per room: €725
- Reserved rooms: 2
- Target profit: €1,500
- Result: Need 11 total rooms (profit: €2,025)
Shareable URL: http://localhost:3000/?R=4500&P=725&S=2&K=1500&unknown=N
- Pure functions for all calculations
- Zod schema validation
- Comprehensive error handling
- Money formatting utilities
- Reusable, accessible components
- Consistent styling with TailwindCSS
- TypeScript interfaces for all props
- Client-side calculator with React hooks
- URL state synchronization
- Real-time form validation
- Responsive layout
When exactly one variable is unknown:
- N unknown:
N = ceil(S + (R + K) / P)
- P unknown:
P = (R + K) / (N - S)
(requires N - S > 0) - R unknown:
R = (N - S) * P - K
- S unknown:
S = floor(N - (R + K) / P)
(minimum 0) - K unknown:
K = (N - S) * P - R
- N (total rooms): Rounded up to ensure profit ≥ target
- S (reserved rooms): Rounded down when derived, with warning
sublet-calc/
├── app/
│ ├── globals.css # Global styles
│ ├── layout.tsx # Root layout with SEO
│ └── page.tsx # Main calculator page
├── components/ui/ # Reusable UI components
│ ├── alert.tsx
│ ├── badge.tsx
│ ├── button.tsx
│ ├── card.tsx
│ ├── field.tsx
│ ├── number-input.tsx
│ └── radio-group.tsx
├── lib/
│ ├── __tests__/
│ │ └── calc.test.ts # Test suite
│ └── calc.ts # Core calculation logic
├── package.json
├── tailwind.config.js
├── tsconfig.json
└── README.md
- TypeScript: Strict mode enabled
- ESLint: Next.js recommended rules
- Prettier: Consistent code formatting
- Testing: Comprehensive vitest test suite
- SEO: Meta tags, Open Graph, Twitter cards
pnpm dev # Start development server
pnpm build # Build for production
pnpm start # Start production server
pnpm lint # Run ESLint
pnpm test # Run tests
pnpm test:watch # Run tests in watch mode
-
Connect Repository
- Connect the
zakaryayev/sublet-calc
repository to Vercel - Framework will auto-detect as Next.js
- No special environment variables needed
- Connect the
-
Verify Deployment
- After deployment, note your Vercel host (e.g.,
sublet-calc.vercel.app
) - Test that
/sublet-calculator/
works correctly - Verify health check at
/sublet-calculator/health
- After deployment, note your Vercel host (e.g.,
To serve the app at zakaryayev.com/sublet-calculator
:
-
Deploy Cloudflare Worker
- Go to Cloudflare Dashboard → Workers & Pages → Create Worker
- Copy-paste contents from
cloudflare/worker.js
as a Module worker - Update
backendHost
to your actual Vercel URL - Deploy the worker
-
Add Routes
- In worker settings → Triggers → Routes, add:
zakaryayev.com/sublet-calculator*
www.zakaryayev.com/sublet-calculator*
(if using www)
- In worker settings → Triggers → Routes, add:
-
DNS Configuration
- Ensure DNS root record is orange-cloud proxied in Cloudflare
For detailed setup instructions, see cloudflare/README.md
.
The basePath: '/sublet-calculator'
configuration ensures:
- All assets (
_next/*
) are properly prefixed - Internal routing works behind reverse proxy
- No hardcoded absolute paths break the subpath deployment
- Modern browsers with ES2020+ support
- Mobile responsive design
- Accessible keyboard navigation
We deploy TWO Vercel projects from the same repo:
A) Root under path:
- Project name:
sublet-calc-root
- Custom Domains:
zakaryayev.com
(Cloudflare Worker proxies/sublet-calculator*
) - Vercel ENV:
NEXT_PUBLIC_BASE_PATH=/sublet-calculator
B) Clean subdomain:
- Project name:
sublet-calc-sub
- Custom Domain:
sublet-calculator.zakaryayev.com
- Vercel ENV:
NEXT_PUBLIC_BASE_PATH=
(empty)
Preview domains (*.vercel.app
) are set to noindex
via vercel.json
.
This project is built for demonstration purposes. Feel free to use and modify as needed.