A REST API built with Node.js, Express.js, and MySQL to manage school data — add schools and retrieve them sorted by proximity to any location.
school-management-api/
├── api/
│ └── index.js # App entry point
├── src/
│ ├── db.js # MySQL connection pool
│ ├── routes/
│ │ └── schools.js # API route handlers
│ └── validators/
│ └── school.js # Input validation
├── .env # Environment variables (never commit this)
├── .gitignore
├── vercel.json # Vercel deployment config
└── package.json
Make sure you have these installed:
git clone https://github.com/YOUR_USERNAME/school-management-api.git
cd school-management-apinpm installDB_HOST=localhost
DB_PORT=3306
DB_USER=root
DB_PASSWORD=your_mysql_password
DB_NAME=school_managementmysql -u root -pCREATE DATABASE IF NOT EXISTS school_management;
EXIT;The
schoolstable is created automatically on the first API call — no manual SQL needed.
npm run devServer runs at: http://localhost:3000
git add .
git commit -m "initial commit"
git push -u origin main- Go to railway.app and log in with GitHub
- Click New Project → Add a service → Database → MySQL
- Once provisioned, click Add a service → GitHub Repo → select this repo
- Go to your Node.js service → Variables tab and add:
| Key | Value |
|---|---|
DB_HOST |
from Railway MySQL MYSQLHOST |
DB_PORT |
from Railway MySQL MYSQLPORT |
DB_USER |
from Railway MySQL MYSQLUSER |
DB_PASSWORD |
from Railway MySQL MYSQLPASSWORD |
DB_NAME |
from Railway MySQL MYSQLDATABASE |
- Go to Settings → Networking → Generate Domain
Your live URL will look like:
https://school-management-api-production.up.railway.app
GET /
Response:
{ "message": "School Management API is running." }POST /addSchool
Request Body (JSON):
{
"name": "City Montessori School",
"address": "Lucknow, Uttar Pradesh",
"latitude": 26.85,
"longitude": 80.94
}Validation Rules:
name— required, non-empty stringaddress— required, non-empty stringlatitude— required, number between-90and90longitude— required, number between-180and180
Success Response 201:
{
"success": true,
"message": "School added successfully.",
"data": {
"id": 1,
"name": "City Montessori School",
"address": "Lucknow, Uttar Pradesh",
"latitude": 26.85,
"longitude": 80.94
}
}Validation Error Response 400:
{
"success": false,
"errors": ["latitude must be a valid number between -90 and 90."]
}GET /listSchools?latitude={lat}&longitude={lon}
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
latitude |
float | Your current latitude (e.g. 26.4499) |
longitude |
float | Your current longitude (e.g. 80.3319) |
Success Response 200:
{
"success": true,
"count": 2,
"user_location": {
"latitude": 26.4499,
"longitude": 80.3319
},
"data": [
{
"id": 2,
"name": "City Montessori School",
"address": "Lucknow, UP",
"latitude": 26.85,
"longitude": 80.94,
"distance_km": 88.4
},
{
"id": 1,
"name": "Delhi Public School",
"address": "Sector 45, Noida",
"latitude": 28.56,
"longitude": 77.36,
"distance_km": 406.1
}
]
}Schools are sorted from nearest to farthest using the Haversine formula.
- Open Postman
- Create a new Collection named
School Management API - Add the following requests:
Request 1 — Add School
- Method:
POST - URL:
http://localhost:3000/addSchool - Body → raw → JSON
Request 2 — List Schools
- Method:
GET - URL:
http://localhost:3000/listSchools - Params tab → add
latitudeandlongitude
Replace http://localhost:3000 with your Railway URL when testing the live deployment.
| Command | Description |
|---|---|
npm run dev |
Start server with nodemon (auto-restart on changes) |
npm start |
Start server normally (used by Railway) |
The schools table is auto-created on first request:
CREATE TABLE IF NOT EXISTS schools (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
address VARCHAR(255) NOT NULL,
latitude FLOAT NOT NULL,
longitude FLOAT NOT NULL
);Schools are sorted using the Haversine formula, which calculates the great-circle distance between two points on Earth given their latitude and longitude. The result is returned as distance_km in each school object.
Shivansh Singh