# property_web_builder: a multi-tenant Rails stack for property listing sites

> PropertyWebBuilder is a MIT licensed Rails application for running many property websites from one install, with tenant and site admin panels, faceted search, Liquid templating and embeddable listing widgets. It suits agencies or portals that need per-tenant sites quickly, and it is a full application rather than a library, so you inherit its tenancy model.

**etewiah/property_web_builder** — Create a fully featured real estate website on Rails in minutes! ⛺

- Repository: https://github.com/etewiah/property_web_builder
- Website: https://propertywebbuilder.com
- Stars: 648 · Forks: 284
- Language: Ruby
- License: MIT
- Published: 2026-10-21 · Updated: 2026-10-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/etewiah-property-web-builder

## One install, many property websites

PropertyWebBuilder is a Rails application whose stated purpose is to create a fully featured real estate website in minutes. The multi-tenancy feature is the one that shapes every other decision: host multiple websites from a single installation, with a tenant layer above the individual sites.

The 2.0 release, described as a major release covering 5 years of development and 500+ commits since v1.4.0, converted the project from a Rails engine to a standalone application. That is the single most consequential change in the project's history, because an engine is meant to be mounted inside a host application, while a standalone application is the application. Anyone upgrading from the 1.x line is not applying a patch, they are replacing the integration model.

The tenancy mechanism is the acts_as_tenant gem, and the admin surface is split in two: site_admin for per-website management and tenant_admin for cross-tenant, platform level operations. That split is the right shape for the problem, since the person running one agency site and the person operating the platform have genuinely different jobs. It also means you get two admin interfaces to configure, secure and train people on rather than one.

## The property model split between sale and rental

The data model was reorganised around a RealtyAsset, with separate SaleListing and RentalListing models hanging off it. The reasoning is straightforward domain modelling: a sale listing and a rental listing share the underlying property, the address, the media and the map location, and they differ in price fields, lease terms and listing lifecycle. Splitting them means the rental screen does not have to know about a asking price and the sale screen does not have to know about a deposit.

For a team extending the application this is the part to read first, because every query, form and search facet is written against those three models. Faceted search with field key filtering is built on top of that structure, and the filters are declared as fields with keys rather than hardcoded columns.

The other feature worth understanding is the seed packs system, described as scenario-based seeding for quick site setup. Combined with idempotent seeding, which the 2.1 notes say prevents duplicate data, this is what makes a new tenant usable in minutes rather than requiring someone to enter listings by hand. Seed data is also the fastest way to see what the search and the themes actually do, which makes it the right first step when you are evaluating the project at all.

## Theming with Liquid templates, CSS variables and Tailwind

The public-facing look is a theme system rather than a hardcoded layout. The themes named in the documentation are Brisbane, described as luxury, along with Bologna, Bristol, Barcelona, Biarritz, Brussels and the default themes, and the 2.0 release moved the front end from Bootstrap to Tailwind CSS with multiple colour palettes per theme.

The theming mechanism has three parts, and each one is a different kind of lever. Liquid templates give structural control over the page, since a theme can change the markup rather than only the colours. CSS variables give a runtime lever, so a palette change does not require recompiling. And the page parts system, mentioned alongside the customisability features, suggests that pages are composed of reusable parts rather than being one monolithic template per theme.

That structure has a visible cost, because Tailwind is compiled per theme. The package scripts in the repository show one build target per theme, for example the default, Bologna, Brisbane, Barcelona, Biarritz and Brussels targets, each compiling an input stylesheet to a build output, and a combined build script that runs all six. The Docker build runs the production variant of that combined build in the Node stage. Six compiled stylesheets is not a problem at this scale, but it is the shape of the thing: every new theme means a new input stylesheet and a new build target.

## Deployment branches, release tags and the environment contract

The repository documents two branches, master for stable releases only and develop for active development which may contain work in progress, and it recommends checking out a specific release tag for production:

```bash
git checkout v2.0.0
```

That recommendation is worth taking seriously for a hosted application, and it raises a point about how releases are tracked. The repository has no GitHub releases, so a tag in git history is the only version marker, and the version history lives in the CHANGELOG instead.

The environment contract is documented in .env.example and it is more demanding than a typical Rails app because of the multi-tenancy and the storage choices. It holds a Google Maps key as VITE_GMAPS_API_KEY, a full Cloudflare R2 set of R2_ACCESS_KEY_ID, R2_SECRET_ACCESS_KEY, R2_BUCKET and R2_ACCOUNT_ID, Firebase credentials, the PLATFORM_DOMAINS list of platform domains where subdomains route to tenants, and an optional PLATFORM_IP for apex domain A records. It also carries Sentry configuration including the DSN, environment override, trace and profile sampling rates, and a SENTRY_SEND_PII switch that is documented as needing to be disabled for strict privacy compliance.

That last flag is a good example of the shape of this project. It is a multi-tenant platform where a single misconfigured environment variable can route tenants to the wrong host, and the documentation is honest about the risk.

## The Dockerfile shows the real dependency footprint

The production Dockerfile is a three-stage build and it exposes what the application actually needs. The first stage is a Node builder on node:22.18-bookworm-slim, which installs the npm dependencies and compiles the Tailwind CSS for all themes, copying the stylesheets, themes, views, helpers and javascript directories into the build.

The second stage is a Ruby builder on ruby:3.4-slim-bookworm, which installs native build dependencies: build-essential, git, libpq-dev, libvips-dev and pkg-config. Those two libraries are telling. libpq-dev is the PostgreSQL client library, so the application expects Postgres rather than a MySQL default. libvips is the image processing library, which is what ActiveStorage uses for image variants, and its presence confirms that image handling is a first-class part of the app rather than an afterthought.

The stage sets BUNDLE_DEPLOYMENT=1, BUNDLE_PATH and BUNDLE_WITHOUT for a production gem install, and RAILS_ENV=production. The comment on the Node stage explains that all dependencies are installed rather than just the production ones because the Tailwind CLI is not in devDependencies, which is a small but real constraint on how you can trim the image.

The application requires Ruby 3.4.7 or higher and Rails ~> 8.1, so a host has to be current. The repository also carries a .tool-versions file, an .envrc, a Procfile and Procfile.dev, a Dockerfile and a docker-entrypoint.sh, and deployment guides for more than 10 platforms, so the deployment path is documented rather than improvised.

## Embeddable widgets, Firebase auth and the Open Collective model

Version 2.1 added embeddable property widgets, which are the most interesting new feature: embed property listings on any external website, with JavaScript and iframe embed options, customisable themes, colours and layouts, domain restrictions for security, and impression and click analytics. Domain restrictions matter more than they sound, since an embeddable widget on someone else's domain is a vector for someone else's content appearing under your brand.

Authentication is optional Firebase authentication with a Devise fallback, plus audit logging for authentication events. The 2.0 release also added push notifications via ntfy.sh. Both choices are notable: Firebase removes the need to run your own identity service, Devise is the fallback for local accounts, and ntfy.sh is a lightweight push notification service.

The project's funding model is Open Collective, and the README asks for contributions through it. Alongside that, the project is part of a small set of property-tech products by the same author, which is worth knowing because it explains the shape of the feature set. The author has also been interviewed on the Coding with Jason podcast about the story of the project. The licence is MIT, with an MIT-LICENSE file at the repository root, and there is no code restriction tied to the funding.

## Where this Rails application is the wrong choice

The first mismatch is scale. If you need one property website with a dozen listings, this is an enormous amount of application to operate. You get multi-tenancy, two admin panels, theming with compiled assets per theme, seed packs, a setup wizard, a CRM-shaped set of models, faceted search, widgets, audit logging and push notifications. Every one of those is a feature to configure, secure and keep working.

The second is the front-end ceiling. The public site is constrained to what the bundled themes and the page parts system provide. The documentation lists customisation as CSS variables, Liquid templates and page parts, and the 2.0 notes mention enhanced theming with CSS variables and Liquid templates, but the themes themselves are the enumerated set. A brand design that does not fit them means writing theme code, and at that point you are maintaining a fork of a multi-tenant Rails app.

The third is the framework coupling. Rails ~> 8.1 with Ruby 3.4.7 means a current host, a JavaScript toolchain in addition, and an upgrade path you have to follow. There is a static site generator for a small agency site, and a WordPress theme, and neither requires you to keep a Rails process, a Postgres database and a Tailwind build in step.

The genuine alternative is not another Rails property package, it is a different architecture: generate static or server-rendered listing sites from your MLS feed with a build pipeline, and put a lightweight CMS in front for the editorial pages. You lose the built-in admin, the multi-tenancy and the widgets, and you gain a much smaller operational surface and far less that can break. That trade is worth making for a single site, and usually wrong for a portfolio.

## Conclusion

PropertyWebBuilder is a good fit for a team that needs several branded property sites, or one site with a non technical team running it, and that accepts a Rails 8.1 and Ruby 3.4.7 host and the tenancy model the application already enforces. It is the wrong choice for a single small site, for a project that needs to extend the public-facing design beyond the bundled themes, or for a team unwilling to own a full Rails application with its own upgrade path. Before deploying it, read the multi-tenancy guide and the seeding guide, decide whether tenants are subdomains or custom domains because the domain model is baked into the routing, and confirm your storage choice, ActiveStorage on S3 or R2, since Cloudinary is no longer supported after the 2.0 rewrite.

## FAQ

### What are the Ruby and Rails versions PropertyWebBuilder needs?

The documentation states that PropertyWebBuilder runs with Ruby 3.4.7 or higher and with Rails ~> 8.1. The production Dockerfile builds on a ruby:3.4-slim-bookworm base image.

### How does multi-tenancy work in property_web_builder?

Version 2.0 converted the project from a Rails engine to a standalone application with full multi-tenancy using the acts_as_tenant gem, and split the admin interfaces into site_admin for per-website management and tenant_admin for cross-tenant operations.

### Which storage backend does PropertyWebBuilder use?

Version 2.0 replaced Cloudinary with ActiveStorage, so uploads go to S3 or R2 compatible storage such as Cloudflare R2 or AWS S3. The .env.example file lists the R2 access key, secret, bucket and account id variables.

### How do I deploy PropertyWebBuilder to production?

The repository recommends checking out a specific release tag rather than a branch, for example v2.0.0, with master holding stable releases and develop holding work in progress. The docs folder includes deployment guides for more than 10 platforms, and there is a production Dockerfile with a Node stage for Tailwind and a Ruby stage for gems.

### What licence is PropertyWebBuilder released under?

The project is MIT licensed, with the licence in the MIT-LICENSE file at the repository root. The repository has no GitHub releases and the last push was on 2026-10-19, so version tracking runs through tags and the CHANGELOG.

## Sources

- [etewiah/property_web_builder on GitHub](https://github.com/etewiah/property_web_builder)
- [Issues](https://github.com/etewiah/property_web_builder/issues)
- [License: MIT](https://github.com/etewiah/property_web_builder/blob/master/LICENSE)
- [Project website](https://propertywebbuilder.com)
- [README](https://github.com/etewiah/property_web_builder/blob/master/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/etewiah-property-web-builder
