From 73c02df21ea47e979ed6bd736106794589b1655d Mon Sep 17 00:00:00 2001 From: Alex Grozav Date: Tue, 28 Jul 2026 07:57:32 +0300 Subject: [PATCH 1/3] refactor(docs): consume layer plumbing instead of forking it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `@uxfront/layer-docs` now ships the collections builder options, the locale files, the Content Studio schema and the Vite prebundle hints, so the local forks are dead weight. Net -2150 lines. - `content.config.ts`: 118 lines -> 11. `defineDocsCollections(DOCS_SECTIONS, { sitemap: true, changelog: true })`. Section topology stays local in `app/constants/sections.ts`; the collection shapes, per-locale fan-out and schemas come from the layer. - Deleted `i18n/locales/` (31 files), `nuxt.schema.ts`, `modules/optimizeDeps.ts` and `modules/useDocusI18nOverride.ts`. That module's own docblock said to remove it once the package shipped its locales; it does now. - Deleted 18 shadow copies that re-declared layer files at the same relative path. Layer precedence meant every upstream fix to those files was invisible here — notably the `AppHeader` anchor-nesting a11y fix, which is now actually in effect (verified: max anchor nesting depth 1 in the prerendered header). - Deleted `utils/prerender.ts`; the layer's `app/utils/prerender.ts` is equivalent and auto-imported, so the explicit relative import goes too. - `app.config.ts` declares `docsTheme.frameworks` (React/Vanilla/Vue, order preserved). The layer no longer ships a default list. Four shadows are kept deliberately, each now carrying a docblock naming its delta and its deletion trigger: - `useDocsSections.ts` — the `THEME_SUBSECTIONS` split is a styleframe content shape. Rebased onto the layer copy, which adds the missing `hasSectionSwitcher`; without it the layer's `AppSubHeader` read `undefined` and the docs sub-header never rendered. - `DocsAsideLeftBody.vue` — theme-subsection nav filter and the `ProIcon` badge. - both `[...slug].vue` pages — `defineOgImage`; `nuxt-og-image` and the `DocsSatori` template are registered here, not in the theme. Rebased to take the layer's `USeparator decorative` a11y fix. - `app/types/non-route-categories.ts` — a deliberate duplicate, because `modules/nonRouteCategories.ts` imports it by relative path at build time and that module has not moved into the layer yet. Requires @uxfront/layer-docs@0.2.0, which is not published yet. Refs UXF-119, UXF-3 --- apps/docs/app/app.config.ts | 14 + apps/docs/app/app.vue | 164 ------------ apps/docs/app/components/LanguageSelect.vue | 74 ------ apps/docs/app/components/app/AppHeader.vue | 112 -------- .../app/components/content/BrowserFrame.vue | 28 -- .../components/content/FrameworkSwitcher.vue | 23 -- .../components/content/GradientPageHero.vue | 17 -- apps/docs/app/components/content/Video.vue | 106 -------- .../app/components/docs/DocsAsideLeftBody.vue | 7 + .../app/components/docs/DocsAsideLeftTop.vue | 16 -- .../components/docs/DocsFrameworkSelect.vue | 20 -- apps/docs/app/composables/useDocsSections.ts | 18 +- apps/docs/app/composables/useDocusI18n.ts | 49 ---- apps/docs/app/composables/useFramework.ts | 32 --- apps/docs/app/error.vue | 166 ------------ apps/docs/app/layouts/default.vue | 25 -- apps/docs/app/pages/[[lang]]/[...slug].vue | 8 + .../[[lang]]/docs/[section]/[...slug].vue | 14 +- apps/docs/app/types/non-route-categories.ts | 6 + apps/docs/app/utils/flattenNavigation.ts | 24 -- apps/docs/app/utils/foldNonRouteCategories.ts | 55 ---- apps/docs/content.config.ts | 127 +-------- apps/docs/i18n/locales/ar.json | 22 -- apps/docs/i18n/locales/be.json | 22 -- apps/docs/i18n/locales/bn.json | 22 -- apps/docs/i18n/locales/ca.json | 22 -- apps/docs/i18n/locales/ckb.json | 18 -- apps/docs/i18n/locales/cs.json | 22 -- apps/docs/i18n/locales/da.json | 22 -- apps/docs/i18n/locales/de.json | 22 -- apps/docs/i18n/locales/el.json | 22 -- apps/docs/i18n/locales/en.json | 22 -- apps/docs/i18n/locales/et.json | 22 -- apps/docs/i18n/locales/fr.json | 22 -- apps/docs/i18n/locales/he.json | 22 -- apps/docs/i18n/locales/hi.json | 22 -- apps/docs/i18n/locales/hy.json | 22 -- apps/docs/i18n/locales/it.json | 18 -- apps/docs/i18n/locales/ja.json | 22 -- apps/docs/i18n/locales/kk.json | 22 -- apps/docs/i18n/locales/km.json | 22 -- apps/docs/i18n/locales/ko.json | 22 -- apps/docs/i18n/locales/ky.json | 22 -- apps/docs/i18n/locales/lb.json | 22 -- apps/docs/i18n/locales/ms.json | 22 -- apps/docs/i18n/locales/nb.json | 22 -- apps/docs/i18n/locales/pl.json | 22 -- apps/docs/i18n/locales/ru.json | 22 -- apps/docs/i18n/locales/sl.json | 22 -- apps/docs/i18n/locales/sv.json | 22 -- apps/docs/i18n/locales/uk.json | 22 -- apps/docs/i18n/locales/ur.json | 22 -- apps/docs/i18n/locales/vi.json | 22 -- apps/docs/modules/optimizeDeps.ts | 21 -- apps/docs/modules/useDocusI18nOverride.ts | 28 -- apps/docs/nuxt.config.ts | 3 - apps/docs/nuxt.schema.ts | 243 ------------------ apps/docs/package.json | 3 +- apps/docs/server/plugins/llms-redirect.ts | 60 ----- .../server/routes/raw/[...slug].md.get.ts | 77 ------ apps/docs/utils/prerender.ts | 11 - 61 files changed, 75 insertions(+), 2150 deletions(-) delete mode 100644 apps/docs/app/app.vue delete mode 100644 apps/docs/app/components/LanguageSelect.vue delete mode 100644 apps/docs/app/components/app/AppHeader.vue delete mode 100644 apps/docs/app/components/content/BrowserFrame.vue delete mode 100644 apps/docs/app/components/content/FrameworkSwitcher.vue delete mode 100644 apps/docs/app/components/content/GradientPageHero.vue delete mode 100644 apps/docs/app/components/content/Video.vue delete mode 100644 apps/docs/app/components/docs/DocsAsideLeftTop.vue delete mode 100644 apps/docs/app/components/docs/DocsFrameworkSelect.vue delete mode 100644 apps/docs/app/composables/useDocusI18n.ts delete mode 100644 apps/docs/app/composables/useFramework.ts delete mode 100644 apps/docs/app/error.vue delete mode 100644 apps/docs/app/layouts/default.vue delete mode 100644 apps/docs/app/utils/flattenNavigation.ts delete mode 100644 apps/docs/app/utils/foldNonRouteCategories.ts delete mode 100644 apps/docs/i18n/locales/ar.json delete mode 100644 apps/docs/i18n/locales/be.json delete mode 100644 apps/docs/i18n/locales/bn.json delete mode 100644 apps/docs/i18n/locales/ca.json delete mode 100644 apps/docs/i18n/locales/ckb.json delete mode 100644 apps/docs/i18n/locales/cs.json delete mode 100644 apps/docs/i18n/locales/da.json delete mode 100644 apps/docs/i18n/locales/de.json delete mode 100644 apps/docs/i18n/locales/el.json delete mode 100644 apps/docs/i18n/locales/en.json delete mode 100644 apps/docs/i18n/locales/et.json delete mode 100644 apps/docs/i18n/locales/fr.json delete mode 100644 apps/docs/i18n/locales/he.json delete mode 100644 apps/docs/i18n/locales/hi.json delete mode 100644 apps/docs/i18n/locales/hy.json delete mode 100644 apps/docs/i18n/locales/it.json delete mode 100644 apps/docs/i18n/locales/ja.json delete mode 100644 apps/docs/i18n/locales/kk.json delete mode 100644 apps/docs/i18n/locales/km.json delete mode 100644 apps/docs/i18n/locales/ko.json delete mode 100644 apps/docs/i18n/locales/ky.json delete mode 100644 apps/docs/i18n/locales/lb.json delete mode 100644 apps/docs/i18n/locales/ms.json delete mode 100644 apps/docs/i18n/locales/nb.json delete mode 100644 apps/docs/i18n/locales/pl.json delete mode 100644 apps/docs/i18n/locales/ru.json delete mode 100644 apps/docs/i18n/locales/sl.json delete mode 100644 apps/docs/i18n/locales/sv.json delete mode 100644 apps/docs/i18n/locales/uk.json delete mode 100644 apps/docs/i18n/locales/ur.json delete mode 100644 apps/docs/i18n/locales/vi.json delete mode 100644 apps/docs/modules/optimizeDeps.ts delete mode 100644 apps/docs/modules/useDocusI18nOverride.ts delete mode 100644 apps/docs/nuxt.schema.ts delete mode 100644 apps/docs/server/plugins/llms-redirect.ts delete mode 100644 apps/docs/server/routes/raw/[...slug].md.get.ts delete mode 100644 apps/docs/utils/prerender.ts diff --git a/apps/docs/app/app.config.ts b/apps/docs/app/app.config.ts index 84267127..a5b60215 100644 --- a/apps/docs/app/app.config.ts +++ b/apps/docs/app/app.config.ts @@ -40,6 +40,20 @@ export default defineAppConfig({ }, ], }, + /** + * Frameworks offered by the sidebar select and the in-content + * `FrameworkSwitcher`, in display order. `value` is the MDC slot name used + * in content (`#react`, `#other`, `#vue`) and the persisted preference + * token. The layer ships no default list — which frameworks styleframe + * documents is a styleframe fact — so this array is the only source. + */ + docsTheme: { + frameworks: [ + { value: "react", label: "React", icon: "i-mdi-react" }, + { value: "other", label: "Vanilla", icon: "i-mdi-language-typescript" }, + { value: "vue", label: "Vue", icon: "i-mdi-vuejs" }, + ], + }, /** * @docs https://www.docus.dev/concepts/configuration#socials-links */ diff --git a/apps/docs/app/app.vue b/apps/docs/app/app.vue deleted file mode 100644 index 0fe0a1cb..00000000 --- a/apps/docs/app/app.vue +++ /dev/null @@ -1,164 +0,0 @@ - - - diff --git a/apps/docs/app/components/LanguageSelect.vue b/apps/docs/app/components/LanguageSelect.vue deleted file mode 100644 index 015dc133..00000000 --- a/apps/docs/app/components/LanguageSelect.vue +++ /dev/null @@ -1,74 +0,0 @@ - - - diff --git a/apps/docs/app/components/app/AppHeader.vue b/apps/docs/app/components/app/AppHeader.vue deleted file mode 100644 index e2d8d64a..00000000 --- a/apps/docs/app/components/app/AppHeader.vue +++ /dev/null @@ -1,112 +0,0 @@ - - - diff --git a/apps/docs/app/components/content/BrowserFrame.vue b/apps/docs/app/components/content/BrowserFrame.vue deleted file mode 100644 index 565357a9..00000000 --- a/apps/docs/app/components/content/BrowserFrame.vue +++ /dev/null @@ -1,28 +0,0 @@ - - - diff --git a/apps/docs/app/components/content/FrameworkSwitcher.vue b/apps/docs/app/components/content/FrameworkSwitcher.vue deleted file mode 100644 index 6951ea68..00000000 --- a/apps/docs/app/components/content/FrameworkSwitcher.vue +++ /dev/null @@ -1,23 +0,0 @@ - - - diff --git a/apps/docs/app/components/content/GradientPageHero.vue b/apps/docs/app/components/content/GradientPageHero.vue deleted file mode 100644 index 1d63a0e0..00000000 --- a/apps/docs/app/components/content/GradientPageHero.vue +++ /dev/null @@ -1,17 +0,0 @@ - - - diff --git a/apps/docs/app/components/content/Video.vue b/apps/docs/app/components/content/Video.vue deleted file mode 100644 index 15f9230d..00000000 --- a/apps/docs/app/components/content/Video.vue +++ /dev/null @@ -1,106 +0,0 @@ - - - diff --git a/apps/docs/app/components/docs/DocsAsideLeftBody.vue b/apps/docs/app/components/docs/DocsAsideLeftBody.vue index 8977985c..54970172 100644 --- a/apps/docs/app/components/docs/DocsAsideLeftBody.vue +++ b/apps/docs/app/components/docs/DocsAsideLeftBody.vue @@ -1,4 +1,11 @@ - - diff --git a/apps/docs/app/composables/useDocsSections.ts b/apps/docs/app/composables/useDocsSections.ts index 5f5fa88f..a1312b10 100644 --- a/apps/docs/app/composables/useDocsSections.ts +++ b/apps/docs/app/composables/useDocsSections.ts @@ -22,6 +22,15 @@ function findFirstLeafPath( return items[0]?.path; } +/** + * Local override of the layer's `useDocsSections`. + * + * The delta is the `theme` branch: styleframe splits one content collection into + * four sub-header tabs via `THEME_SUBSECTIONS`, which is a styleframe content + * shape, not a theme feature. The rest of the shape — including + * `hasSectionSwitcher` — must stay identical to the layer copy, since the + * layer's `AppSubHeader` consumes it. + */ export function useDocsSections() { const route = useRoute(); const navigation = @@ -67,5 +76,12 @@ export function useDocsSections() { sections.value.find((section) => section.active), ); - return { sections, activeSection }; + /** + * Whether the section switcher is worth rendering. A single section (or none) + * gives the reader nothing to switch between, so the sub-header is suppressed + * entirely rather than rendering an empty bar. + */ + const hasSectionSwitcher = computed(() => sections.value.length > 1); + + return { sections, activeSection, hasSectionSwitcher }; } diff --git a/apps/docs/app/composables/useDocusI18n.ts b/apps/docs/app/composables/useDocusI18n.ts deleted file mode 100644 index 242f498a..00000000 --- a/apps/docs/app/composables/useDocusI18n.ts +++ /dev/null @@ -1,49 +0,0 @@ -import type { LocaleObject } from "@nuxtjs/i18n"; -import type { Ref } from "vue"; -import en from "../../i18n/locales/en.json"; - -/** - * `@nuxtjs/i18n` auto-imports. This app ships with i18n disabled — the module is - * not registered (see apps/shared/modules/config.ts) — so the enabled branch - * below is inert. These declarations let the file typecheck without the module - * generating the globals; when i18n is enabled the real composables are used. - */ -declare function useI18n(): { locale: Ref; t: (key: string) => string }; -declare function useLocalePath(): (route: string, locale?: string) => string; -declare function useSwitchLocalePath(): (locale: string) => string; - -export const useDocusI18n = () => { - const config = useRuntimeConfig().public; - const isEnabled = ref(!!config.i18n); - - if (!isEnabled.value) { - return { - isEnabled, - locale: ref("en"), - locales: [], - localePath: (path: string) => path, - switchLocalePath: (_locale?: string): string => "", - t: (key: string): string => { - const path = key.split("."); - return path.reduce( - (acc: unknown, curr) => (acc as Record)?.[curr], - en, - ) as string; - }, - }; - } - - const { locale, t } = useI18n(); - const filteredLocales = - (config.docus as { filteredLocales: LocaleObject[] }) - ?.filteredLocales || []; - - return { - isEnabled, - locale, - locales: filteredLocales, - t, - localePath: useLocalePath(), - switchLocalePath: useSwitchLocalePath(), - }; -}; diff --git a/apps/docs/app/composables/useFramework.ts b/apps/docs/app/composables/useFramework.ts deleted file mode 100644 index e43c1c9d..00000000 --- a/apps/docs/app/composables/useFramework.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { useLocalStorage } from "@vueuse/core"; - -export type Framework = "vue" | "react" | "other"; - -export interface FrameworkOption { - value: Framework; - label: string; - icon: string; -} - -export const FRAMEWORKS: readonly FrameworkOption[] = [ - { value: "react", label: "React", icon: "i-mdi-react" }, - { - value: "other", - label: "Vanilla", - icon: "i-mdi-language-typescript", - }, - { value: "vue", label: "Vue", icon: "i-mdi-vuejs" }, -] as const; - -const STORAGE_KEY = "styleframe-docs:framework"; - -export const useFramework = () => { - const framework = useLocalStorage(STORAGE_KEY, "react", { - initOnMounted: true, - }); - - return { - framework, - frameworks: FRAMEWORKS, - }; -}; diff --git a/apps/docs/app/error.vue b/apps/docs/app/error.vue deleted file mode 100644 index bec74e08..00000000 --- a/apps/docs/app/error.vue +++ /dev/null @@ -1,166 +0,0 @@ - - - diff --git a/apps/docs/app/layouts/default.vue b/apps/docs/app/layouts/default.vue deleted file mode 100644 index 7e000d1c..00000000 --- a/apps/docs/app/layouts/default.vue +++ /dev/null @@ -1,25 +0,0 @@ - - - diff --git a/apps/docs/app/pages/[[lang]]/[...slug].vue b/apps/docs/app/pages/[[lang]]/[...slug].vue index d882756f..e83a5600 100644 --- a/apps/docs/app/pages/[[lang]]/[...slug].vue +++ b/apps/docs/app/pages/[[lang]]/[...slug].vue @@ -1,4 +1,12 @@