DEV Community

Cover image for Building Ekehi: A Contributor's Journal From Code to Coordination
Oluchi Okwuosa
Oluchi Okwuosa

Posted on • Edited on

Building Ekehi: A Contributor's Journal From Code to Coordination

Ekehi is a business resource platform for women entrepreneurs in Nigeria and across Africa. The problem it solves is real: funding exists, grants exist, credit schemes and training programmes exist, but finding them is genuinely hard, especially if you are not already connected to the right people. Ekehi puts all of that in one place. A searchable, filterable directory of funding opportunities, credit products, and training resources, built mobile-first.

We are a team of 15 people. We have a Product Lead, Engineering Lead, Design Lead, Lead Maintainer, and a Backend Lead. My role on this project is People Manager, handling workflows, team synergy, and making sure nothing falls through the cracks.


The Stack

Ekehi is built on Vanilla HTML, CSS, and JavaScript on the frontend, with
Node.js and Express.js on the backend and Supabase handling the database
and authentication. Supabase's built-in full-text search is particularly
relevant for a funding directory where users need to search and filter across
dozens of opportunities quickly. The design system uses DM Serif Text for
headings and Urbanist for body text. This was the stack we were assigned to build with.
For many of the women this platform serves, mobile is the primary device
and connectivity is not always reliable. Every technical decision on this
project sits inside that context.

For contributors, the project uses a tiered branching strategy:

  • main for stable production code
  • development as the integration branch where features come together before going live
  • feature/ branches for isolated work

Every contributor works on a feature branch, opens a pull request into
development, and waits for review before anything merges. Understanding
this flow early saved me from several mistakes.


Design

Before any frontend work began, the design team produced high fidelity screens on Figma covering all the key pages and components. Frontend development was tied directly to those designs, which meant every section had a reference to build from.
Spacing, typography, colour, and layout decisions were all specified in the Figma file and the design system. As a frontend contributor, my job was to match what was designed as closely as possible, not to make

visual decisions independently.

Sprint 1

Sprint 1 is the foundation sprint. The team was running two things in parallel: the infrastructure work that the entire product depends on, and shipping a responsive landing page as the visible deliverable for this sprint. So while the DB schema, Supabase setup, authentication, and sector taxonomy were being handled in the background, there was already something users could land on by the end of the sprint.

My frontend task was the Mission section of the landing page. The section required a centred layout with a small eyebrow label, decorative SVG petal icons positioned around the text, and a large headline, all matching a Figma design.

The technical challenge was the petal positioning. My first instinct was to put the SVG images inside a flex container alongside the text, but that made them sit too close to the text and resize awkwardly at different screen sizes. The fix was absolute positioning. By setting the eyebrow container to position: relative and positioning each petal with position: absolute, the petals float independently around the text without disrupting the layout flow. Each petal got its own class following BEM naming with top, bottom, left, and right values tuned to match the Figma design.

The project uses a utility class system similar to Tailwind for common styling, with component-specific CSS files handling anything the utilities do not cover. Styling the mission section meant using utility classes in the HTML for layout and typography, then writing targeted CSS using the project's design tokens for anything specific to the component. No hardcoded pixel values or colour codes, everything traces back to CSS custom properties defined in the design system.


Sprint 2

My task this sprint was building the filter section of the Opportunities page. This included the page header, a search bar, and five filter dropdowns which are Sector, Status, Business stage, Region, and Type, wired up so that every interaction logs the current filter state to the console. No API re-fetching yet as that is a separate issue. The goal was to establish the filter state object as a foundation for the upcoming API wiring.

The implementation used two shared components, SearchBar.create() and Dropdown.create(), that the team had already built. Each dropdown receives a label, an options array with exact API enum strings as values, and an onChange callback that updates a central filters object and logs it. The filters object lives at module scope so it will be accessible when the API wiring issue comes next.

The issue specified ES module imports rather than global script tags. This meant replacing multiple <script> tags in the HTML with a single <script type="module" src="opportunities.js"> and importing all dependencies at the top of the JS file. The shared components needed export default added to them before this worked, a small change with a meaningful impact on how the codebase scales.

Styling the filter section introduced another challenge. The Dropdown component renders its own HTML at runtime through JavaScript, which means you cannot add classes to its internal elements directly in your HTML. The fix was CSS scoping, targeting the component's internal class names through a parent BEM class I controlled:

.opportunities__dropdowns .dropdown-wrapper {
  flex: 1;
  display: flex;
}

.opportunities__dropdowns .dropdown__trigger {
  width: 100%;
  font-weight: var(--font-regular);
}
Enter fullscreen mode Exit fullscreen mode

This overrides the component's default styles only within the filter section, leaving every other dropdown on the platform untouched.


My Role as People Manager

Outside of contributing code, I handled the coordination and tooling setup for the team.

I set up our ClickUp workspace. That meant building out the Ekehi Space, creating folders for each sprint, and configuring all the custom fields: priority levels, effort sizing, MoSCoW categories, status dropdowns, owner fields, due dates. I set up the views the team actually uses day to day. Board view for a quick status snapshot, Workload view to check capacity across the team, and filtered List view to pull up blocked items fast.

I sat in on meetings across the different tracks, frontend, backend, and
design, to stay across what each team was working on and where things stood. Beyond the meetings, I was also doing direct check-ins with individuals to follow up on assigned tasks.

Our ClickUp workspace is shared across multiple teams in the organisation so everything I configured had to be scoped specifically to our Space. That required ensuring I get it right without affecting anyone else's setup.

Beyond the initial setup, the day to day management of ClickUp was also on me. That means making sure tasks are actually being updated, statuses reflect what is really happening, and owners are assigned to everything that needs one. A ClickUp board that nobody updates is useless so part of my job was consistently following up with the team to keep it current.

I was also filtering by blocked tasks regularly. Anything sitting on blocked for too long gets a follow up from me. Either something needs to be escalated, a decision needs to be made, or someone needs help and has not said so yet. That filter became one of the most useful things in the whole setup because it tells you exactly where the friction is without having to go through every single task manually.

Working with my project lead throughout the sprint meant a lot of back and forth on task progress, making sure what was logged in ClickUp matched what was actually happening and flagging anything that looked like it was falling behind before it became a real problem.


Lessons Learnt

Merge conflicts are not a crisis. They are just two sets of changes that need a decision. Understanding what each side of the conflict contains makes resolving them straightforward. The harder lesson was learning to check in with the team lead before touching shared files because a one-line addition to a shared component has implications across the whole codebase.

CSS scoping matters more than it seems when working in a shared component system. Writing styles that are too broad breaks things in places you are not looking. Writing styles scoped to your own classes keeps your work contained and reviewable.

Working with a team of 15 people across different functions taught me fast that collaboration only works when everyone is actually showing up for their part. When people do not turn in their tasks as at when due, it does not just affect their own work, it affects whoever is waiting on them downstream.

Be specific when you need something from someone. A vague request sits in someone's inbox for days. A message that says exactly what to open, what to click, and that it will take two minutes gets done the same day.

And last one: the people manager role has real work in it even during a sprint where there is nothing to demo. Keeping the team unblocked, tracking what is at risk, making sure decisions happen when they need to. That is what makes the sprints after Sprint 1 possible.

Big respect to everyone on the Ekehi team, all 15 of us. Especially our Product Lead, Engineering Lead, Design Lead, Lead Maintainer, and Backend Lead for keeping things moving. It has been a solid sprint and we are just getting started.


TEE Foundation | Tabi Project | International Women's Day Initiative | March 2026


Top comments (0)