A Platform Built Around Action

WaterBear is a free streaming service with a specific mission: pairing award-winning environmental documentaries with direct calls to action. The platform’s catalog covers topics from wildlife and climate change to human rights and community stories, drawing on original productions as well as content from partners like Greenpeace, WWF, The Jane Goodall Institute, and the Ellen MacArthur Foundation.

The key differentiator comes after the credits roll. Rather than leaving viewers as passive consumers, WaterBear integrates options to sign petitions, donate, volunteer, or adopt more sustainable habits. Recognizing that powerful stories often inspire viewers to want to contribute, the platform actively works to transform that inspiration into engagement.

Project Scope And Goals

Working with the agency Q Agency, the WaterBear team set out to completely rebuild the web and mobile applications from scratch. The original app launched in December 2020, and user feedback from that first iteration shaped the design and feature set of the new version. The primary objectives were defined as follows:

  • Develop a responsive web app and mobile apps with a modern technology stack based on the team’s new design.
  • Provide internal tools for easily building and customizing landing pages for campaigns and promotional content.
  • Address performance bottlenecks early in the development cycle.
  • Implement dynamic, server-side generated sitemaps to improve SEO.
  • Maintain an agile process for iterating on features based on ongoing user feedback.

Choosing The Core Technologies

The project’s infrastructure and most of the back-end services were predetermined, leaving the front-end and mobile technology decisions open. The team selected Next.js for the web application and Flutter for the mobile apps on Android and iOS, with work split across dedicated teams for each platform.

Next.js was chosen primarily for its support of dynamic server-side rendered sitemaps and its built-in optimizations for images and JavaScript bundles. The remaining integral parts of the technical infrastructure were set:

  • Sanity CMS: An open-source headless CMS that integrates with the front-end frameworks.
  • Firebase Authentication: Back-end service supporting social media logins and email/password authentication.
  • Cloud Firestore: A NoSQL cloud database selected for its compatibility with Firebase Authentication.
  • Video.js: An open-source video player with a customizable UI and plugin support.

Managing Cross-Platform Consistency

With both the web and mobile apps interacting with the same back-end services, a significant early hurdle was ensuring they behaved identically. For instance, CMS queries had to filter and sort videos in the exact same order across both platforms, and the integration with Cloud Firestore needed consistent value types and fields.

The team put communication and documentation front and center. Developers used the Firebase Local Emulator Suite for day-to-day work, facilitating fast iteration without touching live data. Regular video calls and Slack messages kept the distributed teams aligned on integrations and feature queries.

A detailed database diagram was maintained as a single source of truth, clearly documenting the structure and value types. This documentation proved more valuable than originally expected: it eliminated ambiguity and eased the transition from the local emulator to staging and then production databases, resulting in fewer integration bugs. Beyond its immediate utility, the same documentation serves as a practical onboarding guide for developers joining the project later.

Setting The Bar As A First-Time Lead

This project was my first assignment as a lead developer, a role that most developers are thrown into without formal preparation. The learning curve is steep, and you have to adapt quickly based on your own instincts and experience. The day-to-day work becomes more managerial: you are accountable for the team’s output, you mentor individual members, and you advocate for the team’s priorities. This happens while you are also more directly involved in planning and client communication. It is a lot of added responsibility, and it can feel overwhelming.

Rather than burying myself in development work, I decided to approach the role deliberately by setting rules and guiding principles for myself. Here is how I put those into practice.

Leading By Example And Mentoring On The Fly

My first goal was consistent code quality across the board, with a priority on performance, accessibility, SEO, and usability — I refer to these as The Four Pillars. People find it easier to follow well-established, documented footsteps, so these pillars were emphasized during team check-ins, demos, and reviews. I set expectations through my own pull requests by asking the team to review my work against those principles.

At the start, I asked the team to scaffold the project and complete basic integration tasks using existing documentation. That gave me room to chart the path forward by working on feature tasks that established the foundation of the pillars. When the team reviewed those PRs, they saw the quality bar I was pursuing. This approach let me lead by example — the team should expect the same level of quality from me that I expect of them.

It also allowed me to mentor the team on the fly. I could share resources and documentation in the PRs, and the team grew their knowledge by requesting changes to my work. I managed to introduce new concepts seamlessly, and my takeaway is simple: use every opportunity to share knowledge and support the team’s learning by setting good examples aligned with clear expectations.

Acting As The Tiebreaker

During my introduction to the role, I read Alex MacCaw’s The Manager’s Handbook, which helped me handle a difficult decision early in the project. During a meeting with the mobile team about our shared database architecture, some members proposed a radical approach to structuring a crucial part of the database. It didn’t sit well with me or others — it wasn’t documented or standard practice within the company. We would have to commit to it, and rolling back would be costly. The only evidence was a small-scale proof of concept, far from what we needed, but the idea’s advocates were adamant.

It was my call, and a specific passage from the book came to mind:

“Don’t let people pressure you into decisions you don’t believe in. They’ll hold you responsible for them later, and they’ll be right. Decisions are your responsibility.”

I stepped back and outlined the possible risks and rewards. It sounds simple, but it clarified the debate and led me to conclude that venturing into the unknown wasn’t worth it. I made my final decision and explained my reasoning at our next internal meeting. I made sure to give props to the team members who came up with the idea — maintaining an inclusive atmosphere where everyone feels heard and free to explore new ideas is important.

Rejecting or postponing an idea shouldn’t be viewed as negative; it’s part of building a high-quality product, which was our primary goal.

Saying “No” While Offering A Compromise

In that story, I also offered the team members a compromise: present their idea to their team lead and explore its potential in a dedicated test project.

This principle carries over to client and stakeholder communication. With Agile methodologies, clients commonly propose ideas mid-project. But you still need to avoid overcommitting and pushing the team to its limits — or carrying all the extra work yourself. A lead developer acts as an advocate for the team, which means knowing when to say “no” to requests, especially those that would make the team’s work clearly difficult or stressful.

Saying “no” might seem cold, but you can always acknowledge the suggestion and offer a compromise. Some real-world examples:

  • Decreasing the scope — “We might not finish X, Y, and Z in time to meet our deadlines. That said, we only need X at this stage, and perhaps we can postpone Y and Z to the next phase.”
  • Postponing — “We can’t spare the time for X at this stage, but it’s a great suggestion; we should note it even though we need to postpone it.”
  • Switching priorities — “If X is a high priority and should be done this sprint, can we postpone a lower-priority task so we can dedicate enough time to finish it?”

Rebecca Knight’s principles on saying “no” have resonated with me:

Do:
  • Evaluate whether you have the desire and bandwidth to help, and ask if priorities can be shifted or trade-offs made.
  • Show a willingness to pitch in by asking if there are small ways you can be helpful.
  • Practice saying no out loud; it gets easier.
Don’t:
  • Use a harsh or hesitant tone, or be overly polite. Strive for a steady, clear no.
  • Hold back the real reason. Give reasons with good weight up front.
  • Distort your message or act tentatively to keep a colleague happy. Be honest and make sure your no is understood.

Communicate With Empathy And Clarity

This connects to all the previous points. Building and maintaining mutual trust within a team is crucial. During internal sprint meetings, I would go over each feature, clear doubts and blockers, and confirm whether anyone had concerns about their tasks. A team member might have little experience with a service they are integrating and feel unsure they can complete it. Or they might have a personal conflict that could delay their work and needs your assistance.

Team members should feel free to speak up and share concerns without judgment or repercussions. That lets you plan, adapt, and solve problems early, and it eases the stress and frustration that stall progress.

Smashing Editorial