Categories: Project Management, Leadership, Frontend, Backend, DevOps, Nonprofit, Technical Writing
Tools: Figma, Astro, Vitest, Cypress, GitHub Actions, Netlify
- Manuel Osorio — Technical Project Manager, Lead Software Engineer
- Jean Fernandez — Co-lead Software Engineer
- Allison Lejune — Data Security & Compliance Engineer
- Andres Jimmy — QA Engineer
- Axel Diaz — Front End Developer
- Calvin Chaparro — Software Engineer
- Ethan Plaza — Software Engineer
- Gabriel Hernandez — QA Engineer
- John Collins — Brand Identity Designer
- Raymond Ynoa — API Integration Engineer
- Zohaib Ahmadzai — Software Engineer
Client Brief
What: A web app designed to help lower-income families access fresh food in food deserts.
Where: Downtown and central Orlando.
Why: To ease access to nutritious food for underserved communities.
Long-Term Goals: Improve access to fresh food and track available pantry resources.
Relation to Project: NourishMap aligns with the goal of empowering food-insecure communities by providing a direct tool for discovering food resources.
Project Overview
NourishMap is a web application that helps users find food markets and pantries in the City of Orlando. The app also includes a recipe book with healthy meal ideas. My team consisted of 9 other developers with varying skill sets allowing my co-lead (Jean) and I to assign tasks accordingly. The goal of the project was to provide a valuable resource for the community and promote healthy eating habits.
My Role
As the Technical Project Manager and Lead Software Engineer, I managed the project lifecycle, led the development team, and ensured the project met deadlines and stayed within budget. My role, also included designing the project architecture, writing code, and testing to ensure a high-quality product. I regularly met with stakeholders to gather requirements, update them on progress, and addressing concerns as they came up. I met with Jean each week to plan out the weekly team meetings, and to discuss upcoming features. One of the most rewarding aspects was working one-on-one with my team members to help them grow as developers. My focus throughout was to support the team with the resources needed to complete the project successfully.
Challenges
Throughout the development of the project we faced several challenges, one of the biggest being not having a budget to work with on the project. We instead had to rely on free tools and resources to build the web app. Through our initial planning phase we performed a requirements' analysis. The three requirements that kept coming up was the need of a some type of interactive map, ability to find food products, and provide recipes that promote healthy eating while meeting dietary, budget restrictions.
Branding
The branding was a more recent addition to the project. Throughout the duration of working on NourishMap we didn't have a brand identity or even a name leaving it with the placeholder of "Food Market App". I eventually came up with the name as a play on the word "Nourishment". I brought in John Collins to help with the branding and he came up with the logo and color scheme. The initial idea was to have the logo be a map marker in the shape of a carrort along side a map. John was able to take that idea and when creating the wordmark logo while incorporating the a stylize carrot that functions as a map marker while being the "i" in NourishMap.
Logo Design
Colors
#1F271B
rgb(31,39,27)
#FBFEFB
rgb(251,254,251)
#C0C0C0
rgb(192,192,192)
#5D595F
rgb(93,89,95)
#F68837
rgb(246,136,55)
#80C144
rgb(128,193,68)
Project Architecture
NourishMap was developed in monorepo-esque fashion but reality this is possible because of the underline technology that we ended up using. The use of astro allowed for us to mix SSR (Server Side Rendering) & SSG (Static Site Generation). With SSG enable were also able to set up our api end-points and database systems.
Frontend Systems
Our frontend pulls data from our internal API and interfaces with a third-party API to display the locations of food markets and pantries on a map. We kept the design simple and user-friendly to make it easy for users to find the information they need. While Astro is a static site generator they also have a server side rendering feature that made it easy to create a static site has dynamically populated components.
Backend Systems
Astro allowed us to build a simple yet extensive backend system. One of features I implemented was a user authentication that allowed for the creation of new user accounts and session management. With in that system I also created a role based permission system so the primary stakeholders could manage the site without having to worry about the technical details of the site. I worked closely with members of the team to implement some of the other features such the contact and location APIs.
Database Systems
For our relational database we used the AstroDB library which allowed us to build and deploy a libSQL database. During the period of our project we used their now deprecated platform, Astro Studio, which I recently migrated to Turso. We created and use the following schema:
classDiagram
class Role {
+id: text
+name: text
+canManageUsers: integer
+canManageRoles: integer
+canManageMarkets: integer
+canViewContactFormLogs: integer
+canManageProducts: integer
}
class User {
+id: text
+name: text
+email: text
-password: text
+verified: integer
+role: text
}
class EmailVerification {
+id: text
+userId: text
+expiresAt: integer
-token: text
}
class Market {
+id: text
+name: text
+address: text
+lat: integer
+long: integer
}
class Products {
+id: text
+name: text
+price: integer
+description: text
+image: text
+marketId: text
}
class ContactFormLog {
+id: text
+body: text
+created: text
}
class Session {
+id: text
+userId: text
+expiresAt: integer
}
class Recipes {
+id: text
+query: text
+data: text
}
%% Relationships
User --> Role : "role"
EmailVerification --> User : "userId"
Products --> Market : "marketId"
Session --> User : "userId"
Testing
We used Vitest and Cypress for our test suites. This allowed for use to quickly create unit tests and integrate end-to-end testing. We adapted a test-driven development (TDD) methodology was tests were fully setup to prevent introducing new bugs to the production site. Since we were using AstroDB (and drizzle), a local database (found in .astro/content.db) is regenerated each time the server is run. This allowed us to create a seed file that would populate the database with needed data, and the cypress (e2e) test would run against that data. Similarly, we used vitest to mock api controllers and front end components.
Locations API Handlers:
flowchart LR
A[Session Validation] -->|Valid Session| B[Check Permissions]
A -->|No Session| C[Return 401: Unauthorized]
B -->|Permission Granted| D[Proceed to Action]
B -->|Permission Denied| E[Return 401: Unauthorized]
Products API Handlers:
sequenceDiagram
participant User
participant API_Handler
participant Database
User->>API_Handler: GET /products
alt Products found
API_Handler->>Database: SELECT * FROM Products
Database->>API_Handler: [products data]
API_Handler->>User: 200 OK, [products data]
else No products found
API_Handler->>User: 404 Not Found, {message: "No products found"}
end
User->>API_Handler: POST /products (create product)
alt Product created successfully
API_Handler->>Permission: hasPermission(canManageProducts)
Permission->>API_Handler: true
API_Handler->>Database: INSERT INTO Products (...) VALUES (...)
Database->>API_Handler: success
API_Handler->>User: 200 OK, {message: "Product created"}
else Missing required fields
API_Handler->>User: 400 Bad Request, {error: "Missing required fields", fields: {...}}
end
User->>API_Handler: PUT /products/:id (update product)
alt Product updated successfully
API_Handler->>Permission: hasPermission(canManageProducts)
Permission->>API_Handler: true
API_Handler->>Database: UPDATE Products SET (...) WHERE id = :id
Database->>API_Handler: success
API_Handler->>User: 200 OK, {message: "Product updated"}
else Missing required fields
API_Handler->>User: 400 Bad Request, {error: "Missing required fields", fields: {...}}
end
User->>API_Handler: DELETE /products/:id
alt Product deleted successfully
API_Handler->>Database: DELETE FROM Products WHERE id = :id
Database->>API_Handler: success
API_Handler->>User: 200 OK, {message: "Product deleted"}
else Missing required fields
API_Handler->>User: 400 Bad Request, {error: "Missing required fields"}
end
Contact Us Page Test:
sequenceDiagram
participant User
participant Browser
participant Server
User->>Browser: Opens Contact Us page
Browser->>Server: Sends GET request to /contact
Server-->>Browser: Sends HTML form
Browser->>User: Displays form
User->>Browser: Fills out form and clicks submit
Browser->>Server: Sends POST request with form data
Server->>Database: Stores form data
alt Success
Server-->>Browser: Sends success message
Browser->>User: Displays success message
else Failure
Server-->>Browser: Sends error message
Browser->>User: Displays error message
end
Authentication Tests:
sequenceDiagram
participant User
participant API_Handler
participant Database
User->>API_Handler: POST /auth/signup
API_Handler->>Database: INSERT INTO Users (...) VALUES (...)
alt Signup successful
Database->>API_Handler: success
API_Handler->>User: 200 OK (redirect to login page)
else Signup failed (e.g., email already exists)
Database->>API_Handler: error
API_Handler->>User: 400 Bad Request, {error: "Signup failed"}
end
Sign In
sequenceDiagram
participant User
participant API_Handler
participant Database
User->>API_Handler: POST /auth/signin (email, password)
API_Handler->>Database: SELECT * FROM Users WHERE email = :email
alt User found and password matches
Database->>API_Handler: [user data]
API_Handler->>User: 200 OK (redirect to homepage or dashboard)
else User not found or password incorrect
Database->>API_Handler: null
API_Handler->>User: 401 Unauthorized (redirect to login page with error message)
end
Deployment
The deployment process for the most part straight forward. We used Netlify and Turso (recently migrated from now deprecated Astro Studio). Whenever a pull request is made netlify would build a preview and a GitHub action that was set up for AstroDB would check if the database migrations introduced (if any) were possible. Assuming all integration were successful and the PR was approved by at least one team member and lead engineer, it can be merged to the master branch and would trigger a production deployment.
Lessons Learned
I jumped at the opportunity to be able to lead a team. I've had prior leadership experience leading several teams at a time for small scale project where I had the role of "Art Director". I also spend sometime as a student leader for a graphic design centered club. With this project I was able to bring in all my past leadership and freelance experience together to facilitate the success of the project.
During the duration of this project there was quite a bit to learning about leading a software project. One of the most important things was the importance of delegating. During the last week of the design phase, I set up all the tools we're going to be using and setup some basic user authentication. Once the team was fully onboarded with all our tools, I was able to start assigning tasks using GitHub issues and project boards. The tasks were usually broken down and the team members were split into pairs to work on them allowing them to work together and learn from each other. This also made it easier for me to having smaller standups with the team to see how they were progressing and if they needed any help, and gave me more time to focus on the project as a whole.
Results
While we were unable to complete all the goals for the project we were able to lay the groundwork for future capstone students that would pick up the project were my team left off. At the end we created an extensive documentation that served as the project handoff and something that the stakeholders can reference when approving any requirements that is within budget.
Acknowledgements
I would like to thank my team for their hard work and dedication to the project. I would also like to thank Lauren and Mike from the City of Orlando's Sustainability/Future-ready City Initiative for your support throughout the project, making this possible for CTSD Capstone students at Valencia College. And Professor Walauskis, thank you for the encouragement not just throughout my time in the Summer Capstone Project but also throughout my time in the CTSD Program. You were a major factor in reigniting my joy for learning and coding.