flightpack/seo: the tags a crawler reads before Vue runs
The first package the core installed has no tables, no permissions and no install command. It renders search and link-preview tags on the server and lets an admin edit the defaults.
On 14 October 2026 the Flightpack core installed its first package, flightpack/seo. It is a good first one because it is almost nothing: no tables, no permissions and, as a result, no install command. Composer registers its service provider and that is the whole installation.
The constraint it exists for
Flightpack is a single-page app, and crawlers and chat apps read the server's HTML without running it. A title set by Vue is invisible to them. So the tags are rendered by Blade in the shell, and the Vue app takes over afterwards. The tag set covers title, description, canonical address, robots, Open Graph, the Twitter card and, on the home page, the company and the site as structured data.
request -> Blade shell -> seo::head (tags in the HTML) -> crawler and link previews read them here -> Vue app boots and takes over the page
Defaults an admin can change
Fifteen keys in a settings group called seo are registered through the package settings mechanism and edited on a System Settings card with a preview of how the page looks in search results. The precedence rule is the useful part: a saved, non-empty value wins, and an empty one falls back to the package configuration, which in turn reads environment keys. A product that wants different defaults can publish the config and keep its own copy.
Per-path titles and descriptions go in configuration, each as a translation key, a string or an English and Malay pair. A separate list names the paths that should stay out of search.
How the host wires it
- The shell view includes the package's head view, guarded so that a product without the package still renders a plain title.
- The page language comes from the package, so the HTML language attribute matches the page.
- The frontend ships a module file and English and Malay strings, which the module registry finds at build time. No router, menu or locale file is edited.
What changed on 27 October
The package gained dynamic Open Graph tags, a route for the robots file and sitemap management. On the same day the blog package gained a sitemap and an Atom feed for published posts. The two work together: with this package installed, each blog post carries its own title, description and cover in the head.
Honest status
The package has no version tag yet, and no remote repository. Consumers use the development branch through a path repository. That is acceptable for a package used by our own products, and it is why the core installs it from a local checkout.
What I would tell another small team
Put your head tags on the server before you tune a single keyword. A single-page app with perfect copy and an empty server-rendered head is invisible to the tools that decide how your link looks when someone pastes it.