Kamil Kołosowski

Kamil Kołosowski


Wedbliss helps couples easily find their dream wedding venue. The platform features an interactive map of expertly curated wedding venues across Poland, in which couples can adjust filters to display venues matching specified criteria.

Developed using a Lean Startup approach, the product has undergone a number of feedback-driven iterations. The following article illustrates our development approach through three stages of the product lifecycle: Discover, Build, and Drive.

The first step was to conduct an in-depth market analysis. This facilitated a refined product vision and allowed us to clearly map a series of user and business outcomes, as detailed in the Discover section.

This real-world research was invaluable, allowing the team to uncover various pain points associated with a couple’s search for their dream wedding venue. Understanding these pain points made designing and architecting our custom Wedbliss solution straightforward, as highlighted in the Build section.

Lastly, we made sure that everything was put in place for smooth and efficient maintenance of the product. In the Drive section, we underscore some of the best practices and standard industry tools used to collect key performance indicators (KPIs) to track product success.

*Note: Early feedback has indicated a considerable market interest in our product. Unfortunately, the wedding industry has been badly hit by the COVID-19 pandemic – product launch will be revisited when revenue projections recover.


The Discovery phase successfully validated and refined the product’s unique value proposition.

Our team conducted a number of small scale experiments to collect user data (i.e. surveys, interviews, content analysis, etc.). This provided early insights into user desire for a more transparent and efficient service in the early stages of their search for a wedding venue. Specifically, users were interested in shortlisting a small number of venues, based on key features such as capacity, price, location, and reviews.

At this stage, we understood what was important to the user, but had not yet formulated a final product response. We used Figma to visualize our ideas, testing prototype solutions directly with potential customers (our Figma approach is detailed further in the next section) to identify how best to meet user needs. This new feedback was then used to modify product design and the process of gathering feedback would begin again. Wireframes and early-stage designs were iterated rapidly, informed by these direct feedback loops.

This iterative design process is useful at any phase of the product lifecycle, including when a product has already been launched in the market and there is a desire to make improvements.

Key Takeaway

Using a feedback/outcome-driven framework, allowed the team to quickly establish a clear set of priorities for the platform. The process empowered the team to make leaner, faster decisions and in turn, accelerate delivery.


The Build phase defined effective processes for design and code delivery.

When building our designs, Figma is our go-to tool. It is straightforward to use, navigate, and collaborate on. Most importantly, however, it allows for great flexibility in structuring our components.

Let’s rewind here for a moment to explain what a component is.

We believe that modularity is the key to creating a flexible/Agile design system. For a system to be modular, it must have interchangeable parts. These parts are called components. Components can be as simple as an individual button, or as complex as an entire navigation header (consisting of other components like logos, buttons and menu items). Once you make something a component, you can create other instances of it, which are essentially connected copies of that component — so if you update the design of the original component, all instances will reflect that change. For example, when you need to change something, like your brand’s link color or home icon, you can make the change once (in the original main component or style) and watch it update across all your designs.

Whether in Figma or in code, components are at the core of our approach to architecting products.

However, bringing our components to life (i.e., writing code), is an exciting but error-prone process, made especially challenging when collaborating with a larger team. It is, therefore, crucial to align on processes and have a shared understanding of the system design (i.e., the architecture).

Most of our processes were defined by SCRUM – probably the most widely used project management framework for Agile development. As for the architecture, incorporating BLoC and State Machine paradigm into our solution were the two core choices that helped us effectively expand (build new features) and navigate an increasingly complex project.

BLoC stands for Business Logic Components and at its core is centered around the concept of Unidirectional Data Flow. If you’re interested to learn more check out this great article written by one of our developers explaining the concept in more detail. We recommend further reading on BLoC to fully understand its benefits. Overall, it helped us separate business logic from the presentation layer and enabled us to reuse code more efficiently.

State Machine is a computational model that consists of states and transition functions. A transition function reads an input and determines the next state. A program cannot be in two states at any given time. This makes the app’s behavior predictable and easily testable. All we have to do is come up with a finite number of states, their possible transitions, and code them up. One of our developers created a library that allows us to express states and the corresponding transitions for a given BLoC in Dart language

The tech stack can be summarized as a multiplatform Dart application, designed for code sharing between Angular Dart used for web development and Flutter used for mobile apps.

The industry is moving towards multi-platform development tools (i.e., one technology to build apps for mobile, web, desktop, and embedded devices) with Flutter at the front of such initiatives. The move is motivated by the need to cut the enormous costs involved in the development and maintenance of multiple tech stacks.

The only reason we used Angular Dart instead of Flutter on the Web is that the latter was still in its early stages of beta testing at the time of building Wedbliss. In our case, migrating Angular Dart to Flutter on the Web will be easy, since we maintain one codebase and most of the code is already shared between web and mobile (as both are written in Dart programming language).

Lastly, it is important to note our approach to designing the backend. We used Ktor and MongoDB. We chose Ktor due to its low setup costs (i.e., lightweight framework with a quick and easy setup). Another advantage was that Ktor is built with Kotlin (a much more concise language when compared to Java), and we took full advantage of Kotlin features such as lambda syntax and DSLs. As for MongoDB, there is a never-ending debate on whether you should choose SQL or NoSQL databases. The truth is, there is no silver bullet and it all depends on your use case. For us, the focus was on flexibility. We chose NoSQL MongoDB due to its schemaless nature that allowed for rapid transformations as our data needs changed. Rather than fitting an application to meet schema requirements, we allowed for experiments to define our optimal database structure.

Key Takeaway

Our component-based approach to designing and building our product allowed for quick and easy propagations of changes – saving us a lot of time when going through the numerous iterations of Wedbliss.


Coming soon.