Portfolio

E-commerce Development: Norwegian housing estate

osiedlenorweskie.pl is a website for a housing estate in Koszalin, presenting the place, architecture, and practical information.

#Websites
E-commerce Development: Norwegian housing estate

Osiedle Norweskie is a gated development of detached houses in Koszalin, built by Firmus Group in the Jamno district on Gradowa street. The architecture keeps a traditional, timeless form, set against surrounding greenery and spaces made for children and their parents. Warm facade tones, a slightly contrasting dark roof and wood detailing settle the houses into their surroundings. Relaxing nature, the proximity of the lake and fresh, almost sea-like air give residents conditions they will not find elsewhere in Koszalin. A lawn of your own, greenery as far as the eye can see, the sounds of nature rather than city traffic: all of it invites you to slow down after work, and gives children somewhere to play.

#The site is mostly pictures, and that decides the engineering

Everything technical about osiedlenorweskie.pl follows from one plain fact. Someone buying a house looks at photographs and floor plans. They do not read paragraphs. So the heaviest thing this site ships is imagery, and every decision about speed is really a decision about images.

The website went live in 2016 and took roughly six weeks. It runs on WordPress with a custom theme, behind Cloudflare at the edge, with Varnish in front of the application and Redis underneath it, and backups in AWS object storage.

#Serving the right image, not just a smaller one

Size variants matter more here than file format, even though format is what people argue about. A two thousand pixel photograph displayed in a four hundred pixel card costs the same transfer no matter how good the codec is. Only after the browser is given a set of variants to choose from does a conversation about compression mean anything, and only then does moving to a newer format show up as a visible difference.

House galleries were built as custom post types holding plans and photographs, loaded without a full page reload, with variants selected by the browser against the real rendered width. That last part is easy to get wrong: a responsive image declaration that describes the layout inaccurately will hand a phone the desktop file and report success while doing it.

Floor plans needed their own answer. Architects deliver plans as print artefacts, with hairline strokes and annotations that are unreadable at phone scale. Shrinking such a file does not solve the problem, because legibility of the dimensions disappears along with the weight. The fix was to separate preview from document: the house card shows a simplified plan prepared for screens, and the print file is downloaded deliberately, in one click, once the visitor already knows this house interests them.

#Four house designs, and why that shapes the content model

The most consequential decision was made before the first template line and concerned what a unit of content is here. The development plans forty-eight houses of varying size, on plots between six hundred and fifty and twelve hundred square metres. Those are not forty-eight different designs. The developer offers four types, named after Norwegian cities: Alesund at 125.72 square metres, Bergen at 136.34, Oslo at 152.12 and Trondheim at 178.70.

If each individual house were its own record with its own description, plan and gallery, then one change to the Bergen finishing standard would mean editing a dozen entries, and sooner or later an editor would update only some of them. With the house type as the record and a specific plot as an instance of it, the description is written once, while plot number, land area and availability status are fields anyone can change without the content drifting apart.

The cost is worth naming too. When an atypical house appears, say a mirrored plan forced by the shape of a plot, the model needs an exception, and exceptions are more expensive in a tightly closed model than in a loose one. It was worth it here because there are a handful of unusual cases and several dozen ordinary ones.

#Who comes back, and how often

Nobody buys a house in one session. The same person returns a dozen times across several months, looking for something different each time: the ground floor plan, then the distance to a school, then construction progress photographs to check how far along the build is. Two requirements follow. House card addresses have to be durable, because they end up in bookmarks and forwarded to family. And progress photographs have to be quick and frequent to add, because they are the reason anyone returns.

The second trait of this audience is the device. A large share of visits come from phones, often on poor signal, since Jamno sits at the northern edge of the city. A site that loads in a second on a desk can take many times longer at the edge of coverage, and the visitor does not separate the carrier’s fault from the site’s.

#The map, and where its usefulness ends

A Leaflet module shows the development and its surroundings using GeoJSON data. A map on a developer’s site has one job: answer what is nearby, and that is a question a written list answers worse than a drawing does.

It is worth knowing where the limit sits. A vector layer with many points can lock up the interface on a weaker phone, because the browser tries to draw everything before handing control back. Restricting the data to the actual surroundings of the development, and loading the map only once the visitor scrolls to its section, costs one extra request and saves several seconds of stutter on first open. That is the kind of trade-off that looks unnecessary on a fast connection and decides whether anyone stays on a slow one.

#Three layers of cache, and what invalidates them

Caching happens at several levels and each one handles a different kind of request. Cloudflare at the edge serves static files and anonymous pages, which is effectively all search traffic. Varnish in front of the application holds assembled house list views whose construction costs several database queries. Redis shortens those queries for anything that has to reach PHP anyway.

Three levels on a site this size sounds excessive until you look at what changes and how often. A house type description does not change for a year. The availability status of one house changes on the day a contract is signed, and the sales team expects the site to show it immediately. If everything sat in one bucket, every status change would evict the unchanging content as well, and the cache would effectively not exist.

So invalidation is targeted and bound to save events on specific records rather than global. The single most common defect I see in builds like this is exactly a cache that technically works and is flushed whenever anything at all is saved. The configuration looks right, the logs show hits, and the server still recomputes everything from scratch dozens of times a day.

#The contact form and what happens to an enquiry

The form collects enquiries about a specific house or a house type, validated on the server and protected against spam. Browser validation is a convenience for the visitor, not a control, so the same rule runs again server side.

Something else matters more: an enquiry has to know where it came from. A message reading “please call me” with no indication that it was sent from an Oslo house card forces the salesperson to call back in order to ask a question the site already knew the answer to. House context is therefore attached automatically, and a copy is written to the database regardless of whether the outbound mail succeeded. Mail servers are unavailable for a few minutes now and then, and that is not a reason for a lead to vanish without trace.

#Backups and updates, the dull part that saves the project

Backups go to AWS object storage, encrypted and rotated. Here is the part usually left unsaid: a backup that has never been restored is a hypothesis, not a safeguard. The presence of files in a bucket guarantees nothing until someone checks that the database dump imports and that the media files came with it rather than only the tables.

The second dull and decisive matter is update order. Core and plugin updates go to a staging environment first, and not out of ritual caution. On a site with a custom theme and custom content types it is the theme, not the WordPress core, that comes apart on a version bump, usually at the point where a template assumed a data shape a plugin has just changed.

#Local visibility and the trap of a distinctive name

Osiedle Norweskie is a memorable name, and that helps right up until you look at what people actually type. Someone who knows the name will find the site without our involvement. Someone still deciding whether to move types something else entirely: houses in Koszalin, gated estate Koszalin, house for sale Jamno. A site built purely around a proper noun serves only the people who have already made up their minds.

So the structure of addresses and headings had to carry what this development is, not only what it is called. The development page talks about detached houses in a gated enclave in Koszalin, and names the district outright rather than assuming the reader knows it. That is not a trick aimed at an algorithm, it is aimed at a person who does not live in the city and has no idea where Jamno sits.

The second trap concerns structured data. It is tempting to describe every house as a priced offer, because search engines like that data and will surface it. The problem is that the price of a house with land shifts during a stage, while data released into an index lives on for weeks. A stale price in a search result produces a conversation that opens with a correction, which is the worst possible opening. The site therefore publishes type, floor area and availability, and leaves the price conversation to a person.

Third, there is the image in the result. A thumbnail chosen automatically often turns out to be a slice of facade without context. Naming a representative image per record costs one field in the content model and decides whether a searcher sees a house or a piece of roof.

#The blog, and why a developer needs written content at all

A blog attached to a residential development is usually treated as an obligatory extra and usually dies after three posts. Here it had a specific job: answer the questions people ask before deciding, the ones that do not fit on a house card. What the morning commute into central Koszalin looks like, what plot servicing status means in practice, how a developer contract differs from a preliminary agreement, what the surroundings look like in winter rather than only in June photographs.

The technical side of that content is simple and the editorial side is not. A post that restates the development description in different words competes with the development page in search, loses to it, and weakens it at the same time. So every piece needed its own subject and had to link into the house cards rather than the other way round. Where topics started to overlap, expanding the existing post was the better move than writing a second one about the same thing.

#What was deliberately left out

A project description without this section is a brochure, so here it is. We did not build an interior finish configurator, although the idea came up at every stage. A configurator makes sense when the options are countable, documented in one place on the client side, and priceable without phoning a salesperson. With four house types and individually negotiated finishing, the tool would have produced numbers that still required confirmation, which is the opposite of what it promises.

We did not build online reservation either. In property, a reservation without a payment is not a reservation, it is a queue, and a publicly visible queue generates more disputes than sales. Availability is therefore information rather than an action, and a person on the developer’s side changes it.

The third omission is resident testimonials. Tempting, but in a development whose first stage was six houses, any published opinion is by definition attributable to a specific family. The site shows construction progress and photographs of completed houses instead, which says the same thing without asking anyone to speak in public.

#Technical support, keeping the harmony

Osiedlenorweskie.pl is not a one-time sketch, it is a site that needs continuous care. Core and plugin updates are tested away from production first, with backups held in AWS. Cloudflare, Varnish and Redis keep performance in hand, and their configuration is revisited whenever the shape of the content changes, because it is content change rather than the passage of time that breaks a caching strategy. Loading quality is monitored, database queries are tuned and caches are cleared when the offer changes.

The site can be extended: a virtual walkthrough, an integration with a sales system, an available-houses module updated from one place. Each of those starts with the same question, which is how much content will actually need maintaining afterwards, because that, and not the code, is what generates cost in the second year.

For a residential project website, the useful first step is to write down property types, location data, media assets, sales contact flow, integrations, and maintenance expectations.

What scope did the Norwegian housing estate project cover?#
Norwegian housing estate sits in the Websites category and was first delivered in 2017. The entities behind it are Redis, Cloudflare and Varnish.
How did delivery run for Norwegian housing estate?#
The build ran about six weeks and went live in 2017. It sits on Redis, Cloudflare and Varnish. The layout came from the client. I built the templates and the content model against it, then checked the paths that carry traffic on a copy of production rather than on an empty install.
What was the hardest technical part of Norwegian housing estate?#
Holding Redis, Cloudflare and Varnish together took the most care. Content, configuration and code stay in separate layers, so a rollback after launch moves one of them and not all three. Edge cases surface on a production copy, which is why the checks run there.
What part of Norwegian housing estate could be reused on another build?#
Redis, Cloudflare and Varnish is the part that carries over; that layer looks much the same on the next build. What does not carry over is this project's content model and its integrations, written against one client's data for a Websites brief. A second build starts from a scope review, and the quote follows it.

Need an FAQ tailored to your industry and market? We can build one aligned with your business goals.

Let’s discuss