Atul Rai
Back to Projects

Spatial project publishing for interiors

A platform where an interior project is photographed spaces with products and materials pinned on the image — the photo is the source of truth, not a detached spreadsheet.

Product Engineer

Role

Leading Architect / Interior Designer

Client

Independent Practice (Aug 2025 – Present)

Period

Overview

Studios already have the photographs. What they lacked was a way to treat those photographs as the project record: this space, this master shot, these objects, in place.

I built a publishing platform for interior projects. You photograph a space, tag what is in it, and publish. Overlays, copy, and print all read from the same project graph. The unusual part is not a feed of images. It is that specification lives on the picture.

This sat in independent practice as Product Engineer for a leading architect / interior designer — one product among others, not a studio identity.

Problem

Typical project sites split media from inventory. The gallery is one artifact. The product list is another. Coordinates, finishes, and captions drift the moment someone crops a photo or reprints a sheet.

The client needed a record that survived crop, device, and print, and that did not fork when the same chair is named differently in another market. Tagging had to start from the image. Editorial copy had to be publishable, not a truncated model dump.

Architecture

A project is a tree of spaces. Each space has a master shot and angle shots. Products and materials exist as overlay hotspots on the master. Coordinates are normalized to the image, not to a particular viewport.

Two AI paths sit behind that graph. A vision annotation pipeline proposes hotspots as schema-valid JSON, then resolves each detection onto a canonical category. A separate generation path writes long-form editorial from the photographs (vision) and social copy plus tags (text), with hard length caps applied at sentence boundaries.

The publisher is a multi-step flow: draft, schedule, publish, with collaborative invites. Print-ready PDFs — an editorial booklet and a spec sheet — are generated from the same live graph as the web. Public APIs, invite-only admin, OIDC, migrations, and healthchecks are the delivery shell, not the product.

Challenges

Normalized overlays look simple until object-contain, print, and device crops disagree. The contract is image space, not screen space; every renderer has to honor it.

Vision output is not a category. Detections have to land on a taxonomy without inventing ids. Prompt-constrained ids plus an alias fallback was the workable split: the model may name a category when it is sure; unresolved labels still map through synonyms instead of becoming a second catalog.

Generation had the opposite failure mode: fluent text that was not shippable. Length limits that slice mid-sentence are worse than no copy. Caps had to be editorial rules, not character counters.

Locale was a data-contract problem. If display names leak into identifiers, the catalog forks. Canonical keys stay internal; regional names and synonyms sit at the edge.

Scale / Performance

This was built for a client practice, not a traffic claim. The load that mattered was correctness under transform: overlay math that still lands after contain-fit; JSON that still parses after a vision call; copy that still reads after a cap; PDFs that still match the published project.

The expensive work is gated (detection, editorial vision, social/tags as separate passes) so a publish edit does not rerun the whole stack. Taxonomy resolution is a lookup against the same category set the prompt was given, not a second model.

Interesting Engineering Decisions

Spatial model

A space is not an album. One master is the tagging surface; angles are views of the same room. Hotspots are pinned in normalized coordinates so a callout is a property of the photograph. Crop, device, and print are renderers of that coordinate, not competing sources of truth.

Vision → taxonomy

Detection returns schema-valid JSON: type, label, position, optional attributes. Category assignment is two-stage. The prompt may emit a known category id; anything else is resolved after the fact through product-type keys, material keys, and a synonym map. Invalid ids are dropped. Unmapped labels stay uncategorised instead of polluting the catalog.

Constrained generation

Editorial and social are different jobs. The vision pass sees the photographs and writes long-form about copy with no brand or hotspot dump in the prompt. A text pass writes caption and tags from project context. Both are clamped at sentence (then word) boundaries so a 200-character short or a 1000-character long is a finished paragraph, not a cut sentence.

Taxonomy as contract

Internally, a sofa is a key. At the edge it can display as sofa or couch. Specs, filters, and PDF rows bind to the key. Regional display names and aliases do not create a per-locale catalog. The taxonomy is the contract between vision, authoring, and export.

Lessons Learned

If the photograph is the record, every downstream format has to be a projection of the same graph. A PDF that invents a finish field is a second product.

Structured output is cheaper than cleanup, but only if you validate against the same id set you put in the prompt. Alias fallback is for language, not for guessing new categories.

Generation quality is a publishing constraint. Sentence-boundary clamps did more for “this can go live” than another prompt adjective.

Do not let locale into primary keys. Synonyms belong at the edge.

Outcome

Shipped for a leading architect / interior designer during independent practice (Aug 2025 – Present). Studios can photograph a space, tag from the image, invite collaborators, and publish to web and print from one project graph.

No user or traffic figures to report. The measure that mattered was whether overlays, taxonomy, copy, and PDFs stayed consistent after a crop, a locale, and a regenerate.