IVTEC Web solutions, made to fit

Atelier Ștefan

A presentation site, portfolio and shop for a joinery workshop, with an admin panel and a separate panel for the people on the shop floor. Framework-free PHP, MariaDB, around 50 tables, with everything that might ever change moved out of the code and into the database.

stefan dashboard
Client
Stefan
Year
2026

A joinery workshop sells two things at once. There are the finished pieces with a price on the label, and there is the made-to-order work, where the price only appears once you know the timber, the dimensions and the finish. Ordinary online shops handle the first case. The second usually ends up as a contact form parked next to the catalogue, leaving the customer with the impression of two separate businesses.

Atelier Ștefan is built around that difference rather than in spite of it.

What it covers

  • Public site: a home page laying out how the work happens, a portfolio filterable by category and year, a catalogue with a product configurator, contact and quote request.
  • Admin panel: orders, products and pricing options, portfolio, pages built from content blocks, media library, messages, users with granular permissions, settings and an audit log.
  • Worker panel: assigned orders, their specifications, status changes and progress photos.

Decisions

One catalogue, two kinds of product. Fixed-price and made-to-order products sit in the same table, told apart by a column. The cart accepts both; if it holds even one made-to-order item, the order becomes a quote request and stops showing a final total, showing an estimate instead. The customer never has to work out which of the two worlds they landed in.

An order keeps its own version of the truth. Name, code, price and chosen options are copied into the order the moment it is placed. If the product is edited or deleted six months later, the old order stays exactly as it was given. Without that the history becomes a lie — and in Romania the invoice has to match the order.

If someone might ever want to change it, it does not live in the code. Contact details, legal texts, VAT rates, order statuses and their colours, email templates, anti-spam thresholds — all in the database, with a screen to edit them. What stays in code is the credentials, the keys and the security logic, precisely so they cannot be changed through the interface.

Sections switch on one at a time. The site was built whole, but every module has a toggle in the panel: shop, portfolio and blog go live once their content is ready. A module that is off is not merely hidden from the menu — its addresses return 404.

The worker panel is made for a phone held in dirty hands. Big targets, few screens, orders sorted by deadline. Statuses can only move along permitted paths defined in the database, so steps cannot be skipped. Prices appear only where the permission is explicitly granted.

Authorisation is checked in two places. Once in the controller for the permission, and again in the query layer, where a scope filter means a worker cannot pull someone else's orders even by changing a number in the address. A hidden button is not a security measure.

Uploads pass through four filters. Real file type verified rather than trusting the name. Full re-encoding of the image, which destroys anything hidden in the metadata. A randomly generated filename. Originals kept outside the public area, and in the folder that is served, the PHP engine is switched off.

The legal side is treated as a requirement, not a formality. Company identification in the footer, the mandatory consumer-protection links, a consent register, and a cookie banner that genuinely holds the scripts back until it is accepted. As for the 14-day right of withdrawal: goods made to a customer's own specification are exempt by law, but only if it is stated plainly and shown at the point of ordering — otherwise the exemption simply does not apply.

What was deliberately left out

Card payment is not integrated. The table and the gateway interface exist, empty, so it can be added later without rewriting anything. The workshop confirms every order by phone before it goes into production anyway, so online payment would have solved a problem that did not exist yet.

The same goes for per-order time tracking and material consumption: not in the first version, but the order structure supports them directly. They get added the day real costs need to be compared against the estimate.

No framework, for one reason

Shared hosting, no terminal, no Docker, no long-running background process. A framework would have brought more than the server could host. The choice has an honest cost: every protection — sessions, form tokens, attempt limiting, content security policy — is written by hand and, more importantly, applied the same way everywhere. Where a framework protects you through its defaults, here consistency does the work.