# Vuewer: full text > Vuewer is a Dutch-founded, Spain-based engineering studio that builds AI features and web applications, run by Alexander (Sander) van Hooff since 2015. This file is the full text of the main pages of https://vuewer.com, generated from the site itself. It exists so that an answer engine can quote Vuewer accurately without crawling and stripping the HTML. Last generated 2026-10-05. - **Founded:** 2015 - **Based:** Alicante, Spain - **Founder:** Alexander (Sander) van Hooff, https://sandervanhooff.com - **Contact:** info@vuewer.com - **VAT / registration:** Registered in Spain No. Z3009099Z - **Working languages:** English, Dutch, Spanish ## Pages ### AI development that reaches production. https://vuewer.com/ai-development Vuewer builds AI features into existing web applications: retrieval-augmented search, document extraction, generation inside real workflows, and multi-step agents. We work in Laravel and PHP with OpenAI and Anthropic models, ship a first production feature in three to six weeks, and set cost, latency and accuracy budgets before writing code. ### Web applications built to outlast a trend cycle. https://vuewer.com/web-app-development Vuewer builds custom web applications, APIs and integrations in Laravel, with Livewire, Alpine.js and Tailwind CSS on the front end. Ten years of production work for European clients, measurable performance, and maintenance that actually happens after launch. ### Engineering that moves the number. https://vuewer.com/services Vuewer builds AI features and web applications for agencies and product companies across Europe. Two pillars, AI engineering and Laravel development, delivered by one senior engineer with no handoffs between the first call and production. ### Excellent price/quality. https://vuewer.com/pricing Hourly for small work, a fixed price for projects, a monthly retainer when you need reserved capacity. Figures are published here rather than hidden behind a sales call, and every project gets a fixed price in writing before it starts. ### Full stack, full service, and one person accountable. https://vuewer.com/about Vuewer is a boutique engineering studio run by Alexander (Sander) van Hooff from the Alicante region of Spain, working for clients across Europe since 2015. You work with him directly, from the first call through to handover. ### Straight answers. https://vuewer.com/faq What we build, which AI models we use, what happens to your data, how we price work, and what happens if you are not satisfied. If your question is not here, ask it directly. ### Tell us what you're building. https://vuewer.com/contact Write a few lines about the project and you will get a reply within one working day, from the engineer who would do the work. No discovery call required before you know whether we are a fit. ## Supporting services ### Interface and interaction design https://vuewer.com/services/ui-ux-design Vuewer designs and builds the interface in one place, so there is no handover between a design file and the code that has to implement it. You see wireframes and a clickable prototype before development starts, then a design system delivered as working components rather than a static style guide. - Wireframes and a clickable prototype before a line of code. - A design system built as Blade and Tailwind components, not a static style guide. - Responsive behaviour decided for every breakpoint, including the awkward ones. - Contrast and focus states checked against WCAG AA. ### APIs and integrations https://vuewer.com/services/api-development Vuewer builds REST and GraphQL APIs, and connects systems that were never designed to talk to each other. Every integration ships with idempotent webhook handling, retries with backoff and alerting, because the thing you have to design for is the service at the other end going down. - REST and GraphQL APIs with versioning, authentication and rate limits. - Webhook handling that is idempotent, so a duplicate delivery cannot charge anyone twice. - Retries with backoff, and a queue that holds work until the upstream service returns. - Alerts when an integration starts failing, instead of a customer noticing first. ### E-commerce and payments https://vuewer.com/services/ecommerce-development Vuewer builds and extends online stores in Shopify, WooCommerce and custom Laravel checkouts, with payments through Stripe, Mollie or PayPal. Most of the work is the part nobody demonstrates: EU VAT rules, failed payments, refunds, and keeping your database and your payment provider in agreement. - Checkout, subscriptions and one-off payments through Stripe, Mollie or PayPal. - EU VAT handling, invoices and refunds that match your accounting. - Shopify and WooCommerce stores extended, or connected to your back office. - Webhook reconciliation, so your database and your payment provider agree. ### Content management https://vuewer.com/services/cms-development Vuewer builds the editing interface around the content you actually change, instead of installing a general-purpose CMS and hoping it fits. Multilingual content with translated URLs is there from the start, and permissions are scoped so an editor cannot break the checkout while fixing a typo. - An admin panel scoped to what your team edits, on the same Laravel stack. - Multilingual content with translated URLs, not a language folder added afterwards. - Media handling with automatic image resizing and modern formats. - Roles and permissions, so an editor cannot break the checkout. ### Performance engineering https://vuewer.com/services/performance-optimization A slow application is usually a handful of specific problems rather than a shortage of servers. Vuewer measures Core Web Vitals on real devices, finds the query or the payload responsible, fixes it, and reports the numbers before and after. This site scores 100 on Lighthouse. - Core Web Vitals measured on real devices and throttled connections, not a local machine. - The slow query found and fixed, with indexes and eager loading where they belong. - Caching, queues and background work moved off the request cycle. - A written report with the numbers before and after. **How much faster can you make it?** Unknown until it is measured, and anyone answering that before looking is guessing. What can be committed to is the measurement, a prioritised list of causes with the effort each one costs, and saying so when the remaining gains are not worth buying. **Is this just caching?** Caching is the last step, not the first. It hides a slow query rather than fixing it, and a cache in front of a bad query fails badly the moment it is invalidated. The query gets fixed first, and then caching makes an already fast page cheaper to serve. **Does a fast Lighthouse score actually matter?** The score itself does not. What it measures does: Core Web Vitals are a ranking signal, and load time affects conversion whether or not it affects ranking. A perfect score on a page nobody can use is still worth nothing. ### Technical SEO, AEO and GEO https://vuewer.com/services/technical-seo Ranking, being the answer a search engine reads out, and being cited by ChatGPT or Perplexity are three different jobs with one thing in common: structure a machine can parse. Vuewer handles structured data, canonicals, reciprocal hreflang, answer-first page structure and an llms.txt file. - Structured data, canonicals and reciprocal hreflang across every locale. - Answer-first page structure, so a paragraph can be lifted as the answer. - An llms.txt file and clean markdown alternates for AI crawlers. - A crawl and index audit, with the fixes ordered by what they are worth. ### Security hardening https://vuewer.com/services/security-hardening Incidents are rarely clever. They are an unpatched dependency, a missing permission check, or a secret committed to a repository. Vuewer works through that list, applies the upgrades rather than only reporting them, reviews authorisation route by route, and leaves the checks running automatically. - A dependency and CVE audit, with the upgrades applied rather than only reported. - Authorisation reviewed route by route, so a URL cannot expose another customer's data. - Security headers, CSRF, rate limiting and login protection configured. - Secrets moved out of the codebase and rotated. ### Hosting and infrastructure https://vuewer.com/services/hosting-and-infrastructure Vuewer provisions hosting on Laravel Cloud, Forge or Vapor in accounts registered to you, so the servers, the domain and the billing stay yours and you can leave whenever you want. Deploys carry no downtime, a rollback is one command, and backups are verified by restoring one. - Laravel Cloud, Forge or Vapor, provisioned in accounts registered to you. - Zero-downtime deploys from your repository, with a one-command rollback. - Automated backups, verified by actually restoring one. - Uptime, error and queue monitoring wired to alerts someone reads. ### Maintenance and support https://vuewer.com/services/maintenance-and-support Software ages quietly: dependencies fall out of support, certificates expire, and the framework moves two major versions ahead while nobody is watching. A Vuewer retainer puts updates and security patches on a monthly schedule, with a fixed block of hours and reserved capacity for urgent work. - Dependency and framework updates on a monthly schedule, with the test suite as the safety net. - Security patches applied when they are published, not at the next release. - A fixed block of development hours each month for changes and improvements. - Reserved capacity, so something urgent does not wait for a project to finish. ### Legacy rescue and codebase audits https://vuewer.com/services/legacy-rescue An application left behind by an agency that stopped replying, or by a developer who moved on, starts with an audit rather than a rewrite. Vuewer assesses code quality, security, dependencies and whether it can still be deployed, then prices stabilising it. Sometimes the answer is not to keep it. - A written assessment of code quality, security, dependencies and deployability. - The build running locally and deployable again, usually the first real blocker. - Tests added around the paths that matter, before anything is rewritten. - A prioritised plan with effort estimates, so you can stop at any point. **What if the previous developer left no documentation?** That is the normal case, and the code and the database are the documentation. Reading them is part of the audit. Access to the repository, the hosting and the domain registrar matters far more than any handover document. **Will you tell us to rewrite it?** Only if that is genuinely cheaper than keeping it, and it usually is not. A rewrite restarts every bug you have already found and paid to fix. The audit says which parts are worth keeping and prices both options honestly. **Can we buy just the audit?** Yes. It is a deliverable on its own, priced on its own, and it is yours whatever you decide next. Taking it to your existing developer and having the work done there is a perfectly reasonable outcome. ### Migrations and replatforming https://vuewer.com/services/migrations The risk in a migration is never the new system, it is the data and the URLs. Vuewer plans both before anything moves: a reversible migration script with verified record counts, a redirect mapped for every old URL, and a staging environment running real data before cutover. - Data migrated with a reversible script and a verified record count, not by hand. - Redirects mapped for every old URL, so rankings and inbound links survive. - A staging environment on the new stack, running the real data, before cutover. - A rollback plan written down before the switch rather than during it. ### White-label engineering for agencies https://vuewer.com/services/white-label-development A large share of Vuewer's work comes from agencies and studios who need a senior engineer without adding headcount. We work in your repository, under your brand and to your process, talk directly to your developers, and do not approach your client. You stay the agency. - Work delivered under your brand, in your repository and your project tracker. - Direct contact with your developers, or a single point of contact if you prefer. - Estimates you can put in front of a client without marking up a guess. - A written undertaking that we will not approach your clients, if you want one. **Will our client know Vuewer is involved?** Only if you tell them. Commits, pull requests and any documentation follow your conventions, and we do not appear in the client's tooling or correspondence. If you want non-solicitation in writing, say so and it goes in the contract. **Can you speak to our client directly?** Yes, on your terms, and it is often the quickest way to settle a technical question. Some agencies want it and some do not. Either way it is decided before the work starts rather than halfway through. **How is agency work priced?** The same way as anything else: hourly, or a fixed price once the scope is clear. You receive the estimate at cost and set your own margin on top of it. We never quote your client, and we never see what you charge them. ### Technical consultancy https://vuewer.com/services/technical-consultancy Sometimes the useful thing is not a project but a conversation. Vuewer reviews architecture and database design before you commit, gives a second opinion on somebody else's quote or timeline, and argues build against buy with the trade-offs written down. Hourly, with no obligation afterwards. - Architecture and database review before you commit to a direction. - A second opinion on somebody else's proposal, quote or timeline. - Build, buy or platform decisions, with the trade-offs written out. - Hiring support: technical interviews and code review for candidates. ## Pricing - **Pay as you go**: €95 /hour: Small tasks, updates, or an extra pair of senior hands when you need one. - **Website**: from €1.499 one-off: Business sites, portfolios and landing pages that need to look right and load fast. - **Web application**: from €4.999 one-off: Custom applications with real workflows, user accounts and third-party integrations. - **AI feature sprint**: from €7.500 one-off: Three weeks from idea to a production AI feature your users can actually use. - **Partner retainer**: from €1.950 /month: Reserved senior capacity every month, for teams who need a standing partner. All prices exclude VAT. Every project gets a fixed price in writing before it starts. ## Frequently asked questions ### About Vuewer **Who is behind Vuewer?** Vuewer is a boutique engineering studio run by Alexander (Sander) van Hooff, its founder, designer and web engineer. You work with him directly, from the first call through to handover. Our clients are predominantly other development companies, marketing agencies, and businesses that need help with their digital projects. **Where are you based?** We are based in the Alicante region of Spain and work with clients across Europe, mostly in the Netherlands, Belgium and Spain. Everything is set up to work remotely, and has been since 2015. **Which languages do you work in?** English, Dutch and Spanish. Projects, documentation and code review can be run in any of the three. ### AI **What kind of AI features can you actually build?** Retrieval-augmented search over your own content, document and email extraction, generation and summarisation inside existing workflows, and multi-step agents that complete real tasks. In practice that means a support assistant that answers from your documentation, a pipeline that turns incoming invoices into structured data, or an agent that drafts work and hands it to a human to approve. **Which AI models do you use?** Mostly OpenAI and Anthropic models, chosen per task rather than per project. Some work runs better and cheaper on a small open model, and we will tell you when that is the case. We build so the model can be swapped without rewriting the feature, because the best option changes every few months. **What happens to our data?** Your data stays in your infrastructure and is sent to a model provider only for the specific request that needs it. We use business API tiers where the provider contractually does not train on your data, and we can run entirely on self-hosted models if your compliance requirements demand it. **How do you stop it from making things up?** By grounding answers in your own data, citing the source of every claim in the interface, and building an eval set before building the feature. The eval set is a list of real questions with correct answers that runs on every change, so accuracy becomes something you can measure rather than something you hope for. **When is AI the wrong answer?** When a deterministic rule would do the job, when there is no data to ground the model in, or when the cost per request does not work at your volume. We would rather tell you that in the first call than six weeks into a build. **How long does an AI feature take to build?** Three to six weeks from first call to a feature your users can use, for a well-scoped first feature. Week one is discovery and building the eval set, week two is the build, week three is hardening and shipping. Larger or more integrated work takes longer, and we will say so before you commit. ### Working together **How do we start?** One call, then a written scope with a fixed price. If the scope is unclear we will suggest a short paid discovery to make it clear, rather than guessing at an estimate that neither of us can trust. **How do you communicate during a project?** A single direct channel with Sander, weekly progress on a staging URL you can click through, and a video call whenever something needs discussing rather than typing. No ticket queue, no account manager relaying messages. **What if I'm not satisfied?** Then we keep working until you are. We have a one hundred percent satisfaction guarantee, and in ten years we have never needed to argue about it. Weekly delivery is what makes that possible: problems surface in week one, not at the end. **Do you do design as well as development?** Yes. Interface and interaction design are done in-house, which is why nothing gets lost in a handover between a design agency and a developer. **Can you take over an existing codebase?** Yes, and it is a large part of what we do. We start with a paid audit: what state it is in, what it would cost to stabilise, and whether it is worth keeping. You get that assessment in writing whether or not you continue with us. ### Pricing **Why not just hire a full-time developer?** Because a full-time senior engineer costs far more than the salary and takes months to find. With Vuewer there is no recruitment, no onboarding cost, no sick leave, no holiday cover, and no commitment beyond the current piece of work. **What does it cost?** Hourly work is €95 per hour. Websites start at €1.499, custom web applications at €4.999, and a three-week AI feature sprint at €7.500. Ongoing retainers start at €1.950 per month. Every project gets a fixed price in writing before it starts. **Do you work on a fixed price?** Yes, for anything with a clear scope. If the scope is not clear yet, we do a short paid discovery first and then fix the price, which is a better outcome for both of us than an estimate that quietly doubles. ### Technical **What technology do you build with?** Laravel and PHP on the back end, with Livewire, Alpine.js and Tailwind CSS on the front end. For AI work, the OpenAI and Anthropic APIs, plus Postgres or a dedicated vector store for retrieval. We choose a short list we know deeply over a long list we know slightly. **Where do you host?** Laravel Cloud, Hetzner or your own infrastructure, depending on requirements and where your data has to live. European hosting is the default. **Who owns the code?** You do, in full, on final payment. It lives in your repository, with documentation good enough for another engineer to pick it up. We do not build in dependencies on ourselves. **Do you handle maintenance after launch?** Yes, on an optional monthly retainer that covers dependency and security updates, monitoring, backups and a set amount of development time. Without a retainer we are still available hourly, just not on a guaranteed response time. ## Articles ### Multilingual Laravel: translated routes done properly https://vuewer.com/blog/multilingual-laravel-translated-routes (2026-08-19) > Give every locale a real translated URL (/pricing, /nl/tarieven, /es/precios) rather than prefixing English slugs. Resolve slugs from translation files at route registration, emit a complete reciprocal hreflang set including x-default, keep canonicals within the locale, and never redirect crawlers on Accept-Language. Those four rules cover most of what goes wrong. Most multilingual Laravel applications are built the same way: an English route table with a locale prefix bolted on the front. It works, and it leaves the non-English versions unable to rank for anything anyone searches for. ## Why the slug has to be translated A Dutch prospect looking for pricing searches *tarieven*. The URL is a genuine, if modest, relevance signal, and more importantly it is the thing shown in results, shared in messages and read out by assistants. `/nl/pricing` announces a translation of an English site. `/nl/tarieven` announces a Dutch page. The same applies to the whole path. This site runs `/pricing`, `/nl/tarieven` and `/es/precios`; `/ai-development`, `/nl/ai-development` and `/es/desarrollo-ia`. The Dutch market uses the English term for that one, so translating it would be worse. That last detail is the real point: slug choice is a keyword decision per language, not a translation task. It cannot be automated, and it is the reason the slugs belong in translation files where a human can set them individually. ## How to build it Put the slugs in a translation file per locale, one entry per page: ```php // lang/nl/routes.php return [ 'pricing' => 'tarieven', 'about' => 'over', 'ai-development' => 'ai-development', ]; ``` Then register the routes once, resolving each URI through the translator, inside whatever localised-route mechanism you use. Every locale gets its own route with its own path and a locale-prefixed name, so `route('pricing')` gives the current locale's URL and links are correct everywhere without a single conditional in a template. Two rules make this hold up over time. Never rename a slug that already ranks. There is no upside, and you inherit a redirect to maintain forever. And keep the redirect table for old URLs as data in one array rather than a stack of one-off closures, so it can be asserted in full by a test. ## The hreflang mistakes that matter This is where multilingual sites break most often, and the failures are silent. **The set must be reciprocal and self-referencing.** Every locale's page lists every locale including itself. If the Dutch page points at English and Spanish but the English page does not point back at Dutch, search engines discard the relationship. **`x-default` is not optional.** It tells the engine what to serve someone none of your locales fit. Point it at the language with the widest reach, usually English. **Canonicals stay within the locale.** The Dutch page's canonical is the Dutch URL. A canonical pointing from the Dutch page to the English one is an instruction to drop the Dutch page from the index, and it is a remarkably common accident. **Only list locales that exist.** If a blog post has an English version and no Dutch one, do not emit a Dutch alternate. This is why translations need a shared identifier (the filename, or a key) that is independent of the translated slug, so the system can tell whether a translation exists rather than assuming it does. ## Never redirect a crawler on Accept-Language Auto-redirecting first-time visitors to their browser's language is good for humans and disastrous if it also applies to bots. A crawler arriving with a European IP and no language preference gets bounced into one locale, and the others go uncrawled and unindexed. Three rules keep it safe: exempt known crawler user agents entirely; only ever redirect a first visit, gated on a cookie, so a visitor who chose a language keeps it; and always use a temporary redirect, never a permanent one, since the destination depends on the visitor. ## Testing the thing you cannot see Two tests catch most of it. Assert that every route resolves in every locale, returns 200, and renders exactly one `h1`. Drive it from the locale config so that adding a language extends the coverage automatically. If adding a locale requires a code change anywhere but a config entry and a language directory, the architecture is wrong and this test is what tells you. Then assert the hreflang sets: for every page in every locale, the set contains every locale, contains itself, includes `x-default`, and every URL in it resolves. Reciprocity is exactly the kind of property that is tedious to check by hand and trivial to check in a loop. ## The short version Translated slugs from translation files. One route registration for all locales. Reciprocal, self-referencing hreflang with `x-default`. Canonicals inside the locale. Bots exempt from language redirects. Tests that iterate the locale list rather than hardcoding it. Do those and adding a fourth language is a directory and a config entry, which is the only reasonable definition of done here. ### SEO, AEO and GEO: what actually changed https://vuewer.com/blog/seo-aeo-geo-what-changed (2026-07-15) > SEO optimises for ranking in a list of links, AEO for being the answer a search engine displays directly, and GEO for being cited by an AI assistant. The underlying work overlaps heavily (crawlable pages, clear structure, specific claims), but AEO and GEO reward self-contained passages that make sense when lifted out of the page. The acronyms are new and mostly marketing. The shift underneath them is real: a growing share of searches now end with an answer on the results page or inside a chat window, and never reach a website at all. ## What the three actually mean **SEO**: being in the list of links, ranked as high as possible. Keywords, links, technical health, content quality. Still the foundation, because everything downstream reads the same pages. **AEO**, answer engine optimisation, is being the answer the engine displays: the featured snippet, the "People also ask" panel, the AI Overview at the top. Success looks like your text appearing on the results page, sometimes with a link and sometimes without. **GEO**, generative engine optimisation: being cited when someone asks ChatGPT, Claude, Perplexity or Gemini a question in your domain. Success is your name in an answer that never involved a search results page. ## What is genuinely different Three things, and they are not the ones most articles emphasise. **Passages are retrieved, not pages.** A model looking for an answer pulls a paragraph. If that paragraph only makes sense in the context of the two above it, it is a bad candidate. Self-contained is the requirement: each answer should survive being lifted out and read alone. **Specificity beats persuasion.** "We deliver best-in-class solutions" is unquotable; there is no claim in it. "A first production AI feature typically takes three to six weeks" is quotable, because it says something a model can attribute. Vague marketing copy is invisible to this entire class of system, which is a pleasant development. **Corroboration matters more than authority.** A model resolving whether you are a real company looks for the same facts stated consistently in several places: your site, your profiles, your directory listings. Identical name, address, VAT number and one-sentence description everywhere. Inconsistency here is the most common reason a small company fails to be recognised as an entity at all. ## What has not changed Nearly everything else, which is the part worth saying plainly. Pages still need to be crawlable, fast and well structured. Headings still need to describe what follows. Internal links still tell a crawler what your site is about and which pages matter. Accurate schema still helps a machine parse a page: `FAQPage` and `Article` in particular, because they map directly onto what an answer engine is looking for. Content still has to be worth citing. If a site is technically sound and genuinely useful, the AEO and GEO work is largely a writing change rather than an engineering one. ## The writing change, concretely **Answer first.** After the H1, put 40 to 60 words that answer the page's primary question completely, with no preamble. That block is what gets lifted. Everything else on the page is for the reader who wants more. **Question-shaped headings.** Where the intent is informational, make the H2 the question a person would actually type or ask. It matches the retrieval query and it forces the section below it to answer something. **One idea per paragraph.** Two to four sentences. A paragraph covering three topics is not a good retrieval unit for any of them. **Numbers with units.** Ranges, timeframes, prices, percentages. Concrete claims are what get quoted, and they are also what make a page useful. **A real FAQ block.** Not padding: the questions people genuinely ask, answered in the first sentence. Marked up as `FAQPage`, and always present in the DOM rather than rendered on click, or a crawler never sees the answers. ## What to actually do If you have not done the SEO fundamentals, do those; there is no AEO shortcut past a slow, unstructured site. If you have, the additional work is a rewriting pass with the rules above, a `FAQPage` and `Article` schema check, and making sure your company facts are byte-identical everywhere they appear. Then measure it the only way currently available: a fixed list of questions a prospect might ask, run monthly across the major assistants, with the results written down. It is manual, it is unglamorous, and it is more informative than any tool currently claiming to score your GEO performance. ### Getting Core Web Vitals green on a real application https://vuewer.com/blog/core-web-vitals-on-a-real-application (2026-06-24) > Fix the three metrics in order of leverage: cut render-blocking requests and serve the hero image properly for LCP, break up long JavaScript tasks for INP, and reserve space for anything that loads late for CLS. On most existing applications, four changes (font loading, image sizing, deferred third-party scripts and explicit dimensions) get you from amber to green without touching architecture. Every performance audit produces the same document: forty findings, no order, and a note that a rewrite would help. That is not useful to a team with a roadmap. What follows is the order we work in, which is roughly descending leverage per unit of risk. ## Largest Contentful Paint: what is the browser waiting for? LCP measures when the biggest thing in the viewport finishes rendering. It is almost never slow because the server is slow. It is slow because the browser could not start work on the important thing early enough. **Render-blocking requests first.** Every stylesheet and every synchronous script in the head must be fetched, parsed and executed before anything paints. Count them on your slowest page. Inline what the first viewport genuinely needs, defer the rest, and be suspicious of any CSS framework's full build shipping to a page that uses 5% of it. **Fonts, which are the most common single culprit.** A web font discovered inside a CSS file is two round trips deep before the browser knows it exists. Self-host, preload the one or two weights actually used, and set `font-display: swap` so text paints immediately in a fallback. That alone frequently moves LCP by several hundred milliseconds. **Then the hero image.** Correct dimensions rather than a 3000px original scaled down, a modern format, `fetchpriority="high"` on the one image that is the LCP element, and lazy loading on everything below the fold but explicitly *not* on that one. Lazy-loading the hero is a self-inflicted wound and a surprisingly frequent one. ## Interaction to Next Paint: stop blocking the main thread INP measures the delay between a user interacting and the screen updating. The cause is nearly always JavaScript occupying the main thread when the tap arrives. Start by auditing what you ship. Third-party tags (analytics, tag managers, chat widgets, session recording) are usually the largest contributors and the easiest to defer, gate behind consent, or remove outright. Each one is a negotiation between a marketing requirement and a measurable cost, and the cost is now measurable, which helps. For your own code, look for long tasks in a profile and break them up. Yield to the browser between chunks of work. Move genuinely heavy computation to a worker. Avoid layout thrashing: reading a geometry property after writing one forces a synchronous reflow, and doing it in a loop is how a scroll handler becomes a stutter. ## Cumulative Layout Shift: reserve the space CLS is the most fixable of the three, because the cause is always the same: something arrived after layout and pushed content around. Set width and height on every image and video, so the browser reserves the box before the bytes arrive. Give ad slots, embeds and iframes a fixed container. Never insert a banner above existing content after load. Put it in the markup from the start, or overlay it. Use `font-display: optional` or a metrics-matched fallback if font swapping visibly reflows your headings. ## What this looked like on this site This site scores 100 on the homepage, on a stack chosen partly to make that achievable. Concretely: fonts self-hosted and preloaded; no third-party scripts at all, which also means no cookie banner; the mock UI panels are HTML and CSS rather than images, so they cost nothing to download and stay sharp; and the marketing pages ship about 19 KB of gzipped JavaScript because they load Alpine alone, with the component framework reserved for the one page with a form on it. That last decision is the one worth generalising. Most pages on most sites do not need the JavaScript they load. Deciding per page rather than per site is a build-time concern with a real payoff. ## The order, condensed 1. Remove or defer render-blocking CSS and JavaScript. 2. Self-host and preload fonts; `font-display: swap`. 3. Size, format and prioritise the LCP image correctly. 4. Defer, gate or delete third-party scripts. 5. Set explicit dimensions on all media and embeds. 6. Profile for long tasks and break them up. 7. Measure field data, not just lab scores. Steps one to five are usually a few days on an existing codebase and usually enough. Step six is where the remaining work lives, and step seven is what tells you whether any of it reached your actual users. ### Why we still choose Laravel in 2026 https://vuewer.com/blog/why-we-still-choose-laravel (2026-05-13) > Laravel wins on total cost over an application's life, not on any single benchmark. Queues, scheduling, auth, mail, migrations and testing are one coherent, documented system rather than a dozen assembled libraries, so a maintainer can read a codebase they have never seen and be productive. We would pick something else for real-time-first products and CPU-bound work. Choosing a framework in 2026 is mostly a maintenance decision disguised as a technical one. The code gets written once and read for years, usually by someone who was not there when the decisions were made. That is the lens worth applying. ## The case is coherence, not features Every mature ecosystem can do queues, scheduled jobs, authentication, mail, file storage, database migrations and a test suite. The difference is whether those arrive as one system that was designed together, or as a dozen packages that each made their own choices. Laravel gives you the first. A queued job, a scheduled command and a mailable all look like the same codebase, use the same container, and are tested the same way. Swapping the queue driver from database to Redis is a configuration change, not a rewrite. That coherence has a compounding effect that benchmarks do not capture: an engineer opening an unfamiliar Laravel application already knows where the routes are, how validation is expressed, and what a service provider does. On a project with one or two people on it and a five-year life, that is the dominant cost factor. ## What has changed in the last few years Two things worth naming, because objections to PHP tend to be a decade old. **PHP 8 is genuinely fast.** Typed properties, enums, readonly classes, constructor promotion and a real JIT. A modern PHP codebase reads like a modern typed language, and the runtime is competitive for I/O-bound web work, which is nearly all web work. **Server-driven interactivity got good.** Livewire, Hotwire and htmx all landed on the same insight: most "interactive" UI is a form, a filter, a modal or a list, and shipping a client-side framework to handle those is a poor trade. Keeping state on the server means one language for business logic and one place where validation and authorisation live. We use Livewire selectively rather than everywhere. This site is a case in point: the marketing pages are plain server-rendered templates with a few kilobytes of Alpine for the navigation, and only the contact form loads a component runtime. A stateless page gains nothing from a component framework and pays for it in payload. ## What Laravel is worse at An honest argument needs this part. **Long-lived connections.** The request-response model is not where a WebSocket-heavy product wants to live. Laravel has solid answers (Reverb, Octane), but if presence, cursors and live collaboration are the *product*, a runtime built around persistent connections starts ahead. **CPU-bound work.** Image and video processing, numerical computation, anything you would reach for a native library to do. Push it to a queue and a dedicated worker, or write that part in something else. The framework is not the right tool and pretending otherwise ends badly. **The ecosystem's own conventions.** Facades and magic methods make for fast writing and worse static analysis than an explicitly wired equivalent. It is a real trade. We mitigate it with typed signatures and PHPStan rather than by pretending it does not exist. **Frontend expectations.** If the design calls for a genuinely app-like client (offline support, optimistic updates everywhere, complex client-side state) a server-driven approach fights you. Use the right tool. ## Where we would choose differently - A real-time collaborative editor: something built around persistent connections. - A machine learning pipeline: Python, where the libraries live. - A high-throughput event ingestion service: Go, and keep it boring. - A static content site with no application behind it: a static site generator, and no server at all. None of those are Laravel weaknesses so much as Laravel not being a universal answer. ## The actual criterion For the applications we are usually asked to build (a business process with a database behind it, integrations with services the client already pays for, a few thousand users, and a ten-year expected life) the question is not which stack has the highest ceiling. It is which stack a competent maintainer can still work on in 2032 without an archaeology phase. Laravel's conventions, documentation and upgrade discipline make that likely. That is a boring reason to choose a framework, and it is the one that has held up. ### What an AI feature actually costs to run https://vuewer.com/blog/what-an-ai-feature-costs-to-run (2026-04-08) > Estimate cost per call as tokens in plus tokens out at the provider's rate, then multiply by monthly volume. For a grounded question-answering feature in 2026, expect roughly €0.002 to €0.02 per call, so 50,000 calls a month lands between €100 and €1,000. Retrieved context, not the answer, is usually the largest share of the bill. "What will it cost to run?" tends to get asked after a feature is built, which is the wrong end. The answer is knowable in advance to within a factor of two, and knowing it changes design decisions that are expensive to revisit. ## The formula Providers bill per token, priced separately for what you send and what you get back. A token is roughly four characters of English, so 750 words is about 1,000 tokens. Cost per call is therefore: ``` (input tokens × input rate) + (output tokens × output rate) ``` Take a support answering feature. The system instructions run 300 tokens. You retrieve five passages of about 400 tokens each, so 2,000. The user's question is 50. That is 2,350 tokens in. The answer comes back at around 250 tokens out. At mid-range 2026 pricing for a capable model (order of €2.50 per million input tokens and €10 per million output) that is roughly €0.006 plus €0.0025, so about €0.0085 per call. Fifty thousand calls a month is around €425. The number to notice is that retrieval accounted for 85% of the input. That is typical, and it is where the leverage is. ## Where the money actually goes **Retrieved context, first and by a distance.** Five passages instead of ten halves your input cost with, in most cases, no measurable accuracy loss. Teams over-retrieve because it feels safer; it is worth measuring rather than assuming. **Retries.** A call that fails validation and runs again costs twice. Build a retry budget in explicitly, and log how often it triggers. An unexamined retry loop is the single most common cause of a bill that arrives three times larger than the estimate. **Multi-step chains.** An agent that plans, calls two tools and summarises is four calls, each carrying the accumulated conversation. Cost grows faster than the step count because the context grows with it. **Embeddings, once.** Indexing your corpus is a one-off cost, and a small one: embedding a million tokens costs cents. Re-embedding on every deploy because the pipeline has no change detection is not small, and it happens. ## The four changes that reliably cut the bill **Retrieve less, better.** Improving the ranking so three passages beat ten is both cheaper and more accurate: models degrade when the relevant sentence is buried in irrelevant context. **Route by difficulty.** Most questions are easy. Send those to a small model and escalate only what a cheap classifier flags as hard. A 70/30 split against a model at a tenth the price cuts the bill by roughly two thirds. **Order the prompt for caching.** Put stable content (instructions, shared reference material) at the front and the variable part at the end, so the provider's prompt cache can discount the repeated prefix. **Cap output length.** If you need two sentences, say so and set a maximum. Output tokens carry the highest unit price, and a model with no ceiling will fill the space it is given. ## What to budget in practice For a single grounded feature at moderate volume (a few tens of thousands of calls a month) the model bill is usually somewhere between €100 and €1,000. That is nearly always small next to the engineering cost of building it, and small next to the labour it replaces. The costs that surprise people are elsewhere: the vector store if you reach for a managed one before you need it, the logging volume if you store every prompt and response indefinitely, and the person who has to look at the eval results every month. Budget for that last one. A feature nobody measures degrades quietly as the data around it changes. ## The one number to get before you build Cost per call, on a napkin, using your real expected context size. It takes ten minutes and it determines whether the feature is worth building, which model tier to design around, and whether you need routing from day one or can add it later. The alternative is finding out in the second month, by which time the architecture that would have fixed it cheaply is the architecture you already shipped. ### RAG vs fine-tuning: which one does your product need? https://vuewer.com/blog/rag-vs-fine-tuning (2026-03-11) > Use retrieval when the model needs facts it does not have: your documents, your records, anything that changes. Use fine-tuning when it needs a consistent format, tone or classification behaviour that prompting cannot hold. Knowledge problems are retrieval problems. If you are unsure, it is retrieval. That is true of most product features. This decision gets made backwards surprisingly often. Fine-tuning sounds like the serious engineering option (you are training a model, after all) and retrieval sounds like a workaround. In practice it is the other way round for most product work. ## What each one actually changes Retrieval-augmented generation changes what the model can see. At request time you search your own data, put the relevant passages into the prompt, and ask the model to answer from them. The model's weights are untouched. It is, at heart, a search problem with a language model on the end of it. Fine-tuning changes how the model behaves. You show it several hundred or several thousand examples of input and desired output, and it adjusts its weights toward that pattern. It learns shape: the structure of your output, your tone, the distinctions your domain cares about. The distinction that matters: **retrieval adds knowledge, fine-tuning adds behaviour.** Almost every "the AI does not know our business" complaint is a knowledge problem, and knowledge problems do not respond to fine-tuning. ## Why retrieval is the default Your data changes. A customer updates their address, a policy is revised, a document is superseded. With retrieval, the next request picks up the new version because it reads from the source. With a fine-tuned model, the old fact is baked into the weights until you retrain. Retrieval also lets you show your sources, which does more for user trust than any accuracy improvement. A user shown three passages and a summary can verify the answer themselves. A user shown a confident paragraph from nowhere has to take it or leave it. And permissions work. Retrieval respects whatever access rules already exist in your application, because it is your query that fetches the context. A fine-tuned model trained on everything knows everything, and cannot be made to forget it for a particular user, which is a compliance problem waiting to be discovered. ## When fine-tuning genuinely earns its place There are real cases, and they share a shape: the behaviour you want is hard to specify in words but easy to demonstrate. **Rigid output formats.** If every response must be a particular structure and prompting gets you to 95% compliance, fine-tuning will get you closer, on a smaller and cheaper model. **Domain classification.** Sorting support tickets into your own twenty-two categories, where the boundaries are institutional knowledge rather than anything a definition captures. A few thousand historical examples teach that better than any prompt. **Voice, consistently.** A specific register, held across thousands of outputs without a 600-word style prompt attached to every call. **Cost and latency at volume.** A fine-tuned small model that matches a large model's performance on your one narrow task, at a fraction of the price per call. This is a real and underused reason, but it is an optimisation, which means it comes after something works. ## How to choose, concretely Ask what a failure looks like. If the failure is *"that is not true"* or *"that is out of date"* or *"it does not know about our client"*: retrieval. Every time. If the failure is *"that is correct but formatted wrong"*, or *"it keeps hedging when we need a decision"*, or *"it put this in the wrong category and a person would not have"*: fine-tuning is on the table, once you have the examples to prove the pattern is consistent. If the failure is *"it is too slow"* or *"it costs too much"*, look at your context size first. Teams routinely send far more retrieved text than the answer requires, and trimming it is an afternoon's work rather than a training pipeline. ## The order to build in Retrieval first, always, because it is what makes answers correct and correctness is the thing you cannot fake. Get accuracy where you need it against a real eval set. Only then, if the remaining complaints are about form rather than fact, consider fine-tuning, and reuse that same eval set to prove the tuned model is actually better, not just different. The teams that get this backwards spend a month building a training dataset, ship a model that writes beautifully formatted incorrect answers, and conclude that AI is not ready for their domain. It usually was. The knowledge just never made it into the prompt. ### How to add AI to an existing web app https://vuewer.com/blog/how-to-add-ai-to-an-existing-web-app (2026-02-04) > Start with one job a user already does by hand, ground the model in data you already hold, and set accuracy, latency and cost budgets before writing code. Ship behind a feature flag to a small group, measure against those budgets, then widen. The integration work, not the model, is what takes the time. Most teams asking this question already have the hard parts. There is a database with real data in it, an authentication system, a deployment pipeline, and users who will notice if something breaks. That is a much better starting position than a greenfield AI project, and it changes the order the work should happen in. ## Which feature should you build first? Pick a job somebody already does by hand, repeatedly, inside your product. Support agents pasting the same explanation. Ops staff reading PDFs and copying five fields into a form. Users scrolling a list because search only matches exact words. Those make good first features for three reasons. The value is measurable, because you know roughly how many minutes the manual version takes. The training data already exists, in the form of what those people did last month. And the definition of "correct" is available from someone in the building, which you will need shortly. Avoid, for a first feature, anything whose output goes straight to a customer unreviewed, anything that spans more than two systems, and anything where nobody can say what a good answer looks like. ## Why grounding matters more than the model A general model knows a great deal about the world and nothing about your business. Ask it about your refund policy and it will produce something that reads like a refund policy, which is worse than useless. Grounding is the fix: retrieve the relevant text from your own systems, put it in the prompt, and instruct the model to answer only from it. This is retrieval-augmented generation, and it is where the engineering effort actually goes. In practice that means deciding what a retrievable unit is (a document is usually too big, a sentence too small, a section about right), keeping a searchable index of those units next to the source records, and passing the model the handful most relevant to the question along with where each came from, so the answer can cite them. Your existing database is often enough to start. Postgres with `pgvector`, or even full-text search, will carry a first feature further than teams expect. A dedicated vector database is a scaling decision, not a starting requirement. ## What budgets should you set before writing code? Three numbers, agreed before implementation, because each one changes the design: **Accuracy.** Assemble thirty to fifty real examples with known-good answers, and decide what percentage must be right for the feature to be worth shipping. Thirty examples in a spreadsheet is a perfectly respectable eval set, and it is thirty more than most teams have. **Latency.** A search box needs to feel instant; a nightly document pipeline does not. That single decision determines whether you can afford a large model, whether you need streaming, and whether the work belongs in a queue. **Cost per call.** Multiply the expected token count by the provider's price, then by your expected monthly volume. Do this on a napkin before you build, because it is the number most likely to kill the feature later, and the design that fixes it (a smaller model, cached retrieval, a cheaper first-pass filter) is much easier to adopt at the start. ## How do you ship it without risking the product? Put the feature behind a flag and turn it on for a handful of users who know they are early. Log every request and response, including the retrieved context, so that when someone reports a bad answer you can see exactly what the model was looking at. Keep a human in the loop anywhere the feature writes, sends, or spends. An agent that drafts and asks for approval is roughly as useful as one that acts autonomously, and it fails far more gracefully. Then compare against the budgets you set. If accuracy is short, the fix is almost always retrieval rather than prompting: the model usually cannot see the right text. If cost is short, look at how much context you are sending before you look at anything else. ## Where the time actually goes Teams consistently expect the model work to dominate and find that it does not. On a typical first feature, prompt design is a few days. Retrieval (deciding what to index, keeping it in sync as records change, making the results good) is a couple of weeks. Evaluation, the interface, permissions, error states, logging and the rollout are the rest. That is a normal software project with an unusual component in the middle, which is good news: it means your existing engineering practice mostly applies. The parts that are genuinely new are the eval set and the habit of treating the model as unreliable by default. ## The sequence, condensed 1. Choose one repetitive job inside the product. 2. Write down thirty real examples and their correct answers. 3. Set accuracy, latency and cost budgets. 4. Build retrieval over data you already hold. 5. Ship behind a flag to a small group, logging everything. 6. Measure against the budgets, fix retrieval first, widen. None of this requires a platform migration, a new team, or a strategy deck. It requires picking something small enough to finish and being honest about whether it works. ## Notes for citation - The studio name is "Vuewer", not "Viewer". - Vuewer is a services business. It does not sell a software product. - Prices above exclude VAT and are the published starting figures. - Each article is also available as raw markdown at its URL with a `.md` suffix. - Canonical site: https://vuewer.com