Merged
Conversation
…s audit Evidence-led inventory of the product (Mac v0.77.0, iOS 1.0), both web surfaces, references, competitors and localization, written before the rebuild so every later copy decision can cite it.
…and account plan The decision documents for the rebuild: final positioning and copy rules, sitemap with content dispositions and redirects, file-level architecture for both repositories, the visual system, and the account experience plan.
…localized error pages
…aid-features.json
…the social card brief resources/data/assets.json holds every sitemap §A.8 slot, a phone crop for each Mac window, every release-post figure and the bespoke og-site card, with the kinds design-system §6.3 pins. AssetManifest validates supplied files (widths, formats, true pixel sizes, byte budgets, light/dark parity, crop before window) and builds the lcpAsset descriptor app.blade.php reads. AssetReferences finds slot uses in TSX, content JSON and markdown. AssetManifestTest checks the real manifest and drives the supplied path on an isolated fixture with GD-drawn images.
…ctures <AssetSlot id> renders a labelled, correctly proportioned placeholder (type label, mono id, localized brief, accessible name, no image request) while the manifest says placeholder, and <picture> with srcset, sizes, dimensions, theme variants and loading priority once supplied, hiding the id and brief. The mode switches on the manifest status alone.
…fest and brief fragments php artisan assets:handoff writes docs/visual-assets.md (Vietnamese replacement steps, capture rules, kinds table, production order, per-page asset briefs with file names, the social-card state and the legacy source list with a cleanup proposal); --check fails on a stale document. Adds the fragment template and the og fragment.
…sTest The srcset and existence checks now include the manifest's supplied srcsets and legacySource files, the ladder check covers AVIF and the manifest naming, and a parser self-check replaces a count that would go red once the legacy components are deleted.
tokens.css gains the default hairline border colour, the forced-colours focus ring and the ThemeControl icon and segment states. app.css keeps only aliases the old pages still name, the banner offsets, the app-plate shadow, the article typography with a gutter permalink, and print. ColorContrastTest now parses tokens.css and asserts every design-system §2.3 pair in both themes, the gamut, hue 55 and the theme-color backgrounds.
The fifteen shared primitives (button, text-link, container, badge, status-badge, field, select, stepper, dialog, data-table, description-list, callout, copy-button, empty-state, notice-page) plus public-only section, page-header, breadcrumbs, card, disclosure, segmented-control, tabs and prose-article. The existing code, kbd, faq-list, footnote, glyph and database-mark are restyled to spec with their old exports kept. FullLine stops bleeding 100vw, SectionShell paints its band directly, and ThemedImage switches on the theme class.
…with the account app lib/theme.ts reads, applies and syncs the shared `theme` key (light by default); ThemeControl offers Light, Dark and System as a menu and a segmented control with labels as props. The consent bar moves to components/shared with one short question and equal Allow and Decline. Crisp loads only from a chat button click. Theme and third-party tests pin the head script, the absence of OS-switched images and of third-party loads in the document.
…t in both languages LandingLayout renders the skip link, the sticky banner and SiteHeader, main, SiteFooter and the consent bar itself, so every page, the error page included, gets the same chrome. The header carries Features, Databases, Pricing, Docs, Blog, the language switcher, the theme control, Account (/account?locale=) and Download; the footer has five groups, a newsletter form through useEmailForm with the page locale and no subscriber count, and Cookie settings. config/banner.php keeps only the switch (off by default), the link and the version; the words move to the banner catalog.
…ount app Nine foundation files and all fifteen design-system primitives are byte-shared; the doc lists their sha256, what a shared file may import, the call-site changes the account app needs to adopt them, and what is deliberately not shared. SharedFilesTest checks presence, header, hash, that every headed file is listed, and that shared modules import nothing app-specific.
…cast fallback and a last-good cache MacReleaseService accepts a release only if it is neither draft nor prerelease, is tagged vX.Y.Z and carries both DMGs, so a plugin release or a half-uploaded app release is rejected. When that fails it falls back to the Sparkle appcast's top item, building the DMG names and URLs from platforms.json. A fresh copy is cached for 15 minutes and a last-good copy forever, and a 5-minute failure marker stops a broken API being retried on every request. With nothing ever fetched, the release is 'unavailable' and both buttons point at GitHub's releases/latest. GitHubRepoService::stars() follows the same pattern. Every test fakes HTTP.
…orms.json Run by hand, never scheduled. It compares GitHub latest (version and publish date), the appcast (version and minimum macOS), the Homebrew cask, the lowest served version against floorVersion, and the iTunes lookup for us (version, minimum iOS, price) and de (against storefrontExclusions). It exits non-zero on any drift or unreadable channel.
…for a Mac Pure rules for the download page: iPhone, iPod and iPadOS's desktop user agent are 'ios'. Only Chromium's architecture hint picks a build, and only to highlight it. Safari and Firefox get no guess. Nothing here starts a download.
…Homebrew and the App Store card
Both DMG links are server-rendered from the release service, with sizes when GitHub provides them, a version badge, and the requirement taken from platforms.json through the platforms catalog. The page also has a 'Which Mac do I have?' disclosure, the Homebrew command with a copy button and a lag note driven by floorVersion, and an iPhone and iPad card that leads on iOS devices. It includes install and first-run steps (notarized, drivers on first pick, sample database), Sparkle updates, other platforms (not available, no date) and older versions. Nothing auto-starts; a post-click panel offers the file again. JSON-LD comes from the shared structured-data builders (#app, #ios-app, WebPage) with no rating, size or breadcrumb. download_click{location, platform} is unchanged.
…ase service The legacy /ios page still renders until its phase-C rewrite. Its header links now come from MacReleaseService and GitHubRepoService (cached, last-good, failure marker) instead of LandingController's full releases list.
…p retired paths from the registry
…captures phone crops, and load the /ios hero with priority
…ges, close the guards that could not fail, and fix the copy they caught
…d secondary columns on phones The DataTable scroll region is now position: relative. Without it, the sr-only words of an off-screen column escaped the overflow clip, and the document grew to 532px at 375px wide on /pricing, the comparisons and two feature pages. The visible caption now sits above the region, so it no longer scrolls or clips. The sticky column is painted with --table-ground, so it no longer shows a raised stripe in dark mode or a two-tone table on a band. Priority columns below 640px: the plan matrix fits all four columns in 343px; availability, the paid-features hub table, the engine tables and the comparison tables fold their secondary columns into the row header. The compare hub's five-column table folds below 1024px. /databases now uses one fixed column layout shared by every category. Monogram marks take the same footprint as vendor marks. Source markers are 12px. A marked cell shows its yes or no word, and TablePro-only rows show an explicit "Does not apply". The hub's Sources section moves to the end of the page, as its captions say.
…s, one download row, anchor-only smooth scroll - Sections: a text-width section is now a left-aligned measure inside the wide grid, so headings no longer zigzag. A plain section that follows another drops its top padding (data-rhythm), so neighbours are one --space-section apart instead of two. - Rebalanced: the platforms band, the /ios phone rows and header facts, the engine page header (the detail lead sits beside the facts card, with a 32px gap), and the pricing cards (activation directly under the price; two columns inside a card at md). - Download: the page uses PageHeader. DMG names are set in mono, and the UA status line has its room reserved. - Download bands: every band is one ActionPair row, whose captions share a line. - Sponsors: a 2x2 grid on phones; logos load eagerly at low priority; the Nimbus mark is cropped to its bounds. - Placeholders: the icon stays with its label. - Scrolling: the global scroll-behavior: smooth is removed. In-page anchors glide one jump at a time (lib/anchor-glide.ts), and Inertia's scroll reset is instant again.
…current section on mobile, label focus ring, dark selected segments
- Theme menu: Enter and Space open it with focus on the checked option, and Escape closes it from the button too. The Features and Language menus close on focus-out, and Escape is scoped to each menu.
- Busy button: it is aria-disabled and swallows clicks instead of using a native disabled, so focus stays on it. Email fields are readOnly while submitting.
- Mobile menu: marks the current row with aria-current and a 2px bar.
- Header nav: the focus ring is drawn around the label instead of the 64px link.
- New --segment-selected token: a step above the track in dark (1.36:1). The disabled Stepper fill sinks below an enabled one.
- Language switcher fallback: names where it leads ("Bài viết này chỉ có bằng tiếng Anh · Xem danh sách Blog").
… are legible - Standalone links, footer links and external links are inline text, so the arrow stays with the last word. - DotList draws separators that never start or end a line. - keepTogether holds dates and "Apple silicon or Intel" on one line. Fixed compounds use a no-break hyphen or space (in-app, Read-Only, mã nguồn mở). - Kbd uses the system UI face, which has ⌘⇧⌥⌃⏎, as an inline box. - Inline code of 32 characters or fewer never breaks.
…release refresh, bounded checkout wait, untrusted X-Forwarded-Host - LCP preload: the head script now loops over each theme's list and sets media. It requested /undefined once an image was supplied. The /ios preload takes the iPad slot's sizes (IosController::IPAD_SIZES). - EnginePaths: replaces five disagreeing copies of the engine link rule. - MacReleaseService: refreshes under a short lock and serves the last good copy meanwhile. - Checkout: gives up on the overlay script after 4s and falls back to the hosted page. - Discount field: drops answers for a code that was edited. - trustProxies: no longer trusts X-Forwarded-Host.
…ted posts by date, one newsletter form on /blog, no repeated legal contact line - /vi/account and /vi/checkout 404s link /account?locale=vi. - The English-only fallback: the post title shows as text, and the Button carries the page's own words. - The 500 page reads the support address from facts.json. - Related posts are listed newest first. - The blog index turns off the footer newsletter. - Privacy and Terms no longer repeat the contact line under their own Contact section. - The VI FAQ docs sentence is reworded.
…ependent of composer dev - Removed: GitHubRepoService and its test; ui/tabs and ui/footnote; the runtime halves of lib/data/engines.ts and comparisons.ts; sponsorLogoSrc and formatPrice; the reversed i18n/paths absoluteUrl; the SEOHead breadcrumbs prop and buildBreadcrumbJsonLd; the legacy banner copy props; unused catalog keys in both languages. - Tests: skip guards that turned a missing data file into a silent skip are gone. - TestCase points the fake Vite's hot file at a path that never exists. While public/hot exists, every SSR page test used to fail with a 500.
v0.77.1 (build 135) shipped on GitHub and Sparkle on 2026-10-03. Homebrew still serves 0.77.0, so the copy floor stays there. The release adds New… for SQLite, DuckDB and libSQL files and fixes the editor and Oracle; no engine fact changed, so the engine data is re-dated to the new tag.
Member
Author
|
Companion PR: TableProApp/license#87 (account and transactional half). Merge it first, on the same day, and only after the P1 imagery is supplied. |
…les exists The php CI job installs no npm packages, so the check now skips there and runs in the ssr job, which does. With REQUIRE_SSR set it fails instead of skipping, so the ssr job cannot pass it by accident.
Vietnamese pages now use Apple's own Vietnamese badge ("Tải về trên App Store"),
black for the light theme and white for the dark one, labelled with that text
and without lang="en". The badge reads the page language itself, so a caller
can no longer pair a label with the wrong artwork.
…m and the site social card The 34 release-post figures (AVIF and WebP, with personal details covered) and the four iCloud sync diagrams (per locale and theme) are now supplied. So is the bespoke og-site card, which replaces the generated card on every page that has none of its own. The manifest, the slot data and the handoff document are regenerated. Tests that found a slot by data-asset-id now use renderedSlotSelector(), which matches a placeholder by its id and a supplied slot by the file it renders.
…e site social card
…lice for real images The placeholder walk now accepts a supplied slot as a <picture> with no placeholder box, and the gzip ceiling on the bundled slot data moves to 18 KB, measured with the Mac captures in place.
…and database pages 64 entries move from placeholder to supplied: the hero window, the feature workflows, every engine page that can run on a Mac (PostgreSQL, MySQL, SQLite, MongoDB, Redis, SQL Server, Oracle, ClickHouse, DuckDB, Cassandra, DynamoDB, etcd, Elasticsearch, SurrealDB, Trino, Beancount, Kafka) and the three 0.70 figures, each with its phone crop where the kind has one. Captured from TablePro 0.77.1 on sample data in an isolated build, light and dark from one state, exported as AVIF and WebP in sRGB within each kind's byte cap. Captures that failed review (a focus ring, an editor diagnostic, cut statements in phone crops, a missing production tag, a scrolled Query Insights view, the Copy To review and the Export dialog) stay placeholders until they are reshot. The Oracle brief now names 23ai Free, the image that runs on Apple silicon.
…ots and six new Mac captures The 140 new AVIF/WebP files that the next commit's manifest entries reference: all 11 iOS and iPadOS slots (phones at 280/560/840 from 840x1821, the iPad at 720/1008/2016 from 2016x1511, its crop at 343/686), and Copy To, the Elasticsearch console and its crop, Export, Import mapping, Query Insights and its crop, and the Touch ID prompt and its crop. Nothing references them yet, so this commit renders exactly like its parent.
…es, and redo 20 flawed ones Flips 20 slots to supplied (all 11 iOS and iPadOS slots and 9 Mac) and replaces the files of 20 that were already supplied, fixing the flaws QA found: focus rings, the editor's error underline, Query Insights scrolled past its chart, Export reading '3 table', no production colour on Touch ID, mid-token wraps in the AI chat. The 0.70 figure 1 becomes 1408:1068. Alt text is corrected in English and Vietnamese for 10 entries. Regenerates the handoff and the bundled slot slice (17.1 KB gzipped). Tests: the icon-and-label check renders ios-connection-list as a placeholder whatever its status, and the /ios test expects the manifest's iPad preload instead of null.
The review lists ENUM columns that reach PostgreSQL as VARCHAR without their allowed values. It treats TINYINT(1) to BOOLEAN as lossless and never lists it, so the old example described something the app does not do and the capture beside it showed otherwise.
…one crops Supplies mac-connection-ssh-form, mac-engine-picker, mac-edit-preview-sql and mac-structure-ddl-preview, with their phone crops (72 AVIF/WebP files). In 0.77.1 no native 343 pt cut holds what their briefs ask for. Per the owner's decision of 2026-10-04, the crops are scaled down uniformly: the SSH form at 0.667x (4:5), and the other three at 0.635x with the 1:1 aspect. The mobile-crop kind note now allows a scale down to 0.6x, and each crop's brief records its scale. The SSH form's alt now says key authentication instead of a private key. The page shows the detail's alt over both images, and the phone crop uses SSH Agent. The engine picker crop's alt describes the 0.77.1 list instead of tiles. Regenerates the handoff and the bundled slot data.
Landing/ came with the site when it was split out of the platform app, where it set the public pages apart from the account, API and webhook controllers. Every controller here serves a public page, so the folder grouped nothing. Route names are unchanged.
Homebrew now serves 0.77.1, so every Mac channel's lowest served version is 0.77.1 and release:check reported drift. Raising the floor drops the "since 0.77" labels that only mattered while Homebrew lagged.
datlechin
marked this pull request as ready for review
October 4, 2026 18:53
datlechin
added a commit
that referenced
this pull request
Oct 4, 2026
…40) changed() piped the changed-path list into grep -q. grep exits on its first match, and under set -o pipefail the printf still writing into the closed pipe failed the whole test once the list passed 64 KB. The 1,584-file rebuild (#38) therefore reported php=false and content=false: it shipped without rebuilding the caches, reloading PHP-FPM or regenerating the sitemap, and the smoke test answered 500. A here-string has no pipe. The new test runs the script's own changed() under its shell options against a list larger than the buffer; it fails on the old definition.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Rebuild delivery summary
The website rebuild of
tablepro.app, delivered on therebuildbranch of both webrepositories: this one (
TableProApp/web, the public site) andTableProApp/license(the account, checkout and transactional pages on the same origin). This document answers
the rebuild brief's delivery checklist point by point for this repository. It points to
the design documents rather than repeating them.
Section references such as "architecture §1.7" or "positioning §11" point to
docs/rebuild/design/{architecture,design-system,positioning,sitemap}.md. The rebuildbrief, the research notes, evidence matrix, stale-claim list, baseline and other working
records behind those documents are kept privately and are not part of this repository.
State. The account half is merged (TableProApp/license#87 and #88). This PR is still a
draft and nothing in it is merged or deployed. No provider dashboard, mailbox or production
database was touched. The page controllers live directly in
app/Http/Controllers(theLanding/folder came from the platform app and grouped nothing here).1. Positioning and headline
Final copy: positioning §1. The category-first proposal won; two grafts came from the
durable-identity and workflow-first proposals.
<title>Why it fits today and later. The headline names the category and the audience, not a
platform. The platforms live in a separate availability layer that is rendered from
resources/data/platforms.json: the title's{deviceList}, the captions under eachaction, the header and footer platform links, and the structured data. Adding Windows,
Linux or Android means adding a platform entry. The headline does not change, and no
sentence claims parity between apps (positioning §3, §13 guard tests). Every claim holds
on the Mac builds being served when the copy was finished (0.77.1 on GitHub and Sparkle,
0.77.0 on Homebrew) and on App Store 1.0 (build 22). Copy contains no typed counts: counts are derived from data
(
NoTypedCountsTest).2. Sitemap and dispositions
Final sitemap: sitemap §A (51 paired pages, 102 URLs; the English-only blog set; legal;
system responses). Keep, rewrite, merge, archive, redirect and remove decisions for every
existing, historical and inbound URL: sitemap §C.
CockroachDB and PGlite → PostgreSQL, ScyllaDB → Cassandra). Kafka was added.
/compare/azimuttanswers a branded 410.English only and are listed on
/vi/blogas English articles (noindex).resources/data/redirects.jsonholds every 301 and 410, read byRedirectMap(architecture §1.7). Each redirect lands on a 200 in one hop and keeps
refandutm_*.public/sitemap.xml: 113 URLs, alternates on the 102 paired URLs. The sitemap and thehead tags come from one registry (
PageRegistry).3. Product evidence, release applicability and factual corrections
the store listing, and its release applicability (0.77.x against 0.76.1 against iOS
1.0) was reconciled. The copy floor (
platforms.mac.floorVersion) is 0.77.0, thelowest version any channel serves, so no page needs a version label today. A feature
newer than the floor would get one from the data. 0.77.1 (2026-10-03) adds New… for
SQLite, DuckDB and libSQL files plus editor and Oracle fixes; no engine fact changed.
2 Team). The site now names them from
paid-features.jsoneverywhere.describe current behaviour. Polar is named as the merchant, Cloudflare Web Analytics
and GA4 are disclosed, and the refund policy states 7 days on every plan.
key browsing and the iPad sidebar are not claimed, and the blog post carries a dated
correction.
4. Research references and the principles applied
The reference set (Zed, Raycast, Linear, Proxyman, 1Password, Things, Tower, Notion,
Obsidian, TablePlus, Beekeeper Studio, DataGrip, DbVisualizer, Postico, DBeaver, Navicat;
Apple, Google and W3C guidance) produced a set of synthesized principles. The principles
were all applied; the design documents state the rules they decided (design-system §1).
data. Each destination has its own verb. The header stays short and conventional.
Platform scope is described positively, with no parity claim.
Apple silicon and Intel links. It gives the requirement, Homebrew and honest
after-click steps, and falls back to the releases page.
currency from
pricing.json. The pages say what happens when payment stops. Paidfeatures are a matrix with one line each. Account is in the header and footer.
the equivalent page without ever redirecting. No Vietnamese shells for English
content. Money and product terms are consistent in Vietnamese. Translation
completeness is tracked as data (
ContentParityTest).5. Screens and languages
/) and Vietnamese (/vi). The locale allowlist isresources/data/locales.json, mirrored in the account app.503 pages in the path's language. A Vietnamese URL for an English-only page explains
this and links the English page. A Vietnamese account or checkout URL links
/account?locale=vi.Overview, Machines, Team, Library, thank-you, and newsletter
confirm/unsubscribe. Language is a stored preference set by an explicit
?locale=orform field, and transactional mail follows it. The cross-app contract is architecture §2.
/vi/bloglists them labelled "(tiếng Anh)" and isnoindex. The documentation(
docs.tablepro.app) is English only, and each link to it says so. The legal pagesin Vietnamese state that the English version prevails.
6. Visual assets and placeholders
docs/visual-assets.md, generated byphp artisan assets:handofffromresources/data/assets.jsonanddocs/rebuild/assets/*.md. It contains a brief perasset with the scene, dataset, framing, light/dark, locale, export sizes, file names
and the manifest fields to change, with a Vietnamese summary for each.
social card): 126
suppliedand 21placeholder. All five P1 entries are supplied:the homepage hero window and its phone crop, the iPhone shot in the homepage platforms
band, and the
/iosheader iPad capture and its crop. The social card is suppliedtoo. The 21 placeholders are P2 and P3: seven database-page details with their phone
crops (Redshift, Cloudflare D1, Turso, BigQuery, Snowflake, Elasticsearch, Teradata),
mac-agent-modeandmac-handoff-ioswith their crops,mac-team-library,ios-live-activityandipad-two-windows. Kinds across all entries: 15 Mac windows(with 39 phone crops), 41 detail crops, 11 iPhone, 2 iPad, 36 release-post figures,
1 diagram, 1 illustration.
or Vietnamese description (
asset-slot.test.ts, andimgInsidePlaceholders: 0inevery capture). The supplied-image path (
<picture>, AVIF/WebP, the LCP preload pertheme with the phone crop under its own
media) is tested against an isolatedfixture (
AssetManifestTest,RootTemplateTest), and every supplied entry's filesare checked for presence, pixel size and byte budget (
AssetManifestTest).og:generatefor every feature, database and compare pagein both locales, plus the release posts (91 generated PNGs under
public/og). Thebespoke site card (
public/og/bespoke/og-site-{en,vi}.png) is the default card inboth locales; the generated
/og.png(EN) and/og/vi/default.png(VI) stay as thefallback.
public/images/app-store-{light,dark}-vi.svg.7. Changed files by repository and purpose
TableProApp/web(main...rebuild: 1,589 files, 988 of them images and otherbinaries, and about +103k/−18k lines of text; the integration fixes are below):
app/Http/Middleware,app/Support/{Localization,Seo},routes/web.php,bootstrap/app.phpresources/data/*.json(platforms, pricing, engines, comparisons, paid-features, sponsors, facts, redirects, assets, locales),tests/Feature/Dataresources/data/content/{en,vi},resources/data/legal/{en,vi},resources/js/i18n/messages/{en,vi}resources/css/{tokens,fonts,app}.css,resources/js/components/{ui,shared}resources/js/pages/*,resources/js/components/{home,features,databases,compare,pricing,download,blog,legal,site}app/Services/Releases,app/Console/Commands/ReleaseCheckCommand.phpapp/Support/Assets,resources/views/og,public/og,docs/visual-assets.md,docs/rebuild/assetsscripts/dev-proxy.mjs,scripts/check-shared-files.sh,docs/shared-files.mdtests/Feature/**,tests/js/*.test.tsdocs/rebuild/design,docs/rebuild/assetsThe companion account-app changes (locale handling, localized mail, shared chrome) are
described in TableProApp/license#87.
Integration fixes, this repository:
DataTablekeeps hidden words inside its scroll region, which ended thepage-wide sideways scroll on phones. It shows its visible caption above the region and
paints the sticky column with its section's ground. Priority columns are used below
640px on the plan matrix, availability, paid-features, engine and comparison tables.
/databasesgets fixed column widths shared by every category.rhythm apart instead of two. The platforms band, the
/iosslots, the engine pageheader and the pricing cards were rebalanced. All download bands are built from one
ActionPairrow.scroll-behavior: smoothwas removed. In-page anchors glide onejump at a time (
lib/anchor-glide.ts), so Inertia's scroll reset is instant again.DotList),dates, inline code and fixed compounds no longer strand at line breaks. File names are
set in mono.
/undefinedonce animage was supplied) and takes the placement's
sizes.EnginePathsrule replaces five copies./vi/account*404s link the account.GitHubRepoService,tabs,footnote, runtime halvesof
engines.tsandcomparisons.ts, the reversedabsoluteUrl, the SEOHeadbreadcrumbs prop, legacy banner props, unused catalog keys). Obsolete skip guards were
removed from tests. Tests no longer depend on a running
composer dev(public/hot).8. Validation
Results for this repository, after the integration fixes (2026-10-03):
npm run typechecknpm run test:jsnpm run build(client and SSR)REQUIRE_SSR=1 php artisan test --compact, withinertia:start-ssron 13715vendor/bin/pint --testphp artisan assets:handoff --checkscripts/check-shared-files.sh ../licensesame, anddocs/shared-files.mdis identicalgtag.js. Layout shift: no public page above 0.003. LCP median 72–76 ms (localhost: a regression check, not a field number). SEO: one H1 per page; every public page has a self canonical with en/vi/x-default, except/vi/blog, which isnoindexby designrelease:checkplatforms.jsonafter the 0.77.1 update (GitHub and Sparkle 0.77.1, Homebrew 0.77.0 as expected)account and transactional screens, the 404 and 410 pages, and long articles), in
English and Vietnamese, light and dark, at 375, 768, 1280 and 1440. Captures are taken
through the local proxy with third parties blocked. Reviewed by tile against
design-system §8. Every public page was re-captured after the fixes.
lang, canonical andhreflang, horizontal overflow,clipped text, console and hydration errors, cookies, third-party requests, LCP and
CLS.
consent shared between the two apps, the cross-app account link, account locale,
download device handling, mocked checkout and newsletter, the redirect table, keyboard
and reduced motion, platform-to-public links, and the sitemap crawl.
Not verified, and why:
supplied.
/index.phpnormalisation behind production nginx: it needs a local nginx withthe production vhost, and the server was not touched.
Bundle cost against
main(Vite client build ofgit archive mainagainstrebuild; JS and CSS that a page loads, gzip)://download/blog/faqThe increase is mostly the second language's UI catalogs, which every page bundles
(architecture §1.4 asked for this to be measured), and the slot manifest (
asset-slotchunk, 14.7 KB gzip on pages with images). The shared
appentry is unchanged(98.9 → 99.8 KB). Splitting the slot descriptions per locale, or passing each page's
slots as props, is a follow-up.
Failures already on
main: none on the public side.9. Local preview
Architecture §4 has the full list. In short, for this repository:
Local settings:
WEB_DOMAIN=localhostin both apps; in the account app, a throwawaydatabase, mail on the
logdriver and payments mocked (its own README has the settings).Use built assets. While
composer devruns,public/hotmakes pages load from the Vitedev server: the test suite ignores it, but a browser check of production behaviour (CLS,
hydration timing) needs it gone. Connected journeys to try: the header Account link to
/account?locale=; a guest checkout from/vi/pricingthat carriesviinto the order;theme and consent set on
/showing on/account; and the account's links back to thepublic pages in the reader's language.
10. Routing and release, for the maintainer
maindeploys itself when its tests pass.theme,tablepro:analytics-consentand the visual system, so thetwo should go out the same day. A mismatch between them is cosmetic, not
functional.
scripts/check-shared-files.sh ../license(a checkout ofTableProApp/license) before marking either PR ready. Every pair must reportsame./vi/account*is apublic 404 that links
/account?locale=vi.reads the live release, so a new app version needs no copy change.
Still open