The steady rhythm of Kairos's keyboard was a soothing sound. For two days, he had lived in the quiet, focused bubble of the campusfix-backend project. He had built the foundation: the Express server was humming, the connection to MongoDB was stable, and the User model was complete with secure password hashing and JWT token generation. It was clean, tested, and working. He felt a deep sense of satisfaction. He was building something solid.
Now, he was tackling the heart of the application: the Issue model. It was more complex than the user. It needed a title, a description, a category (plumbing, electrical, etc.), a status, the user who reported it, and most challengingly, a location and a photo.
He'd spent the morning wrestling with Mongoose schemas, defining the data types and validation.
const IssueSchema = new mongoose.Schema({
title: {
type: String,
required: true,
trim: true,
maxlength: 100
},
description: {
type: String,
required: true,
maxlength: 500
},
category: {
type: String,
required: true,
enum: ['Plumbing', 'Electrical', 'Structural', 'HVAC', 'Other']
},
status: {
type: String,
enum: ['Submitted', 'In Progress', 'Resolved'],
default: 'Submitted'
},
reportedBy: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
required: true
},
location: {
building: { type: String, required: true },
roomOrArea: { type: String },
// For future map integration
coordinates: {
lat: { type: Number },
lng: { type: Number }
}
},
imageUrl: {
type: String // This would be a link to where we store the photo
},
upvotes: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
}]
}, {
timestamps: true // This would automatically add createdAt and updatedAt fields
});
He leaned back, admiring the structure. It was elegant. It was comprehensive. Now, he needed to build the API endpoints to create, read, update, and delete these issues. He started with the POST route to create a new issue.
His phone buzzed, shattering his concentration. It was a message from Ares.
Ares: How's the API coming along? I've got the repo set up and the basic front-end structure. Ready to make our first API call soon.
Kairos: Just building the Issue model. It's a beast. Almost ready for you.
Ares: Perfect. I'm staring at a blank form component that's desperate for something to talk to.
He put the phone down, a new urgency in his movements. He didn't want to be the one holding up progress. He finished the POST route, carefully writing the middleware to protect the route and attach the user from the JWT token to the reportedBy field. He tested it using Postman, sending a JSON payload.
{"title": "Leaky Faucet", "description": "Dripping constantly in the 2nd floor west wing bathroom", "category": "Plumbing", "location": {"building": "Main Hall", "roomOrArea": "West Wing Bathroom"}}
The server responded with a 201 Created status and the new issue object, complete with its unique _id and a createdAt timestamp. Success.
Kairos: [Screenshot of the successful Postman response] Kairos:The 'create issue' endpoint is live! Go crazy.
Ares: On it.
He could almost feel her, on the other side of campus, wiring up the form to send its data to his server. He felt a thrill of connection. His code was about to talk to her code. This was the magic.
Five minutes later, his phone buzzed again.
Ares: Okay. I'm getting a 500 error. 'Internal Server Error'. Not very helpful. Your logs are probably screaming.
Kairos's heart sank. He'd been so sure it was working. He opened his terminal where the server was running. Sure enough, there was a nasty error message in red text.
TypeError: Cannot read properties of undefined (reading 'building')
He frowned. The error was pointing to his code where he tried to access req.body.location.building. But he was sure he'd sent the location object. He looked back at his Postman test. He had. It had worked.
Then it hit him. Postman. He'd sent the data as raw JSON. But what was the front-end sending?
Kairos: How are you sending the data? Is it JSON?
Ares: It's form data. There's a photo upload. You can't send a file as JSON.
He facepalmed so hard it probably echoed in the hallway. Of course. He'd been so focused on the structure of the data that he'd completely forgotten how the data would arrive. The front-end would use multipart/form-data to handle the file upload, not application/json.
His entire POST route was built to parse JSON. It couldn't handle form data. This was a fundamental, rookie oversight. The first real handoff between them, and his part was broken.
Kairos: I'm an idiot. I built it for JSON. I need to use a library like multer to handle form data and file uploads. Stand by. Fixing it now.
He expected frustration. A sigh. A hint of annoyance at the delay.
Her response was simple.
Ares: No worries. I figured it was something like that. I'll work on styling the form while you wrestle with multer. Let me know when it's ready.
No judgment. No pressure. Just calm understanding and a re-prioritization of her own tasks. It was the most supportive thing he could have imagined.
It took him an hour. He had to install multer, configure it to handle file uploads, set up a storage destination, and then rewrite his POST route to use multer's middleware to parse the form data before his own logic could use it. It was a frustrating process, full of minor configuration errors, but he finally got it.
He tested it again with Postman, this time switching the body type to form-data and adding a key for image with a test file. The server processed it, saved the image to a folder, and stored the path in the imageUrl field. It worked.
Kairos: Okay. Round two. Should be good now.
Ares: Sending…
He watched his terminal, holding his breath. The request came in. The multer middleware processed it. His function ran. It created the new issue in the database.
201 Created.
Ares: It worked! The form is submitting! I have a list of issues!
Attached was a screenshot of her front-end. It was crude, just unstyled text on a screen, but it was their data. His back-end. Her front-end. Working in harmony.
It was a small thing, a simple POST request. But in that moment, it felt like a monumental achievement. They had hit their first hurdle, and they had cleared it together without a single moment of drama. It wasn't about who was right or who made the mistake. It was about solving the problem.
Kairos looked at the screenshot on his phone, a grin spreading across his face. They weren't just planning anymore. They were building. And it was working.