07 · Construction Tech

Location-based matchmaking between property managers and construction contractors.

Solo Bubble.io MVP, three sprints, the client's testing pass came back at zero bugs. The product matches property managers to nearby contractors by specialisation and location: PMs list a project, the algorithm proposes contractors, the platform invites bids, the PM finalises one. Built on the AirDev Canvas framework.

The Construction Marketplace splash illustration with the line: Construction Market is a web application where construction companies can bid for projects submitted by construction customer

Tech-literate founders who hired me for execution, not judgment

Construction Marketplace lives at constructionmarket.io. A property manager lists a project. The platform’s matchmaking algorithm proposes nearby contractors whose specialisations match the project’s scope. Those contractors get invited to bid. The PM reviews the bids, opens a thread with the contractors they want to talk to, and finalises one. The model is small, deliberate, and the entire product wraps tightly around it.

I came onto the project through Upwork in January 2024. The founders were established software developers themselves; they did not need me to make product calls. They needed someone who could turn a precise specification into a working Bubble.io app on the AirDev Canvas framework, document the build alongside writing it, and pass their independent testing team’s cases on the first run. The engagement ran across three sprints in 2024, with gaps between for the founder’s wider business operations.

AirDev Canvas: the starting point, not the destination.

The clients chose AirDev Canvas as the framework before I joined. Canvas is a Bubble.io scaffolding kit that ships a working auth flow, a user-account structure, a navigation pattern, and a set of design conventions out of the box. Greenfield Bubble.io is faster than greenfield React, but Canvas is faster again. For an MVP that needs to be production-shaped in three sprints with gaps in between, the time it saves on the boring layers is the time you spend on the matchmaking logic that actually defines the product.

The trade-off is that you inherit Canvas’s data shapes and naming conventions. Anything you extend has to play nicely with the Canvas surface or you spend the rest of the build untangling its assumptions from yours. The schema for properties, contractors, and bids hangs off the Canvas user model with explicit extensions, not parallel structures.

The Construction Marketplace sign-in screen with email and password fields next to the product illustration, the AirDev Canvas auth surface as the entry point to the platform

The auth surface. AirDev Canvas ships the sign-in flow, the password reset path, and the session handling; the project-specific extensions hang off the Canvas user model.

The matchmaking algorithm: specialisation, service radius, and a clean read.

The matchmaking is the product. A property manager posts a project with a location, a specialisation, and a price range. A contractor’s profile carries their service radius, their specialisations, and their service area. The algorithm reads both sides and produces an invite list: contractors whose service area covers the project’s location and whose specialisation list intersects the project’s required specialisation.

The trick on Bubble.io is to keep this query cheap. Walking every contractor row on every project post is the version that locks up at fifty contractors. The version that ships denormalises the contractor’s service area into geocoded fields and stores the specialisations as relation rows that can be filtered server-side, so the matching query is a single constrained read instead of an in-memory scan. Boring schema work, large performance consequence.

The Construction Marketplace New Project modal with fields for title, description, location, specialisation, price range, and an image upload area

The property manager posts a project. Six fields drive the matchmaking algorithm on save: title and description for the bid invite, location and specialisation for the match, price range as a filter, optional images for context.

The Construction Marketplace property manager portal showing the My Projects list with a single project Construction of Bridge with 1500 metres specified, and Edit and Delete options

The property manager’s My Projects view. One row per project, edit and delete, and the bid feed for each project sits one click away.

Invite-to-bid, not open marketplace.

The deliberate design choice the founders made was to keep the bid flow invitation-only rather than open. A contractor never browses projects; they receive invites for projects the algorithm matched them to. They accept the invite, submit a bid (price, timeline, message), and wait. The PM sees the incoming bids, opens a thread with the ones they want to talk to, and accepts one.

The invite model is the structural difference between this product and a generic project marketplace. It keeps contractors from being spammed with irrelevant project posts, keeps PMs from drowning in bids they have to triage, and gives the platform a control point over match quality. The engineering shape that supports it is straightforward once the schema is right: an Invite record per match, an Bid record per accepted invite, and per-bid Thread record opened on demand.

The Construction Marketplace contractor Account Settings showing the company name, a 100-mile service radius, the location, and a Civil Engineering Contractors specialisation chip

The contractor’s Account Settings. Service radius and specialisation chips are the inputs the matchmaking algorithm reads from on every project post.

The Construction Marketplace contractor portal showing Sample Projects with a Dream Home entry, sidebar navigation for Projects, Bids, and Samples, and an Add Sample button

The contractor’s portal. Sample Projects build the portfolio a PM browses when reviewing bids; Projects and Bids tabs hold the active engagements.

The Construction Marketplace property manager Account Settings showing the Profile tab with first name, last name, description, and location fields and a Save changes button

The property manager’s Account Settings. The Canvas profile fields plus the location that joins the matchmaking algorithm on every project post.

Email: SendGrid first, then a migration to Postmark.

The transactional email layer started on SendGrid. Account verification, invite-to-bid notifications, bid-status updates, password reset, the usual transactional fan-out. SendGrid worked. The reason we eventually migrated to Postmark was not deliverability in the first place: it was support. The team hit a couple of issues that SendGrid’s support could not resolve on a useful timeline, and the deliverability differences between the two providers on a transactional load were already a tilt in Postmark’s favour.

The migration itself was small. Bubble.io’s API Connector calls map almost one for one between the two providers. The deliverability win was real and immediate; the support difference was the part that justified the swap.

Documentation as a deliverable, not an afterthought.

The clients asked for documentation alongside the build, not as a final pass. Every sprint shipped with documentation for the data model, the workflow layer, the integration points, and the deployment steps. The reason that mattered was that the founders are software developers themselves; they wanted to be able to extend the product without me being the only person who could read the codebase.

This changed the rhythm of the work. Decisions had to be defensible in writing the same day they shipped, not three weeks later when the context had cooled. The discipline made the build slower per feature and faster across the engagement: the second and third sprints could pick up where the first one left off without a re-archaeology pass each time.

An independent testing pass that came back at zero bugs.

The founders ran a separate testing team against the build at the end of each sprint. The team had no context on the implementation; they read the spec, wrote test cases against it, and ran them against the deployed app. Across all three sprints, the bug count returned to me was zero.

This is the part of the engagement I am proudest of. Zero bugs in a third-party test pass on a Bubble.io build is not luck. It is the result of writing every workflow against the actual schema instead of an assumed one, testing every input case before deploying, and treating “the spec says X” as the only correct answer when implementation gets ambiguous. The discipline lived in the sprints; the test result was the receipt.

What changed

Engagement 2024 3 sprints, direct client
Stack Canvas AirDev framework on Bubble.io
Test pass 0 bugs client's testing team

The Construction Marketplace MVP shipped to constructionmarket.io across the three sprints. The matchmaking algorithm holds, the invite-to-bid flow runs end to end, the email layer migrated cleanly from SendGrid to Postmark, and the documentation deliverable kept the codebase legible to the founders for whatever they ship next.

The pattern of the engagement is the part I would do again. Tech-literate clients with a precise spec, a framework chosen up front, documentation written alongside the code, and a testing team holding the deliverable to the spec rather than to taste. Three sprints with gaps in between is a healthy cadence when the work is small and the spec is clean.