diff --git a/.github/scripts/docs-after-clone.sh b/.github/scripts/docs-after-clone.sh new file mode 100644 index 000000000..19df08cdf --- /dev/null +++ b/.github/scripts/docs-after-clone.sh @@ -0,0 +1,7 @@ +#! /usr/bin/env bash +set -e + +[[ -z "$1" ]] && echo "Missing working directory argument" && exit 1 + +echo "Installing root pnpm" +pnpm -C $1 i \ No newline at end of file diff --git a/.github/scripts/docs.yml b/.github/scripts/docs.yml new file mode 100644 index 000000000..498b25ee7 --- /dev/null +++ b/.github/scripts/docs.yml @@ -0,0 +1 @@ +build-end: {} \ No newline at end of file diff --git a/.github/workflows/deploy-developer-portal.yml b/.github/workflows/deploy-developer-portal.yml new file mode 100644 index 000000000..644818586 --- /dev/null +++ b/.github/workflows/deploy-developer-portal.yml @@ -0,0 +1,24 @@ +# This workflow is triggered whenever the main branch is updated +name: Deploy to DevHub + +on: + push: + branches: + - main + +jobs: + trigger-deployment: + name: Trigger deployment + runs-on: ubuntu-latest + steps: + + - uses: octokit/request-action@v2.x + name: Trigger deployment + with: + route: POST /repos/{owner}/{repo}/actions/workflows/{workflow_id}/dispatches + owner: shopware + repo: developer-portal + ref: main + workflow_id: checkout-test-build-deploy.yml + env: + GITHUB_TOKEN: ${{ secrets.DEV_HUB_PERSONAL_ACCESS_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/developer-portal-healthckeck.yml b/.github/workflows/developer-portal-healthckeck.yml new file mode 100644 index 000000000..eb24a97ad --- /dev/null +++ b/.github/workflows/developer-portal-healthckeck.yml @@ -0,0 +1,19 @@ +name: Healthcheck + +on: + pull_request: + branches: + - main + +jobs: + + create-healthcheck: + uses: shopware/developer-portal/.github/workflows/healthcheck.yml@main + with: + owner: ${{ github.repository_owner }} + repo: ${{ github.event.repository.name }} + branch: ${{ github.event.pull_request.head.ref }} + sha: ${{ github.event.pull_request.head.sha }} + secrets: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + PERSONAL_TOKEN: ${{ secrets.DEV_HUB_PERSONAL_ACCESS_TOKEN }} diff --git a/.github/workflows/update-healthcheck.yml b/.github/workflows/update-healthcheck.yml new file mode 100644 index 000000000..c9e9a8b88 --- /dev/null +++ b/.github/workflows/update-healthcheck.yml @@ -0,0 +1,39 @@ +# This workflow is triggered from developer-portal +name: Update healthcheck + +on: + workflow_dispatch: + inputs: + owner: + description: "Owner to checkout" + required: true + type: string + repo: + description: "Repo to checkout" + required: true + type: string + check: + description: "Check ID" + required: true + type: string + conclusion: + description: "Healthcheck conclusion" + required: true + type: string + run_id: + description: "Workflow run ID" + required: true + type: string + +jobs: + + update-healthcheck: + uses: shopware/developer-portal/.github/workflows/update-healthcheck.yml@main + with: + owner: ${{ inputs.owner }} + repo: ${{ inputs.repo }} + check: ${{ inputs.check }} + conclusion: ${{ inputs.conclusion }} + run_id: ${{ inputs.run_id }} + secrets: + TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/apps/docs/.vitepress/config.ts b/apps/docs/.vitepress/config.ts index f8e957ff0..90e7f0ee7 100644 --- a/apps/docs/.vitepress/config.ts +++ b/apps/docs/.vitepress/config.ts @@ -1,254 +1,9 @@ import { defineConfigWithTheme } from "vitepress"; import type { Config as ThemeConfig } from "vitepress-shopware-docs"; import baseConfig from "vitepress-shopware-docs/config"; -import { TsFunctionDescription, TsFunctionsList } from "@shopware-pwa/typer"; -import nav from "./navigation"; +import { TsFunctionDescription, TsFunctionsList } from "@shopware-docs/typer"; import { resolve } from "node:path"; -import { SearchPlugin } from "vitepress-plugin-search"; - -export const sidebar = [ - { - text: "SHOPWARE FRONTENDS", - items: [ - { text: "Overview", link: "/" }, - { text: "Why Shopware Frontends", link: "/why-shopware-frontends" }, - ], - }, - { - text: "FRAMEWORK", - link: "/framework/", - items: [ - { text: "Requirements", link: "/framework/requirements" }, - { text: "Internal Structure", link: "/framework/internal-structure" }, - { - text: "Composables", - link: "/framework/composables", - items: [ - { - text: "Context Composables", - link: "/framework/composables/context-composables", - }, - { - text: "Shared Composables", - link: "/framework/composables/shared-composables", - }, - { - text: "Overwriting Composables", - link: "/framework/composables/overwriting-composables", - }, - ], - }, - { text: "Shopping Experiences", link: "/framework/shopping-experiences" }, - { text: "Styling", link: "/framework/styling" }, - ], - }, - { - text: "BUILDING", - link: "/getting-started/", - items: [ - { - text: "Setup Templates", - link: "/getting-started/templates", - items: [ - { - text: "Demo Store", - link: "/getting-started/templates/demo-store-template", - }, - { - text: "Blank Template", - link: "/getting-started/templates/blank-template", - }, - { - text: "Custom Vue Project", - link: "/getting-started/templates/custom-vue-project", - }, - { - text: "Custom React Project", - link: "/getting-started/templates/custom-react-project", - }, - { - text: "Astro Template", - link: "/getting-started/templates/astro-template", - }, - ], - }, - { text: "Routing", link: "/getting-started/routing" }, - { text: "Languages", link: "/getting-started/languages" }, - { - text: "CMS", - link: "/getting-started/cms/", - items: [ - { text: "Content Pages", link: "/getting-started/cms/content-pages" }, - { - text: "Customize Components", - link: "/getting-started/cms/customize-components", - }, - { text: "Create Blocks", link: "/getting-started/cms/create-blocks" }, - { - text: "Create Elements", - link: "/getting-started/cms/create-elements", - }, - { - text: "Overwriting CMS", - link: "/getting-started/cms/overwriting-cms", - }, - ], - }, - { - text: "E-Commerce", - link: "/getting-started/e-commerce/", - items: [ - { - text: "Product listing", - link: "/getting-started/e-commerce/product-listing", - }, - { - text: "Product detail page", - link: "/getting-started/e-commerce/product-detail-page", - }, - { text: "Prices", link: "/getting-started/e-commerce/prices" }, - { text: "Cart", link: "/getting-started/e-commerce/cart" }, - { text: "Checkout", link: "/getting-started/e-commerce/checkout" }, - { text: "Payments", link: "/getting-started/e-commerce/payments" }, - { - text: "Custome Payment", - link: "/getting-started/e-commerce/custom-payment", - }, - { - text: "JSON-LD", - link: "/getting-started/e-commerce/json-ld", - }, - ], - }, - { - text: "Features", - link: "/getting-started/features/", - items: [ - { - text: "Sitemap", - link: "/getting-started/features/sitemap", - }, - { - text: "Wishlist", - link: "/getting-started/features/wishlist", - }, - { - text: "Custom Products extension", - link: "/getting-started/features/custom-products", - }, - ], - }, - { - text: "Page elements", - link: "/getting-started/page-elements/", - items: [ - { - text: "Breadcrumbs", - link: "/getting-started/page-elements/breadcrumbs", - }, - { text: "Images", link: "/getting-started/page-elements/images" }, - { - text: "Login Form", - link: "/getting-started/page-elements/login-form", - }, - { - text: "Navigation", - link: "/getting-started/page-elements/navigation", - }, - { - text: "Examples", - link: "/getting-started/page-elements/examples/", - items: [ - { - text: "Cart", - link: "/getting-started/page-elements/examples/cart/", - }, - { - text: "Product listing", - link: "/getting-started/page-elements/examples/listing/", - }, - { - text: "Product Detail Page", - link: "/getting-started/page-elements/examples/product-detail-page/", - }, - { - text: "Footer Navigation", - link: "/getting-started/page-elements/examples/footer-navigation/", - }, - { - text: "Navigation", - link: "/getting-started/page-elements/examples/navigation/", - }, - ], - }, - ], - }, - ], - }, - { - text: "BEST PRACTICES", - link: "/best-practices/", - items: [ - { text: "Deployment", link: "/best-practices/deployment" }, - { - text: "Error Handling", - link: "/best-practices/error-handling", - items: [ - { - text: "API Client Error Handling", - link: "/best-practices/error-handling/api-client-error-handling", - }, - ], - }, - { text: "Images", link: "/best-practices/images" }, - { text: "Performance", link: "/best-practices/performance" }, - { text: "Testing", link: "/best-practices/testing" }, - ], - }, - { - text: "RESOURCES", - link: "/resources/", - items: [ - { text: "🚀 Links", link: "/resources/links" }, - { text: "🤗 Community Modules", link: "/resources/community-modules/" }, - { text: "😱 Troubleshooting", link: "/resources/troubleshooting" }, - { - text: "Integrations", - link: "/resources/integrations/", - items: [ - { - text: "Multi CMS instance", - link: "/resources/integrations/multi-cms", - }, - { text: "Strapi", link: "/resources/integrations/strapi/" }, - ], - }, - ], - }, - { - text: "PACKAGE REFERENCE", - link: "/packages/", - items: [ - { text: "Composables", link: "/packages/composables" }, - { - text: "API Client", - link: "/packages/api-client", - items: [ - { - text: "Associations", - link: "/packages/api-client/docs/associations", - }, - { - text: "Storefront URL", - link: "/packages/api-client/docs/storefront-url", - }, - ], - }, - { text: "Types", link: "/packages/types" }, - { text: "Helpers", link: "/packages/helpers" }, - ], - }, -]; +import {sidebar} from "./sidebar"; interface ThemeConfigExtended extends ThemeConfig { ai: { @@ -264,7 +19,6 @@ export default defineConfigWithTheme({ srcDir: "src", // srcExclude: ["tutorial/**/description.md"], In case we need something to be excluded scrollOffset: "header", - ignoreDeadLinks: true, // remove once MR #294 is merged head: [ [ @@ -327,44 +81,23 @@ export default defineConfigWithTheme({ ], themeConfig: { - nav, sidebar, algolia: { - indexName: "", - appId: "", - apiKey: "", - // searchParameters: { - // facetFilters: ["version:v1"], - // }, + indexName: "beta-developer-shopware", + appId: "J1Y01X9HGM", + apiKey: "711e1cadf66a3957aaf183a58aad12a7", }, ai: { endpoint: "", }, - // TODO: temporarily disabled; change to actual repository pattern once vitepress is upgraded to have editLink.pattern: https://vitepress.dev/reference/default-theme-edit-link#site-level-config - editLink: false as any, }, vite: { - define: { - __VUE_OPTIONS_API__: false, - }, - server: { - host: true, - fs: { - // for when developing with locally linked theme - allow: ["../.."], - }, - }, - build: { - minify: "terser", - chunkSizeWarningLimit: Infinity, - }, - json: { - stringify: true, - }, plugins: [ - SearchPlugin(), - TsFunctionsList(), + TsFunctionsList({ + rootDir: resolve(__dirname, "../../../"), + prefix: '/', + }), TsFunctionDescription({ rootDir: resolve(__dirname, "../../../"), dirs: [ @@ -396,8 +129,13 @@ export default defineConfigWithTheme({ ], }), ], - }, - vue: { - reactivityTransform: true, + build: { + rollupOptions: { + external: [ + 'vue-instantsearch/vue3/es', + 'instantsearch.css/themes/algolia-min.css', + ] + } + } }, }); diff --git a/apps/docs/.vitepress/navigation.ts b/apps/docs/.vitepress/navigation.ts deleted file mode 100644 index bf69b40df..000000000 --- a/apps/docs/.vitepress/navigation.ts +++ /dev/null @@ -1,75 +0,0 @@ -const nav = [ - { - link: "https://developer.shopware.com/docs/guides/plugins/apps", - text: "Apps", - }, - { - link: "https://developer.shopware.com/docs/guides/plugins/themes", - text: "Themes", - }, - { - link: "https://frontends.shopware.com/", - text: "Frontends", - repo: "shopware/frontends", - }, - { - link: "https://developer.shopware.com/docs/guides/integrations-api", - text: "Integrations", - }, - { - text: "Resources", - activeMatch: `^/(api)`, - items: [ - { - text: "HTTP APIs", - items: [ - { - text: "Store API", - link: "https://shopware.stoplight.io/docs/store-api/", - repo: "shopware/store-api-reference", - }, - { - text: "Admin API", - link: "https://shopware.stoplight.io/docs/admin-api/", - repo: "shopware/admin-api-reference", - }, - ], - }, - { - text: "Administration", - items: [ - { - text: "Admin Extension SDK", - link: "https://shopware.github.io/admin-extension-sdk/", - repo: "shopware/admin-extension-sdk", - }, - { - text: "Meteor Icon Kit", - link: "https://shopware.github.io/meteor-icon-kit/", - repo: "shopware/meteor-icon-kit", - }, - { - text: "Component Library", - link: "https://shopware.github.io/meteor-component-library/", - repo: "shopware/meteor-component-library", - }, - ], - }, - { - text: "Learning", - items: [ - { - text: "Academy", - link: "https://academy.shopware.com/", - }, - { - text: "YouTube", - link: "https://www.youtube.com/user/shopwareAG", - }, - ], - }, - ], - }, -]; - -export default nav; diff --git a/apps/docs/.vitepress/sidebar.ts b/apps/docs/.vitepress/sidebar.ts new file mode 100644 index 000000000..ac79c01a8 --- /dev/null +++ b/apps/docs/.vitepress/sidebar.ts @@ -0,0 +1,246 @@ +/** + * Sidebar configuration is exported so DevHub can import it and prefix links with /frontends/. + */ +export const sidebar = [ + { + text: "SHOPWARE FRONTENDS", + items: [ + { text: "Overview", link: "/" }, + { text: "Why Shopware Frontends", link: "/why-shopware-frontends" }, + ], + }, + { + text: "FRAMEWORK", + link: "/framework/", + items: [ + { text: "Requirements", link: "/framework/requirements" }, + { text: "Internal Structure", link: "/framework/internal-structure" }, + { + text: "Composables", + link: "/framework/composables", + items: [ + { + text: "Context Composables", + link: "/framework/composables/context-composables", + }, + { + text: "Shared Composables", + link: "/framework/composables/shared-composables", + }, + { + text: "Overwriting Composables", + link: "/framework/composables/overwriting-composables", + }, + ], + }, + { text: "Shopping Experiences", link: "/framework/shopping-experiences" }, + { text: "Styling", link: "/framework/styling" }, + ], + }, + { + text: "BUILDING", + link: "/getting-started/", + items: [ + { + text: "Setup Templates", + link: "/getting-started/templates", + items: [ + { + text: "Demo Store", + link: "/getting-started/templates/demo-store-template", + }, + { + text: "Blank Template", + link: "/getting-started/templates/blank-template", + }, + { + text: "Custom Vue Project", + link: "/getting-started/templates/custom-vue-project", + }, + { + text: "Custom React Project", + link: "/getting-started/templates/custom-react-project", + }, + { + text: "Astro Template", + link: "/getting-started/templates/astro-template", + }, + ], + }, + { text: "Routing", link: "/getting-started/routing" }, + { text: "Languages", link: "/getting-started/languages" }, + { + text: "CMS", + link: "/getting-started/cms/", + items: [ + { text: "Content Pages", link: "/getting-started/cms/content-pages" }, + { + text: "Customize Components", + link: "/getting-started/cms/customize-components", + }, + { text: "Create Blocks", link: "/getting-started/cms/create-blocks" }, + { + text: "Create Elements", + link: "/getting-started/cms/create-elements", + }, + { + text: "Overwriting CMS", + link: "/getting-started/cms/overwriting-cms", + }, + ], + }, + { + text: "E-Commerce", + link: "/getting-started/e-commerce/", + items: [ + { + text: "Product listing", + link: "/getting-started/e-commerce/product-listing", + }, + { + text: "Product detail page", + link: "/getting-started/e-commerce/product-detail-page", + }, + { text: "Prices", link: "/getting-started/e-commerce/prices" }, + { text: "Cart", link: "/getting-started/e-commerce/cart" }, + { text: "Checkout", link: "/getting-started/e-commerce/checkout" }, + { text: "Payments", link: "/getting-started/e-commerce/payments" }, + { + text: "Custome Payment", + link: "/getting-started/e-commerce/custom-payment", + }, + { + text: "JSON-LD", + link: "/getting-started/e-commerce/json-ld", + }, + ], + }, + { + text: "Features", + link: "/getting-started/features/", + items: [ + { + text: "Sitemap", + link: "/getting-started/features/sitemap", + }, + { + text: "Wishlist", + link: "/getting-started/features/wishlist", + }, + { + text: "Custom Products extension", + link: "/getting-started/features/custom-products", + }, + ], + }, + { + text: "Page elements", + link: "/getting-started/page-elements/", + items: [ + { + text: "Breadcrumbs", + link: "/getting-started/page-elements/breadcrumbs", + }, + { text: "Images", link: "/getting-started/page-elements/images" }, + { + text: "Login Form", + link: "/getting-started/page-elements/login-form", + }, + { + text: "Navigation", + link: "/getting-started/page-elements/navigation", + }, + { + text: "Examples", + link: "/getting-started/page-elements/examples/", + items: [ + { + text: "Cart", + link: "/getting-started/page-elements/examples/cart/", + }, + { + text: "Product listing", + link: "/getting-started/page-elements/examples/listing/", + }, + { + text: "Product Detail Page", + link: "/getting-started/page-elements/examples/product-detail-page/", + }, + { + text: "Footer Navigation", + link: "/getting-started/page-elements/examples/footer-navigation/", + }, + { + text: "Navigation", + link: "/getting-started/page-elements/examples/navigation/", + }, + ], + }, + ], + }, + ], + }, + { + text: "BEST PRACTICES", + link: "/best-practices/", + items: [ + { text: "Deployment", link: "/best-practices/deployment" }, + { + text: "Error Handling", + link: "/best-practices/error-handling", + items: [ + { + text: "API Client Error Handling", + link: "/best-practices/error-handling/api-client-error-handling", + }, + ], + }, + { text: "Images", link: "/best-practices/images" }, + { text: "Performance", link: "/best-practices/performance" }, + { text: "Testing", link: "/best-practices/testing" }, + ], + }, + { + text: "RESOURCES", + link: "/resources/", + items: [ + { text: "🚀 Links", link: "/resources/links" }, + { text: "🤗 Community Modules", link: "/resources/community-modules/" }, + { text: "😱 Troubleshooting", link: "/resources/troubleshooting" }, + { + text: "Integrations", + link: "/resources/integrations/", + items: [ + { + text: "Multi CMS instance", + link: "/resources/integrations/multi-cms", + }, + { text: "Strapi", link: "/resources/integrations/strapi/" }, + ], + }, + ], + }, + { + text: "PACKAGE REFERENCE", + link: "/packages/", + items: [ + { text: "Composables", link: "/packages/composables" }, + { + text: "API Client", + link: "/packages/api-client", + items: [ + { + text: "Associations", + link: "/packages/api-client/docs/associations", + }, + { + text: "Storefront URL", + link: "/packages/api-client/docs/storefront-url", + }, + ], + }, + { text: "Types", link: "/packages/types" }, + { text: "Helpers", link: "/packages/helpers" }, + ], + }, +]; \ No newline at end of file diff --git a/apps/docs/.vitepress/theme/components/PageRef.vue b/apps/docs/.vitepress/theme/components/PageRef.vue deleted file mode 100644 index 9fbc9d31b..000000000 --- a/apps/docs/.vitepress/theme/components/PageRef.vue +++ /dev/null @@ -1,50 +0,0 @@ - - - diff --git a/apps/docs/.vitepress/theme/index.ts b/apps/docs/.vitepress/theme/index.ts index 35cf6f557..8a820eb49 100644 --- a/apps/docs/.vitepress/theme/index.ts +++ b/apps/docs/.vitepress/theme/index.ts @@ -1,25 +1,21 @@ // import './styles/index.css' -import { h, App } from "vue"; -import { VPTheme } from "vitepress-shopware-docs"; -import PageRef from "./components/PageRef.vue"; +import {SWAGTheme} from "vitepress-shopware-docs"; // Ai component // import AI from "./components/AI.vue"; import "./custom.css"; -export default Object.assign({}, VPTheme, { - Layout: () => { - // @ts-ignore - return h(VPTheme.Layout, null, { +export default { + ...SWAGTheme({ + slots: { // banner: () => h(Banner), // "content-top": () => h("h1", "We have important Announcement!"), // 'sidebar-top': () => h(PreferenceSwitch), // 'aside-mid': () => h(SponsorsAside), // 'aside-bottom': () => h(VueJobs) - }); - }, - enhanceApp({ app }: { app: App }) { - app.component("PageRef", PageRef); - // app.component("AI", AI); - // app.provide('some-injection-key-if-needed', VALUE) - }, -}); + }, + enhanceApp({app}) { + // app.component("AI", AI); + // app.provide('some-injection-key-if-needed', VALUE) + } + }) +} \ No newline at end of file diff --git a/apps/docs/package.json b/apps/docs/package.json index 4725b17ed..208c121fd 100644 --- a/apps/docs/package.json +++ b/apps/docs/package.json @@ -3,6 +3,7 @@ "private": true, "version": "1.6.1", "description": "", + "type": "module", "scripts": { "dev": "vitepress", "build": "vitepress build", @@ -15,16 +16,17 @@ "@shopware-pwa/types": "workspace:*", "flexsearch": "^0.7.43", "markdown-it": "^14.0.0", - "vitepress": "1.0.0-beta.7", + "vitepress": "^1.0.0-rc.42", "vitepress-plugin-search": "1.0.4-alpha.22", - "vitepress-shopware-docs": "0.3.0-beta.44", + "vitepress-shopware-docs": "^1.1.22", "vue": "^3.4.19" }, "devDependencies": { - "@shopware-pwa/typer": "workspace:*", + "@shopware-docs/typer": "^1.1.22", "@types/markdown-it": "^13.0.7", "@types/node": "^20.11.19", "@vitejs/plugin-vue": "^5.0.4", + "sass": "^1.70.0", "typescript": "^5.3.3" }, "pnpm": { diff --git a/apps/docs/src/getting-started/e-commerce/product-detail-page.md b/apps/docs/src/getting-started/e-commerce/product-detail-page.md index cfb60bac0..4fcf19488 100644 --- a/apps/docs/src/getting-started/e-commerce/product-detail-page.md +++ b/apps/docs/src/getting-started/e-commerce/product-detail-page.md @@ -19,7 +19,7 @@ In order to display information of a product there is a `Product` object needed, - Images - ... -To achieve that, you can utilize methods available within `composables` package (or directly via API client package named `@shopware-pwa/api-client`). In this example we will use [useProductSearch](../../../packages/composables/useProductSearch.md). +To achieve that, you can utilize methods available within `composables` package (or directly via API client package named `@shopware-pwa/api-client`). In this example we will use [useProductSearch](../../packages/composables/useProductSearch.md). :::info Associations Keep in mind that not every field, or inner object of the `Product` entity is available automatically. @@ -66,7 +66,7 @@ const productNumber = computed(() => product.value?.productNumber); Each product can have additional resource loaded asynchronously like Cross-Sells, or Customer Reviews. -Thanks to [useProductAssociations](../../../packages/composables/useProductAssociations.md) composable, you can load it providing the product you are on: +Thanks to [useProductAssociations](../../packages/composables/useProductAssociations.md) composable, you can load it providing the product you are on: ```js const { loadAssociations, isLoading, productAssociations } = diff --git a/apps/docs/src/getting-started/page-elements/breadcrumbs.md b/apps/docs/src/getting-started/page-elements/breadcrumbs.md index 217ad8227..026d1bc99 100644 --- a/apps/docs/src/getting-started/page-elements/breadcrumbs.md +++ b/apps/docs/src/getting-started/page-elements/breadcrumbs.md @@ -22,8 +22,8 @@ In this chapter you will learn how to ### Quick reference -- [useBreadcrumbs](/packages/composables/useBreadcrumbs) is a composable used for a breadcrumbs management with sharable state -- [getCategoryBreadcrumbs](/packages/helpers/getCategoryBreadcrumbs) is a helper used for converting `Category` to the `Breadcrumb` object +- [useBreadcrumbs](../../packages/composables/useBreadcrumbs) is a composable used for a breadcrumbs management with sharable state +- [getCategoryBreadcrumbs](../../packages/helpers/getCategoryBreadcrumbs) is a helper used for converting `Category` to the `Breadcrumb` object ## Building breadcrumbs for a static page @@ -49,7 +49,7 @@ Each CMS page contains the `Category` with `breadcrumb` array, which contains a breadcrumb: ["Home", "Main navigation ", "Summer Party"] ``` -we can convert current `string` array to the `Breadcrumb` object using [getCategoryBreadcrumbs](/packages/helpers/getCategoryBreadcrumbs) helper, and then pass it to [useBreadcrumbs](/packages/composables/useBreadcrumbs) composable. +we can convert current `string` array to the `Breadcrumb` object using [getCategoryBreadcrumbs](../../packages/helpers/getCategoryBreadcrumbs) helper, and then pass it to [useBreadcrumbs](../../packages/composables/useBreadcrumbs) composable. ```ts import { getCategoryBreadcrumbs } from "@shopware-pwa/helpers-next"; @@ -74,7 +74,7 @@ onBeforeRouteLeave(() => { ## Displaying Breadcrumbs -Breadcrumbs are stored in sharable variable `breadcrumbs` in [useBreadcrumbs](/packages/composables/useBreadcrumbs) composable. +Breadcrumbs are stored in sharable variable `breadcrumbs` in [useBreadcrumbs](../../packages/composables/useBreadcrumbs) composable. ```vue