Uh oh!
There was an error while loading. Please reload this page.
feat(build): upgrade to Astro 7 and Tailwind CSS 4 - #2315
Open
isaque-bock-azion wants to merge 18 commits into
Open
feat(build): upgrade to Astro 7 and Tailwind CSS 4#2315isaque-bock-azion wants to merge 18 commits into
isaque-bock-azion wants to merge 18 commits into
Conversation
isaque-bock-azionforce-pushed
the
feat/astro7-tailwind4
branch
from
August 19, 2026 20:06
9ffd966 to
802fc20Compareisaque-bock-azion
marked this pull request as ready for review
August 19, 2026 22:44
isaque-bock-azion
requested review from
a team, bruno-andrade-azion, marcus-souza-azion and pedro-ribeiro-azion
as code ownersAugust 19, 2026 22:44
Replaces the deprecated @astrojs/tailwind integration (capped at Astro 5) with Tailwind 4 via @tailwindcss/postcss, unblocking the Astro 7 upgrade. - Vendor azion-webkit@1's entry CSS (src/styles/webkit-v1-main.css) since it contained Tailwind v3 directives; the file is removed once webkit v4 lands. - New Tailwind entry in src/styles/main.css: cascade-layer order keeps PrimeVue between base and utilities (same cascade as v3), `important` import flag preserves v3's important:true, @source compiles the raw .vue components azion-webkit@1 ships, and v3 preflight compatibility styles keep border/placeholder/cursor defaults. - Slim tailwind.config.cjs: theme-only copy of what azion-webkit@1's config provided; its v3-only addUtilities plugins now live in CSS as @Utility px-shell/px-container. The unused `container.padding` config is dropped (crashes Tailwind 4's compat layer with custom screens). - Rename removed v3 utilities: flex-shrink-0 -> shrink-0, rounded -> rounded-sm. - Drop autoprefixer (built into Tailwind 4).
Astro 7.2.3, Vite 8, Vue 3.5, and the Content Layer API. Also patches the 9 published vulnerabilities in astro <7.0.4. Content Layer (mandatory since Astro 6 removed legacy collections): - Move src/content/config.ts to src/content.config.ts with a glob() loader and `astro/zod` imports. - entry.slug -> entry.id and entry.render() -> render(entry) across pages, layouts, components, and utils. The [lang]/[...slug] route rebuilds the legacy id (path with extension) from entry.filePath for getGithubEditUrl, and docs-path-by-url.json now uses entry.filePath directly. Markdown: keep the unified() processor from @astrojs/markdown-remark so the custom remark/rehype plugins keep running; porting them to Sätteri is a follow-up. Integrations: @astrojs/mdx 7, @astrojs/vue 7, @astrojs/preact 6, @astrojs/sitemap 1.0.1 -> 3.7.3, astro-expressive-code 0.44, astro-auto-import 0.5, astro-og-canvas 0.13. Vite 8 adjustments: - Tailwind 4 moves from @tailwindcss/postcss to @tailwindcss/vite (Vite 8's postcss-import no longer resolves the bare `tailwindcss` import). - A small config plugin bundles primevue/azion-webkit/azion-theme into the new prerender environment: Astro marks primevue as external there, and primevue 3's ESM files use directory imports Node cannot resolve. - Drop the obsolete vite.ssrBuild flag. TablePricing now caches pricing API responses per product_slug for the whole build; the prerender pass fetching once per page caused transient DNS failures. Build verified: 1494 pages, frontmatter test passing, asides/heading anchors/expressive-code/JSON+md+llms.txt endpoints/sitemaps all present in the output.
isaque-bock-azionforce-pushed
the
feat/astro7-tailwind4
branch
from
August 28, 2026 21:25
802fc20 to
17ca0e6Compare…th Tailwind (#2316) Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Ports the header, search trigger and palette from the webkit design system sample (feat/doc-masthead-action-belt) to the docs site. - Header: rebuilt on GlobalHeader (.Left/.Brand/.Nav/.Right) with @container so the search trigger can switch shapes via container query instead of viewport breakpoints - HeaderSearch: two-root trigger (IconButton narrow / field-shaped wide) with @min-[47rem] container query, verbatim from the sample - HeaderSearchDialog: CommandMenu shell (⌘K shortcut, Dialog/Overlay owned by webkit) feeding Algolia via direct client.search() across the four i18n indices; replaces vue-instantsearch + AlgoliaDialog - HeaderRightSidebar: mobile nav migrated from manual Teleport to webkit Drawer (side="left", size="small"); closes on palette-open cross-island event - DocsTopNav: NavigationMenu extracted into its own client:idle island so the hover-pill highlight (pointerenter + provide/inject) hydrates correctly; was dead inside the SSR-only Header.vue - main.css: added text-overline-md / text-overline-sm Tailwind shims so Kbd keycaps (⌘K, ESC) render at the token's 12px, not 16px - Removed: AlgoliaDialog, AlgoliaInstantSearch, AlgoliaIndexHit, KeyboardKey, DocsSearchTrigger, vue.config.js; dep vue-instantsearch
Deletes public/assets/docs/css/ (theme.css, index.css), and the orphaned SCSS layers under src/styles/ (breakpoints, functions, icons, tokens) — none of these were imported anywhere after the webkit/theme migration; all design tokens now come from @aziontech/theme.
Replaces the hand-rolled footer flex layout with webkit's Footer component, aligned with the design system's own sample (SiteFooter.vue). Updates the i18n model: drops the legacy `cta` (phone numbers) and `copyright` exports, adds `tagline` in their place, as the DS Footer now renders the signature band with the brand mark and tagline from the component itself.
- LeftSidebar: drops SidebarContent (Astro/SCSS/TSX trio) and the sidebarpanelmenu/ pair; now delegates to DocsSidebarMenu (webkit DS) via the menuToWebkit adapter - ReadableContent: rewired to webkit's DocProse for article typography (heading ladder, prose body, callout, code chip); removes the local .prose/.article SCSS that duplicated those rules - RightSidebar: swaps the local TableOfContents/TableOfContentsItem pair for webkit's OnThisPage component - PageContent/MainLayout: layout adjustments for the webkit rail's sizing contract (auto column instead of fixed 20rem)
…egrations - Aside: replaced hand-rolled admonition (inline SVGs + SCSS) with webkit's doc-callout; maps caution→warning, unwraps <p> to inline prose, preserves authored titles as lead-in text - Code: switched from astro-expressive-code to local CodeBlock wrapper (webkit's syntax highlighting); removes expressive-code integration files - LinkButton: wraps button roots in `data-doc-chrome` span (display:contents) so DocProse prose-link paint does not repaint buttons inside article content - AzionLogo.vue: deleted (unused after Header.vue moved to GlobalHeader.Brand) - plugins/rehype-autolink-config: adds data-doc-anchor on heading anchors so DocProse's link rules skip them - .gitignore: add Azion CLI build artifacts (.edge/, .vulcan, .open-next) - pnpm-workspace.yaml: pin @aziontech/theme and webkit to current versions
New components used by the sidebar/toc/code refactor: - CodeBlock: webkit syntax highlighting shell (replaces expressive-code) - DocPageHeader: page title + metadata band above article content - DocsSidebar: webkit Sidebar rail wrapper for the left nav - DocsSidebarMenu: webkit Menu tree rendering the navigation tree - OnThisPage: webkit table-of-contents for the right sidebar - menuToWebkit: adapter converting the docs navigation data model (getNavigationMenu) to webkit's Menu/tree props contract - integrations/astro-code-blocks: Astro integration wiring CodeBlock into the remark/rehype pipeline
Adds the auto-generated azion.config.mjs (build preset: astro, storage bucket for docs-preview-webkit) and the GitHub Actions workflow for Azion deploy, alongside the azion/ config directory generated by the CLI.
Replaces the LinkButton compatibility wrapper with @aziontech/webkit/button imported directly. Props mapped: link→href, severity="secondary"→kind="secondary"; added size="medium" and class="not-prose no-underline" on every call site. Removes the unused Container import.
DocProse styles every `a` in the article body as a prose link -- link ink, underline, flat radius -- with `!important`, and steps aside only for `[data-doc-chrome]`. A webkit Button rendered with `href` is such an `a`, so every button in the docs body came out blue, underlined and square on top of its own fill. `class="not-prose no-underline"` never had a chance: the contract's selector is more specific and important. The attribute cannot go on the Button itself -- it sets `inheritAttrs: false` and forwards only `class`, so `data-doc-chrome` is dropped before it reaches the DOM. DocButton puts it on a wrapping span instead, whose subtree the contract also excludes, and adds `data-doc-block` for the standard block spacing. Same treatment for HeroHome's actions row: the hero CTAs live inside ReadableContent too and were painted as prose links for the same reason.
…utton The 650 pages that import the button rendered it as a prose link -- blue, underlined, square corners over the button's own fill -- because DocProse styles every `a` in the article body and only stops at `[data-doc-chrome]`. DocButton carries that boundary; swapping the import is the whole fix. Two leftovers from the LinkButton era go with it. `class="not-prose no-underline"` was reaching for this same escape and never worked, and `iconPos="left"` names a prop the webkit Button does not have -- it has one icon slot, always leading -- so it was dropped on the floor either way. Mechanical: the import line was identical in all 650 files, `<Button` has no closing-tag form here, and occurrences inside code fences were left alone. All 650 files re-checked through the MDX compiler.
… mounted Every documentation page logged "Hydration completed but contains mismatches". DocProse's copy tip lives in a `<Teleport to="body">`, and Astro does not re-emit Vue's teleport payload into the served markup -- so on hydration Vue walks into `<body>` looking for the teleport anchor and finds the page's own first element instead. Vue then discards the server DOM for that subtree and re-renders it on the client, on every page. Gating the teleport on a mounted flag keeps the server render and the client's first render identical -- the tip is a `v-if` comment inline in the root either way -- and it costs nothing, since the tip only ever opens on pointerover. Carried as a pnpm patch because the fix belongs upstream in @aziontech/webkit; drop `patches/` and the `patchedDependencies` entry once a release ships it.
The authoring API is unchanged: 328 tab blocks across 178 content files keep writing `<Tabs>` with `<Fragment slot="tab.x">` / `slot="panel.x">`, so not one .mdx was touched. `Tabs.ts` re-exports the SFC because the content imports `~/components/tabs/Tabs` without an extension and Vite's resolve.extensions does not include .vue. Panels stay in the DOM behind `hidden` instead of using TabView's Panel, which mounts its slot behind `v-if`. Dropping inactive panels would take half the prose of every tabbed page out of the served HTML -- out of Ctrl+F, out of the crawl, and out of reach of the heading-anchor wiring ReadableContent installs once on mount. The cost is TabView's sliding indicator and edge fades; this component owns the active value, the ids and the arrow keys instead, and the chips fall back to Item's standalone `selected` styling, which paints the same. Two things the port had to fix rather than carry over. Astro hands slots to the island in resolution order, not authoring order, so a panel holding an island (`<Code>`) overtakes the panel written above it -- the tabs are now the source of order and panels are paired by key, which also moves the default from "first panel" to "first tab" (they diverge in 23 of the 328 blocks, some of them real content typos). And the shared store subscribes only on mount: `tabStore` is a module singleton, so subscribing during SSR would leak a listener per render and let one request's choice bleed into the next. PricingTableOfContents comes along as Vue over webkit's DocOnThisPage, keeping the two pricing-specific behaviors: the `-1` anchor remap for the `real` tab, and the scroll-spy that skips headings under `[hidden]`.
… originals
Overline, TitleSection and the four-part card family (CardBase,
CardBaseClickable, CardTitle, CardDescription) all had an equivalent already
shipping in @aziontech/webkit, so they are gone: 502 lines of local markup
replaced by Overline, SectionTitle, DocCard and DocCardGroup.
The card grid is the change worth reading. DocCardGroup is both the frame and
the rules -- cards abut inside it and the hairlines between them are the
group's own gaps -- so Cardlist no longer draws a grid, a gap or a border of
its own. Two deliberate omissions: no icon, because the content data carries
SVG paths while DocCard's `icon` expects a PrimeIcons class, and no CTA link,
because the data has no call-to-action copy and inventing i18n strings is not a
refactor. The old card's arrow goes with them; the whole card is still the
link.
Overline is a `w-fit` inline element rather than a block, so centering moved
from `text-center` to `self-center` on the parent. And in the branch where
SectionTitle takes over the whole header, `titleTag` stops having an effect --
the design system fixes h2 there. That branch compiles but no page exercises it
today: none of the 70 call sites passes a `title`.
The hero stays hand-built on purpose. webkit's HeroTitle always renders the
highlighted span at the *start* of the headline, and both homes author it at
the end ("Welcome to <span>Azion Docs</span>"). With no title slot, adopting it
would mean losing the accent, inverting the sentence, or rewriting both
headlines -- an editorial call, not a refactor.ThemeSwitcher becomes an adapter over webkit's ThemeSwitcher (196 -> 112 lines): the dropdown, its trigger, the viewport measuring and the document click/Escape listeners all go, and what stays is the part the design system does not own -- reading and writing the preference. The stored value keeps its exact old shape, the `prefers-color-scheme` key holding 'System' | 'Dark' | 'Light', because BaseLayout reads that same key in a blocking inline script and every returning visitor already has one of those strings saved; the lowercase mode names webkit speaks are paired to them here rather than migrating anyone's storage. Visually this turns a dropdown into a segmented icon group. SystemStatus takes its dot and label from StatusIndicator, so severity comes from theme tokens instead of the inline hex the component used to paint with. The pill around it stays a plain anchor: webkit's Button takes its content through a `label` string and exposes no default slot, so wrapping the indicator in one would render the text and drop the dot. Also removes STATUS_PAGE and its `status` ref, which nothing read. SelectLang moves to webkit's Dropdown -- not Select, which is still draft in the catalog. `placement="auto"` replaces the hand-rolled "is there room below?" measurement. The options stay real anchors so the translated route is still crawlable and middle-clickable. Two known defects are documented in BaseLayout rather than worked around. Nothing nested in this Footer island hydrates today, SystemStatus included, and that predates the webkit adoption -- the controls paint but do not respond to a click. And webkit's Dropdown and ThemeSwitcher teleport an overlay to <body>, which Astro never re-emits into the served markup; the fix is the doc-prose patch in patches/ extended upstream to tooltip and dropdown. `client:only` looks like the answer to both and is a trap: an island nested inside a Vue island never mounts under it, so the controls vanish entirely instead of merely being inert. BaseLayout also carries an unrelated change that was already pending in the working tree: the ScrollArea rules for the "On this page" rail.
This is not one change; it is everything that was sitting uncommitted in the tree, swept in at the author's request so nothing is left dangling. Two distinct bodies of work: The webkit/Tailwind 4 adoption in progress: 68 legacy components removed (BackendGuidesNav, Badge, Breadcrumb, Button, the NavGrid and tabs .astro families, the Preact leftovers TableOfContents, SidebarToggleTabGroup, ExternalLinkIcon and Spoiler, and the rest), Footer rebuilt on the design system's own Footer, and the supporting changes across content.config.ts, content.ts, the i18n helpers, src/util and the layouts. The lint toolchain migration (MM-15912), authored in a parallel session: flat config in eslint.config.mjs replacing .eslintrc.js and .eslintignore, eslint 9 with typescript-eslint 8, stylelint 16 with postcss-html and postcss-scss, and the call sites those rules touched. Also included: azion.config.mjs and azion/azion.json from the preview deploy, and .claude/launch.json. Neither body of work is mine and neither was reviewed here. They are committed as they stood, so the history has a point to return to before the deploy.
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 freeto 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.
What
Base branch for the docs modernization stack (MM-15897). Two commits, one per migration:
@astrojs/tailwindintegration (capped at Astro 5). New CSS-first entry insrc/styles/main.css(importantflag, cascade layers keeping PrimeVue between base and utilities,@sourcefor azion-webkit@1's raw.vuecomponents, v3 preflight compat). azion-webkit@1's entry CSS is vendored intosrc/styles/webkit-v1-main.cssuntil webkit v4 lands.content.config.ts+ glob loader,slug→id,render(entry)), integration bumps (@astrojs/sitemap1.0.1→3.7.3 included), and the markdown pipeline kept onunified()so all custom remark/rehype plugins keep working. Also fixes the 9 published vulnerabilities inastro <7.0.4.Notable plumbing
prerenderVite environment that ignoresvite.ssr.noExternaland force-externalizesprimevue; a small inline config plugin (azion:server-noexternal) bundles primevue/azion-webkit/azion-theme there (PrimeVue 3's ESM uses directory imports Node can't resolve).TablePricingnow caches pricing API responses perproduct_slugfor the whole build — the prerender pass fetched once per page and caused transient DNS failures.Verification
pnpm run build:local: 1494 pages in ~2m48s, frontmatter test passing.doc-all-data.json/docs-path-by-url.json/docs-llms.txt/.mdendpoints, both sitemaps, Tailwind 4 CSS inlined with!importantparity.astro previewsmoke test in the browser: layout matches production, Algolia search dialog opens and returns results, zero console errors.Known notes
astro dev(Vite 8 optimize-deps CJS interop withalgoliasearchinside azion-webkit@1). The production build is unaffected — worth a follow-up.astro-expressive-code0.44 warns about unknown code-fence languages (code,env,gitignore) in a few MDX files — content fixes, separate PR.🤖 Generated with Claude Code