Skip to content

Pages by Operation

You can use the OAOperation component to render a specific operation.

Example

Creating operations pages

To generate pages for each operation, create a directory named operations in the docs directory. Inside the operations directory, create a file named [operationId].md and a file named [operationId].paths.js.

/docs
├── /operations
│   ├── [operationId].md
│   └── [operationId].paths.js

Paths Loader File

Using the Paths Loader File feature of VitePress, you can use the [operationId].paths.js file to generate the pages for each operation.

ts
import { usePaths } from 'vitepress-openapi'
import spec from '../public/openapi.json' with {type: 'json'}

export default {
    paths() {
        return usePaths({ spec })
            .getPathsByVerbs()
            .map(({ operationId, summary }) => {
                return {
                    params: {
                        operationId,
                        pageTitle: `${summary} - vitepress-openapi`,
                    },
                }
            })
    },
}

Meta descriptions

getPathsByVerbs() also exposes each operation's raw Markdown description. Combined with the markdownToPlainText helper, you can use it to generate a <meta name="description"> for each page:

ts
import { markdownToPlainText, usePaths } from 'vitepress-openapi'
import spec from '../public/openapi.json' with {type: 'json'}

export default {
    paths() {
        return usePaths({ spec })
            .getPathsByVerbs()
            .map(({ operationId, summary, description }) => {
                return {
                    params: {
                        operationId,
                        pageTitle: `${summary} - vitepress-openapi`,
                        description: markdownToPlainText(description, { maxLength: 160 }),
                    },
                }
            })
    },
}

markdownToPlainText reduces the Markdown (and any inline HTML) to a single line of plain text, truncated at a word boundary when maxLength is set.

Then map the params onto the page data in your .vitepress/config.[js,ts] file, using the transformPageData hook:

ts
export default defineConfig({
    transformPageData(pageData) {
        if (pageData.params?.pageTitle) {
            pageData.title = pageData.params.pageTitle
        }
        if (pageData.params?.description) {
            pageData.description = pageData.params.description
        }
    },
})

Markdown File

In the [operationId].md file, you can use the OAOperation component to render the operation.

If you have configured the OpenAPI Specification using the useOpenapi composable in your .vitepress/theme/index.[js,ts] file, you can just pass the operationId prop to the OAOperation component, and it will automatically fetch the spec from the global context.

markdown
---
aside: false
outline: false
title: vitepress-openapi
---

<script setup lang="ts">
import { useRoute } from 'vitepress'

const route = useRoute()

const operationId = route.data.params.operationId
</script>

<OAOperation :operationId="operationId" />

Searching Operations

If you want to make use of search on your site, the default local search will not work due to https://github.com/vuejs/vitepress/issues/2939

Consider using vitepress-plugin-pagefind, which works with dynamic routes.