Stelle docs-site auf Nuxt-UI-Docs-Template-Stil um
This commit is contained in:
3
docs-site/.gitignore
vendored
Normal file
3
docs-site/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
node_modules
|
||||||
|
.nuxt
|
||||||
|
.output
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
FROM node:20-alpine AS builder
|
FROM node:20-alpine AS builder
|
||||||
WORKDIR /app/docs-site
|
WORKDIR /app/docs-site
|
||||||
|
|
||||||
COPY docs-site/package.json ./
|
COPY docs-site/package.json docs-site/package-lock.json ./
|
||||||
RUN npm install
|
RUN npm ci
|
||||||
|
|
||||||
COPY docs-site ./
|
COPY docs-site ./
|
||||||
COPY docs /app/docs
|
COPY docs /app/docs
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# FEDEO Docs Site (Nuxt Content)
|
# FEDEO Docs Site (Nuxt UI + Nuxt Content)
|
||||||
|
|
||||||
Diese Docs-App basiert auf Nuxt Content und rendert die Inhalte aus dem Repository-Ordner `docs/`.
|
Diese Docs-App nutzt den Standardstil des offiziellen Nuxt-UI-Docs-Templates und rendert Inhalte aus `docs/`.
|
||||||
|
|
||||||
## Lokale Entwicklung
|
## Lokale Entwicklung
|
||||||
|
|
||||||
@@ -11,20 +11,21 @@ npm install
|
|||||||
npm run dev
|
npm run dev
|
||||||
```
|
```
|
||||||
|
|
||||||
Die App ist danach unter `http://localhost:3005` erreichbar.
|
Danach ist die App unter `http://localhost:3005` erreichbar.
|
||||||
|
|
||||||
## Build
|
## Build
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm run build
|
npm run build
|
||||||
|
npm run preview
|
||||||
```
|
```
|
||||||
|
|
||||||
## Production-Deploy
|
## Production-Deploy
|
||||||
|
|
||||||
Das Docker-Image startet einen Node-Server auf Port `3000`.
|
Das Docker-Image startet einen Nuxt Node-Server auf Port `3000`.
|
||||||
In der Haupt-`docker-compose.yml` wird die App hinter Traefik unter `/docs` veröffentlicht.
|
In der Haupt-`docker-compose.yml` ist der Service hinter Traefik unter `/docs` veröffentlicht.
|
||||||
|
|
||||||
## Content-Quelle
|
## Content-Synchronisierung
|
||||||
|
|
||||||
Vor `dev` und `build` wird automatisch synchronisiert:
|
Vor `dev` und `build` wird automatisch synchronisiert:
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
<template>
|
|
||||||
<NuxtPage />
|
|
||||||
</template>
|
|
||||||
57
docs-site/app/app.config.ts
Normal file
57
docs-site/app/app.config.ts
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
export default defineAppConfig({
|
||||||
|
ui: {
|
||||||
|
colors: {
|
||||||
|
primary: 'green',
|
||||||
|
neutral: 'slate'
|
||||||
|
},
|
||||||
|
footer: {
|
||||||
|
slots: {
|
||||||
|
root: 'border-t border-default',
|
||||||
|
left: 'text-sm text-muted'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
seo: {
|
||||||
|
siteName: 'FEDEO Docs'
|
||||||
|
},
|
||||||
|
header: {
|
||||||
|
title: 'FEDEO Docs',
|
||||||
|
to: '/',
|
||||||
|
search: true,
|
||||||
|
colorMode: true,
|
||||||
|
links: [
|
||||||
|
{
|
||||||
|
icon: 'i-simple-icons-github',
|
||||||
|
to: 'https://git.federspiel.tech/flfeders/FEDEO',
|
||||||
|
target: '_blank',
|
||||||
|
'aria-label': 'Repository'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
footer: {
|
||||||
|
credits: `Built with Nuxt UI • © ${new Date().getFullYear()} FEDEO`,
|
||||||
|
colorMode: false,
|
||||||
|
links: [
|
||||||
|
{
|
||||||
|
icon: 'i-simple-icons-github',
|
||||||
|
to: 'https://git.federspiel.tech/flfeders/FEDEO',
|
||||||
|
target: '_blank',
|
||||||
|
'aria-label': 'Repository'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
toc: {
|
||||||
|
title: 'Inhaltsverzeichnis',
|
||||||
|
bottom: {
|
||||||
|
title: 'Links',
|
||||||
|
links: [
|
||||||
|
{
|
||||||
|
icon: 'i-lucide-book-open',
|
||||||
|
label: 'FEDEO Projekt',
|
||||||
|
to: 'https://git.federspiel.tech/flfeders/FEDEO',
|
||||||
|
target: '_blank'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
44
docs-site/app/app.vue
Normal file
44
docs-site/app/app.vue
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
const { seo } = useAppConfig()
|
||||||
|
|
||||||
|
const { data: navigation } = await useAsyncData('navigation', () => queryCollectionNavigation('docs'))
|
||||||
|
const { data: files } = useLazyAsyncData('search', () => queryCollectionSearchSections('docs'), {
|
||||||
|
server: false
|
||||||
|
})
|
||||||
|
|
||||||
|
useHead({
|
||||||
|
meta: [{ name: 'viewport', content: 'width=device-width, initial-scale=1' }],
|
||||||
|
htmlAttrs: { lang: 'de' }
|
||||||
|
})
|
||||||
|
|
||||||
|
useSeoMeta({
|
||||||
|
titleTemplate: `%s - ${seo?.siteName}`,
|
||||||
|
ogSiteName: seo?.siteName,
|
||||||
|
twitterCard: 'summary_large_image'
|
||||||
|
})
|
||||||
|
|
||||||
|
provide('navigation', navigation)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<UApp>
|
||||||
|
<NuxtLoadingIndicator />
|
||||||
|
|
||||||
|
<AppHeader />
|
||||||
|
|
||||||
|
<UMain>
|
||||||
|
<NuxtLayout>
|
||||||
|
<NuxtPage />
|
||||||
|
</NuxtLayout>
|
||||||
|
</UMain>
|
||||||
|
|
||||||
|
<AppFooter />
|
||||||
|
|
||||||
|
<ClientOnly>
|
||||||
|
<LazyUContentSearch
|
||||||
|
:files="files"
|
||||||
|
:navigation="navigation"
|
||||||
|
/>
|
||||||
|
</ClientOnly>
|
||||||
|
</UApp>
|
||||||
|
</template>
|
||||||
25
docs-site/app/assets/css/main.css
Normal file
25
docs-site/app/assets/css/main.css
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
@import "tailwindcss";
|
||||||
|
@import "@nuxt/ui";
|
||||||
|
|
||||||
|
@source "../../../content/**/*";
|
||||||
|
|
||||||
|
@theme static {
|
||||||
|
--container-8xl: 90rem;
|
||||||
|
--font-sans: 'Public Sans', sans-serif;
|
||||||
|
|
||||||
|
--color-green-50: #EFFDF5;
|
||||||
|
--color-green-100: #D9FBE8;
|
||||||
|
--color-green-200: #B3F5D1;
|
||||||
|
--color-green-300: #75EDAE;
|
||||||
|
--color-green-400: #00DC82;
|
||||||
|
--color-green-500: #00C16A;
|
||||||
|
--color-green-600: #00A155;
|
||||||
|
--color-green-700: #007F45;
|
||||||
|
--color-green-800: #016538;
|
||||||
|
--color-green-900: #0A5331;
|
||||||
|
--color-green-950: #052E16;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--ui-container: var(--container-8xl);
|
||||||
|
}
|
||||||
23
docs-site/app/components/AppFooter.vue
Normal file
23
docs-site/app/components/AppFooter.vue
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
const { footer } = useAppConfig()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<UFooter>
|
||||||
|
<template #left>
|
||||||
|
{{ footer.credits }}
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #right>
|
||||||
|
<UColorModeButton v-if="footer?.colorMode" />
|
||||||
|
|
||||||
|
<template v-if="footer?.links">
|
||||||
|
<UButton
|
||||||
|
v-for="(link, index) of footer?.links"
|
||||||
|
:key="index"
|
||||||
|
v-bind="{ color: 'neutral', variant: 'ghost', ...link }"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</UFooter>
|
||||||
|
</template>
|
||||||
49
docs-site/app/components/AppHeader.vue
Normal file
49
docs-site/app/components/AppHeader.vue
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import type { ContentNavigationItem } from '@nuxt/content'
|
||||||
|
|
||||||
|
const navigation = inject<Ref<ContentNavigationItem[]>>('navigation')
|
||||||
|
const { header } = useAppConfig()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<UHeader
|
||||||
|
:ui="{ center: 'flex-1' }"
|
||||||
|
:to="header?.to || '/'"
|
||||||
|
>
|
||||||
|
<UContentSearchButton
|
||||||
|
v-if="header?.search"
|
||||||
|
:collapsed="false"
|
||||||
|
class="w-full"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<template #left>
|
||||||
|
<NuxtLink :to="header?.to || '/'">
|
||||||
|
<AppLogo class="w-auto h-6 shrink-0" />
|
||||||
|
</NuxtLink>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #right>
|
||||||
|
<UContentSearchButton
|
||||||
|
v-if="header?.search"
|
||||||
|
class="lg:hidden"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<UColorModeButton v-if="header?.colorMode" />
|
||||||
|
|
||||||
|
<template v-if="header?.links">
|
||||||
|
<UButton
|
||||||
|
v-for="(link, index) of header.links"
|
||||||
|
:key="index"
|
||||||
|
v-bind="{ color: 'neutral', variant: 'ghost', ...link }"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #body>
|
||||||
|
<UContentNavigation
|
||||||
|
highlight
|
||||||
|
:navigation="navigation"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</UHeader>
|
||||||
|
</template>
|
||||||
3
docs-site/app/components/AppLogo.vue
Normal file
3
docs-site/app/components/AppLogo.vue
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<template>
|
||||||
|
<span class="font-semibold text-primary">FEDEO Docs</span>
|
||||||
|
</template>
|
||||||
31
docs-site/app/error.vue
Normal file
31
docs-site/app/error.vue
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import type { NuxtError } from '#app'
|
||||||
|
|
||||||
|
defineProps<{
|
||||||
|
error: NuxtError
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const { data: navigation } = await useAsyncData('navigation', () => queryCollectionNavigation('docs'))
|
||||||
|
const { data: files } = useLazyAsyncData('search', () => queryCollectionSearchSections('docs'), {
|
||||||
|
server: false
|
||||||
|
})
|
||||||
|
|
||||||
|
provide('navigation', navigation)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<UApp>
|
||||||
|
<AppHeader />
|
||||||
|
|
||||||
|
<UError :error="error" />
|
||||||
|
|
||||||
|
<AppFooter />
|
||||||
|
|
||||||
|
<ClientOnly>
|
||||||
|
<LazyUContentSearch
|
||||||
|
:files="files"
|
||||||
|
:navigation="navigation"
|
||||||
|
/>
|
||||||
|
</ClientOnly>
|
||||||
|
</UApp>
|
||||||
|
</template>
|
||||||
22
docs-site/app/layouts/docs.vue
Normal file
22
docs-site/app/layouts/docs.vue
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import type { ContentNavigationItem } from '@nuxt/content'
|
||||||
|
|
||||||
|
const navigation = inject<Ref<ContentNavigationItem[]>>('navigation')
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<UContainer>
|
||||||
|
<UPage>
|
||||||
|
<template #left>
|
||||||
|
<UPageAside>
|
||||||
|
<UContentNavigation
|
||||||
|
highlight
|
||||||
|
:navigation="navigation"
|
||||||
|
/>
|
||||||
|
</UPageAside>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<slot />
|
||||||
|
</UPage>
|
||||||
|
</UContainer>
|
||||||
|
</template>
|
||||||
90
docs-site/app/pages/[...slug].vue
Normal file
90
docs-site/app/pages/[...slug].vue
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import type { ContentNavigationItem } from '@nuxt/content'
|
||||||
|
import { findPageHeadline } from '@nuxt/content/utils'
|
||||||
|
|
||||||
|
definePageMeta({
|
||||||
|
layout: 'docs'
|
||||||
|
})
|
||||||
|
|
||||||
|
const route = useRoute()
|
||||||
|
const { toc } = useAppConfig()
|
||||||
|
const navigation = inject<Ref<ContentNavigationItem[]>>('navigation')
|
||||||
|
|
||||||
|
const { data: page } = await useAsyncData(route.path, () => queryCollection('docs').path(route.path).first())
|
||||||
|
if (!page.value) {
|
||||||
|
throw createError({ statusCode: 404, statusMessage: 'Seite nicht gefunden', fatal: true })
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data: surround } = await useAsyncData(`${route.path}-surround`, () => {
|
||||||
|
return queryCollectionItemSurroundings('docs', route.path, {
|
||||||
|
fields: ['description']
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
const title = page.value.seo?.title || page.value.title
|
||||||
|
const description = page.value.seo?.description || page.value.description
|
||||||
|
|
||||||
|
useSeoMeta({
|
||||||
|
title,
|
||||||
|
ogTitle: title,
|
||||||
|
description,
|
||||||
|
ogDescription: description
|
||||||
|
})
|
||||||
|
|
||||||
|
const headline = computed(() => findPageHeadline(navigation?.value, page.value?.path))
|
||||||
|
|
||||||
|
const links = computed(() => {
|
||||||
|
return [...(toc?.bottom?.links || [])].filter(Boolean)
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<UPage v-if="page">
|
||||||
|
<UPageHeader
|
||||||
|
:title="page.title"
|
||||||
|
:description="page.description"
|
||||||
|
:headline="headline"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<UPageBody>
|
||||||
|
<ContentRenderer
|
||||||
|
v-if="page"
|
||||||
|
:value="page"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<USeparator v-if="surround?.length" />
|
||||||
|
|
||||||
|
<UContentSurround :surround="surround" />
|
||||||
|
</UPageBody>
|
||||||
|
|
||||||
|
<template
|
||||||
|
v-if="page?.body?.toc?.links?.length"
|
||||||
|
#right
|
||||||
|
>
|
||||||
|
<UContentToc
|
||||||
|
:title="toc?.title"
|
||||||
|
:links="page.body?.toc?.links"
|
||||||
|
>
|
||||||
|
<template
|
||||||
|
v-if="toc?.bottom"
|
||||||
|
#bottom
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="hidden lg:block space-y-6"
|
||||||
|
:class="{ 'mt-6!': page.body?.toc?.links?.length }"
|
||||||
|
>
|
||||||
|
<USeparator
|
||||||
|
v-if="page.body?.toc?.links?.length"
|
||||||
|
type="dashed"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<UPageLinks
|
||||||
|
:title="toc.bottom.title"
|
||||||
|
:links="links"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</UContentToc>
|
||||||
|
</template>
|
||||||
|
</UPage>
|
||||||
|
</template>
|
||||||
25
docs-site/app/pages/index.vue
Normal file
25
docs-site/app/pages/index.vue
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
const { data: page } = await useAsyncData('index', () => queryCollection('landing').path('/').first())
|
||||||
|
if (!page.value) {
|
||||||
|
throw createError({ statusCode: 404, statusMessage: 'Seite nicht gefunden', fatal: true })
|
||||||
|
}
|
||||||
|
|
||||||
|
const title = page.value.seo?.title || page.value.title
|
||||||
|
const description = page.value.seo?.description || page.value.description
|
||||||
|
|
||||||
|
useSeoMeta({
|
||||||
|
titleTemplate: '',
|
||||||
|
title,
|
||||||
|
ogTitle: title,
|
||||||
|
description,
|
||||||
|
ogDescription: description
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<ContentRenderer
|
||||||
|
v-if="page"
|
||||||
|
:value="page"
|
||||||
|
:prose="false"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
@@ -1,106 +0,0 @@
|
|||||||
:root {
|
|
||||||
--bg: #f6f8f7;
|
|
||||||
--panel: #ffffff;
|
|
||||||
--text: #1f2937;
|
|
||||||
--muted: #5f6b7a;
|
|
||||||
--accent: #0b6e4f;
|
|
||||||
--line: #d8e0dc;
|
|
||||||
}
|
|
||||||
|
|
||||||
* {
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
margin: 0;
|
|
||||||
font-family: ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial, sans-serif;
|
|
||||||
color: var(--text);
|
|
||||||
background: radial-gradient(circle at 10% 10%, #e7f2ed, transparent 35%), var(--bg);
|
|
||||||
}
|
|
||||||
|
|
||||||
.docs-layout {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: 280px minmax(0, 1fr);
|
|
||||||
min-height: 100vh;
|
|
||||||
}
|
|
||||||
|
|
||||||
.docs-aside {
|
|
||||||
border-right: 1px solid var(--line);
|
|
||||||
background: var(--panel);
|
|
||||||
padding: 1rem;
|
|
||||||
position: sticky;
|
|
||||||
top: 0;
|
|
||||||
height: 100vh;
|
|
||||||
overflow: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.docs-brand {
|
|
||||||
display: block;
|
|
||||||
font-weight: 700;
|
|
||||||
color: var(--accent);
|
|
||||||
text-decoration: none;
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.docs-sidebar ul {
|
|
||||||
list-style: none;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0 0 0 0.8rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.docs-sidebar > ul {
|
|
||||||
padding-left: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.docs-sidebar li {
|
|
||||||
margin: 0.3rem 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.docs-sidebar a {
|
|
||||||
color: var(--text);
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.docs-sidebar a.router-link-active {
|
|
||||||
color: var(--accent);
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
|
|
||||||
.docs-main {
|
|
||||||
padding: 2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.docs-article {
|
|
||||||
max-width: 900px;
|
|
||||||
background: var(--panel);
|
|
||||||
border: 1px solid var(--line);
|
|
||||||
border-radius: 14px;
|
|
||||||
padding: 2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.docs-article h1,
|
|
||||||
.docs-article h2,
|
|
||||||
.docs-article h3 {
|
|
||||||
margin-top: 1.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 900px) {
|
|
||||||
.docs-layout {
|
|
||||||
grid-template-columns: 1fr;
|
|
||||||
}
|
|
||||||
|
|
||||||
.docs-aside {
|
|
||||||
position: static;
|
|
||||||
height: auto;
|
|
||||||
border-right: none;
|
|
||||||
border-bottom: 1px solid var(--line);
|
|
||||||
}
|
|
||||||
|
|
||||||
.docs-main {
|
|
||||||
padding: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.docs-article {
|
|
||||||
padding: 1rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
interface NavItem {
|
|
||||||
title?: string
|
|
||||||
_path?: string
|
|
||||||
children?: NavItem[]
|
|
||||||
}
|
|
||||||
|
|
||||||
defineProps<{ items: NavItem[] }>()
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<nav class="docs-sidebar">
|
|
||||||
<ul>
|
|
||||||
<li v-for="item in items" :key="item._path || item.title">
|
|
||||||
<NuxtLink v-if="item._path" :to="item._path">{{ item.title }}</NuxtLink>
|
|
||||||
<span v-else>{{ item.title }}</span>
|
|
||||||
<DocsSidebar v-if="item.children?.length" :items="item.children" />
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</nav>
|
|
||||||
</template>
|
|
||||||
25
docs-site/content.config.ts
Normal file
25
docs-site/content.config.ts
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
import { defineCollection, defineContentConfig, z } from '@nuxt/content'
|
||||||
|
|
||||||
|
export default defineContentConfig({
|
||||||
|
collections: {
|
||||||
|
landing: defineCollection({
|
||||||
|
type: 'page',
|
||||||
|
source: 'index.md'
|
||||||
|
}),
|
||||||
|
docs: defineCollection({
|
||||||
|
type: 'page',
|
||||||
|
source: {
|
||||||
|
include: '**',
|
||||||
|
exclude: ['index.md']
|
||||||
|
},
|
||||||
|
schema: z.object({
|
||||||
|
links: z.array(z.object({
|
||||||
|
label: z.string(),
|
||||||
|
icon: z.string(),
|
||||||
|
to: z.string(),
|
||||||
|
target: z.string().optional()
|
||||||
|
})).optional()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
@@ -1,22 +1,27 @@
|
|||||||
export default defineNuxtConfig({
|
export default defineNuxtConfig({
|
||||||
modules: ['@nuxt/content'],
|
modules: [
|
||||||
|
'@nuxt/image',
|
||||||
|
'@nuxt/ui',
|
||||||
|
'@nuxt/content'
|
||||||
|
],
|
||||||
css: ['~/assets/css/main.css'],
|
css: ['~/assets/css/main.css'],
|
||||||
app: {
|
|
||||||
head: {
|
|
||||||
title: 'FEDEO Docs',
|
|
||||||
meta: [
|
|
||||||
{ name: 'description', content: 'Versionierte FEDEO-Dokumentation auf Nuxt Content.' }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
content: {
|
content: {
|
||||||
documentDriven: false,
|
build: {
|
||||||
highlight: {
|
markdown: {
|
||||||
theme: 'github-light'
|
toc: {
|
||||||
|
searchDepth: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
experimental: {
|
||||||
|
asyncContext: true
|
||||||
|
},
|
||||||
|
compatibilityDate: '2024-07-11',
|
||||||
nitro: {
|
nitro: {
|
||||||
preset: 'node-server'
|
preset: 'node-server'
|
||||||
},
|
},
|
||||||
compatibilityDate: '2025-01-01'
|
icon: {
|
||||||
|
provider: 'iconify'
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
12675
docs-site/package-lock.json
generated
Normal file
12675
docs-site/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,15 +1,23 @@
|
|||||||
{
|
{
|
||||||
"name": "fedeo-docs-site",
|
"name": "fedeo-docs-site",
|
||||||
"version": "2.0.0",
|
|
||||||
"private": true,
|
"private": true,
|
||||||
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "node ./scripts/sync-content.mjs && nuxi dev --host 0.0.0.0 --port 3005",
|
"build": "node ./scripts/sync-content.mjs && nuxt build",
|
||||||
"build": "node ./scripts/sync-content.mjs && nuxi build",
|
"dev": "node ./scripts/sync-content.mjs && nuxt dev --host 0.0.0.0 --port 3005",
|
||||||
"preview": "nuxi preview --host 0.0.0.0 --port 3005"
|
"preview": "nuxt preview --host 0.0.0.0 --port 3005",
|
||||||
|
"postinstall": "nuxt prepare"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"nuxt": "^3.17.7",
|
"@iconify-json/lucide": "^1.2.102",
|
||||||
"@nuxt/content": "^2.13.4"
|
"@iconify-json/simple-icons": "^1.2.78",
|
||||||
|
"@nuxt/content": "^3.12.0",
|
||||||
|
"@nuxt/image": "^2.0.0",
|
||||||
|
"@nuxt/ui": "^4.6.1",
|
||||||
|
"nuxt": "^4.4.2"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"typescript": "^6.0.2"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=20.0"
|
"node": ">=20.0"
|
||||||
|
|||||||
@@ -1,30 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
const route = useRoute()
|
|
||||||
|
|
||||||
const contentPath = computed(() => route.path)
|
|
||||||
const { data: navigation } = await useAsyncData('docs-navigation', () => fetchContentNavigation())
|
|
||||||
const { data: page } = await useAsyncData(
|
|
||||||
() => `docs-page-${contentPath.value}`,
|
|
||||||
() => queryContent().where({ _path: contentPath.value }).findOne(),
|
|
||||||
{ watch: [contentPath] }
|
|
||||||
)
|
|
||||||
|
|
||||||
if (!page.value) {
|
|
||||||
throw createError({ statusCode: 404, statusMessage: 'Seite nicht gefunden' })
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div class="docs-layout">
|
|
||||||
<aside class="docs-aside">
|
|
||||||
<NuxtLink class="docs-brand" to="/">FEDEO Docs</NuxtLink>
|
|
||||||
<DocsSidebar :items="navigation || []" />
|
|
||||||
</aside>
|
|
||||||
|
|
||||||
<main class="docs-main">
|
|
||||||
<article class="docs-article">
|
|
||||||
<ContentRenderer :value="page" />
|
|
||||||
</article>
|
|
||||||
</main>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
const { data: navigation } = await useAsyncData('docs-navigation', () => fetchContentNavigation())
|
|
||||||
const { data: page } = await useAsyncData('docs-page-index', () =>
|
|
||||||
queryContent().where({ _path: '/' }).findOne()
|
|
||||||
)
|
|
||||||
|
|
||||||
if (!page.value) {
|
|
||||||
throw createError({ statusCode: 404, statusMessage: 'Seite nicht gefunden' })
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div class="docs-layout">
|
|
||||||
<aside class="docs-aside">
|
|
||||||
<NuxtLink class="docs-brand" to="/">FEDEO Docs</NuxtLink>
|
|
||||||
<DocsSidebar :items="navigation || []" />
|
|
||||||
</aside>
|
|
||||||
|
|
||||||
<main class="docs-main">
|
|
||||||
<article class="docs-article">
|
|
||||||
<ContentRenderer :value="page" />
|
|
||||||
</article>
|
|
||||||
</main>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
@@ -1,5 +1,3 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"extends": "./.nuxt/tsconfig.json"
|
||||||
"types": ["@types/node"]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user