Small full-stack calculator built as a take-home submission. The app has a React + TypeScript frontend and a Go backend. The frontend renders a calculator UI and sends structured calculation requests to the backend, which remains the source of truth for arithmetic and validation.
For the scoped product definition, see docs/PRD.md.
For representative AI planning and implementation prompts, see docs/AI_PROMPTS.md.
- Frontend: React 19, TypeScript, Vite, Tailwind CSS
- Backend: Go,
net/http - Frontend tests: Vitest
- Backend tests:
go test
Current backend and UI wiring support:
- Addition
- Subtraction
- Multiplication
- Division
- Power
- Square root
- Percentage
The UI follows an immediate-execution calculator model.
Examples:
2 + 2 =displays42 + 2 +displays4and prepares the next addition2 + 2 + 2 =displays62 + 3 × 4 =displays20, because chained operations resolve immediately:(2 + 3) × 49 + 16 √ =displays13, because√applies to the currently displayed operand:9 + √1610 %displays0.1, because percentage meansx / 1008 ÷ 0 =displays a recoverable error
Prerequisites:
- Node.js 20+ and npm
- Go 1.26+
From the repo root, create the frontend environment file:
echo "VITE_API_BASE_URL=http://localhost:8080" > frontend/.envInstall frontend dependencies:
cd frontend
npm installBackend:
cd backend
go run .Runs on http://localhost:8080.
Frontend:
cd frontend
npm run devRuns on http://localhost:5173.
Docker is provided as an optional convenience for local review.
docker compose up --buildServices:
- Frontend:
http://localhost:5173 - Backend:
http://localhost:8080
Backend:
cd backend
go test ./...
go test ./... -coverFrontend:
cd frontend
npm test
npm run typecheck
npm run test:coveragePOST /api/calculate
Example request:
curl -X POST http://localhost:8080/api/calculate \
-H "Content-Type: application/json" \
-d '{
"operation": "multiply",
"operands": [6, 7]
}'Example success response:
{
"result": 42
}Example error response:
{
"error": {
"code": "DIVISION_BY_ZERO",
"message": "Cannot divide by zero."
}
}- The backend owns arithmetic and validation. The frontend does not compute results locally.
- The frontend uses a reducer for pure state transitions and a controller hook for async API orchestration.
- The calculator follows an immediate-execution model rather than expression parsing or operator precedence.
- Scope is intentionally tight for the take-home: one page, one API endpoint, focused tests, and no history, memory keys, keyboard shortcuts, or advanced calculator features.
For fuller scope and acceptance criteria, see docs/PRD.md.
