How to kick off a new software project. Lead your team's engineering initiative.
Software engineer's and CTO's perspectives
I’m excited to announce a special edition of Build Bytes!
This article is written in collaboration with Gregor Ojstersek. Gregor is a talented CTO with years of experience in the tech industry.
His articles about team processes have been truly eye-opening for me. If you’re a software engineer looking to learn tech management skills, be sure to check out Gregor’s newsletter, Engineering Leadership.
What will you learn?
Let’s say you’ve been working as a developer for a few years, and now you’re given an initiative at work to kick off a new project. Brand new, fresh project. No legacy business logic, and no old technologies. A free field to show off what you’ve learned in other projects.
Where do you start? How do you pick technologies? How do you establish communication with your stakeholders?
In this article, we’ll share tactics and strategies to help you do exactly that.
Chapter 1: Understand the project deeply, before starting with the implementation
Ask as many questions as possible.
It’s essential to ask as many questions before you start with the project. Jumping straight into code may not contribute to the best possible outcomes. Knowing the business reasons and motivation behind it will ensure you make the right technical decisions along the road.
Start with business-oriented questions. Here are some questions that can help you to understand the reasons behind the project (credit to Pawel Huryn):
Why are we building this?
Why are we building it now?
For whom are we building it?
What’s the unique value of this product?
How is it aligned with the company’s vision?
How is it aligned with the business strategy?
How will it affect our customers and users?
How will it create value for the business?
How can we make sure that our customers would love it?
Can our business support it (e.g., legal, finances)?
How can we bring it to the market?
Should we do it at all?
These questions should be asked of the stakeholders of the project.
Chapter 2: Architecture
Whenever you code, you're coding inside an architecture. You can think of developing as preparing furniture for a room. Each room belongs to a building, and the way the building is structured (hallways, fire exits, floors, elevators, parking lot) is the architecture.
Architecture should be dictated by the business problem you’re trying to solve
Code is only written to solve problems. Naturally, it should reflect the problem your app is aiming to solve.
When choosing architecture you can start with the following questions:
What will the app do for the user? Who is the user of the app?
What roles can the user have? User, admin, guest?
Are you building a brand-new system? Is it a “green field“ project? Or are you building on top of existing functionality? Do you need to integrate an old API into the new system?
Do you or someone on your team have domain knowledge or experience in the industry you’re building a project in? Talk to them. Software reflects the real world, so there’s a decent chance that the mental models they’ve used will be similar to the ones you will need to use.
For illustration, this article discusses a headless architecture with a software team divided into two sub-teams (back-end and front-end).
Both teams work in separate codebases and communicate through a REST API. This is a typical architecture that many modern web apps use. The advantage of such architecture is that each sub-team can move independently and work with technologies that best suite their needs.
Cheatsheet for picking technologies
Here’s a complete list of factors I would consider when selecting a technology for a project:
Adoption level
A large GitHub Star Amount can be a great indicator of broad adoption.
High adoption level ensures you’ll have more third-party learning resources if you encounter issues.
Large Company Backing (e.g. Meta's React.js, Google's GoLang, etc).
If a large company uses the technology, many edge cases will be discovered by developing the company’s features. Use that to your advantage.
How well is the technology adopted at your own company? Are your colleagues familiar with it? Have you built up some know-how in other projects you’ve worked on together?
Active open-source community
Fast GitHub Issue response time.
Active Discord/Slack Community.
If you run into issues that don’t have solutions on Stack Overflow or the official docs, will you get them answered fast?
Broad 3rd party library support, diverse ecosystem.
Excellent quality of technical documentation.
Several-year track record.
Let the technology cook. Don’t be one of the earliest adopters for a production project. Playing around with the most bleeding-edge technologies for personal projects is fine, but if you’re taking the initiative at work, use something well-tested.
Strong engineers in the core team for the technology.
A mechanism for the community to submit proposals to the core team
No great technology ever stays the same. It has to evolve. If you look at some of the web’s most powerful technologies, like JavaScript or PHP, they all have a proposal acceptance process.
A real-world tech stack for a web app project
Here’s a technology stack that has worked well for several large projects I’ve worked on.
Back-end:
Language: PHP
Database: MySql
Framework: Symfony
API Documentation: API Platform
Front-end:
Language: JavaScript (TypeScript syntax)
Framework: Next.js & React.js
Cache & Hydration: React Query
Global client state: Zustand
Styling: Tailwind CSS
💡 Note: you can pick different technologies for your project, but make sure that your tech stack covers all the tech stack categories.
Chapter 3: Workflows
Once your architecture and tech stack are figured out, the next step is to agree on the workflows. These include communication with a B2B client, designers, and the Dev Ops team.
But the most common workflow is communicating within the same team, usually back-end and front-end developers.
You have to nail this communication because no matter how good your tech stack is, delivering the project on time will be hard if you're stuck at the communication level.
The back-end and front-end collaboration
In an ideal world, the front-end team should have all the backend APIs prepared beforehand. However, in practice is hard to implement because some functionality might be more complex for the front-end team, while some functionality might be more straightforward for the back-end team and vice versa.
In reality, even if some functionality is developed simultaneously, it might take the back-end team longer to prepare the required changes, making the endpoint exposed to the front-end even possible.
In the meantime, the front-end team has to keep working. Otherwise, they will fall behind in the timeline once the endpoint is finally ready to be implemented in the front-end.
A process for unblocking both front-end and back-end
A solution that has worked well for me and my team is to split a project into user stories with four subtasks.
Here’re the steps for forming such tasks:
Step 1: Define the user story in non-technical language. It has to be understandable to all stakeholders like designers, project managers and clients.
User story: Checkout page
Functionality:
Specify address
Choose payment method
Adjust cart items
Step 2: Split the user story into four sub-tasks (2 front-end and 2 back-end).
Back-end task:
a) Prepare API structure
Check the design (e.g. Figma), and ensure all properties are returned.
Talk with the front-end developer, and ensure the structure works for both parties.
b) Implement business logic and provide the endpoint in the agreed API structure
Front-end task:
c) Static design implementation using the agreed API structure
Use a mock API
Match the design provided by the designer (e.g. Figma)
d) Implement the dynamic design using the final endpoint provided by the backend developer.
Step 3: Front-end and back-end developer work in parallel.
By structuring tasks in such a way, our team was able to have far fewer blockers. This is simply because all team members always have something to do.
Once you agree on a workflow and apply it to one task, you can simultaneously scale it to several user stories.
Here’s an illustration of what that would look like.
Sync back-end and front-end types. Take the collaboration to a new level
Syncing data types is a common issue when working with a headless architecture (as mentioned before, by headless, I mean having separate backend and frontend systems).
When a new feature is implemented, often, backend developers have to change existing API endpoints by adding or removing properties. Data mismatches and bugs can arise without systematically syncing these changes with the front-end codebase.
Open API + TypeScript sync solution
Syncing Open API documentation and TypeScript types is an excellent solution to this problem. Front-end developers can run a single command and have up-to-date documentation straight in their editor. This allows both teams to move faster while having a more stable and robust system.
Steps for setting up type sync:
Step 1: Create API documentation using Swagger or Open API. Here’s an example of how it looks for the open-source Sylius platform:
Step 2: Install and use the openapi-typescript
NPM package to your front-end codebase. Follow the instructions in the screenshot below.
Step 3: Use the generated types in the front-end codebase. Whenever an endpoint is changed in the back-end codebase, the “generate-types
“ command can be rerun, and TypeScript will tell which places must be updated to make back-end and front-end match.
Here’s an example of using the generated types inside the front-end codebase. Notice how my IDE suggests the possible data structures in the API docs. As mentioned, these types will also be updated if the backend team updates the API documentation.
💡 Team Communication Tip: this type sync setup is a huge productivity win for the front-end developers. However, you have to remember that maintaining the API Documentation and a correct type DTO representation in the JSON format can be additional work for the backend team.
Take your time to agree on the processes with your colleagues on who and how will maintain this setup in the back-end codebase. Invest time upfront, reap the benefits later.
Building mock JSON API
Once you agree on the backend API structure for a feature, you need a way to serve that data to the front-end. Setting up a custom server can be time-consuming and result in work that will be useless after the final endpoint is finished.
A solution to that is using the npm library called json-server
. It allows you to create simple REST APIs in seconds.
You can build your own mock JSON server by reading this documentation.
Chapter 4: Documentation
The goal of writing software is to solve problems. Solving problems requires information. Information needs to be stored such that your team members find it fast.
In my experience, the best software documentation aims to align people from the same team and increase collaboration with the other teams.
Meanwhile, software documentation that purely focuses on the technical details usually is never actually used to develop and often gets forgotten.
A great way to visualise how helpful software documentation functions within an organisation is to look at it from above as a river.
The river can have multiple smaller branches or even other rivers that flow into it. But it’s constantly flowing towards the sea.
Similarly, software and its documentation should integrate other sources like documentation from the design team and flow towards releasing software that solves real-life customer problems.
In contrast, poor software documentation visually looks like a static lake where you feel like you could drown in the technical jargon.
I find that excellent software documentation focuses on these things:
Integrating documentation from other stakeholders (product, design).
Puts delivering features for users as the priority.
It doesn’t abstract business problems with technical jargon, making reading it more challenging than needed.
They keep things simple but actionable and helpful.
Helps onboard, new team members.
Summary
This article has looked at architecture, workflows and documentation tips to help you start a new web development project.
The main takeaway is that you must completely shift your mindset when given the initiative to kick off a new software project. In addition to thinking about how to code a feature, you must also consider how to plan and communicate with your teammates.
In other words, you have to go from a person who only writes code, to a person who:
Writes about the advantages/disadvantages of possible architectures.
Writes workflow documents for your team.
Writes software documentation.
Thanks for reading, and see you next time!
Further reading
It’s been a blast working with Gregor on this Build Bytes issue! If you haven’t already, go and subscribe to his Engineering Leadership newsletter.
It was a pleasure collaborating with you on this Rutenis!
It's amazing how in-depth this goes and how helpful this type of article is for people especially earlier in their careers.
Great collaboration guys!