bloggrify/bloggrifypublic Fork
⑂ main
Commits
⬇ Clone ▾
git clone https://git.rickub.com/bloggrify/bloggrify.git
git clone ssh://git@rickub.com/bloggrify/bloggrify.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

Download ZIP
fix: make page redirections behave as documented fce1cf8 · on main · hlassiege · Jul 27, 2026
content.config.ts · 99 lines · 3.6 KBTypeScript Blame HistoryRaw
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
import { defineCollection, defineContentConfig, z } from '@nuxt/content'
import { useNuxt } from '@nuxt/kit'
import { joinURL } from 'ufo'
import { defineSitemapSchema } from '@nuxtjs/sitemap/content'
import { defineRobotsSchema } from '@nuxtjs/robots/content'
import { defineSchemaOrgSchema } from 'nuxt-schema-org/content'
const { options } = useNuxt()
const cwd = joinURL(options.rootDir, 'content')


export default defineContentConfig({
  collections: {
    page: defineCollection({
      type: 'page',
      source: {
        cwd,
        include: '**/*.md',
        prefix: '',
      },
      schema: z.object({
        pageid: z.string().optional(),
        id: z.string().optional(),

        title: z.string().optional(),
        description: z.string().optional(),
        date: z.coerce.date().optional(),
        cover: z.string().optional(),

        comments: z.boolean().optional(),
        nocomments: z.boolean().optional(),
        listed: z.boolean().optional(),
        /** @deprecated synonym of `listed: false`, normalised at build time by the bloggrify module. */
        hidden: z.boolean().optional(),
        draft: z.boolean().optional(),

        readingTime: z.object({
          time: z.number().optional(),
          text: z.string().optional()
        }).optional(),

        table_of_contents: z.boolean().optional(),
        // Per-page opt-out, mirroring `nocomments`. An absent optional boolean comes back
        // from the content store as `false` (never `undefined`), so a per-page override has
        // to be expressed as a truthy flag rather than `table_of_contents: false`.
        notoc: z.boolean().optional(),
        layout: z.string().optional(),

        tags: z.array(z.string()).optional(),
        categories: z.array(z.string()).optional(),

        author: z.string().optional(),

        redirect_to_domain: z.string().optional(),
        redirect_to_full_url: z.string().optional(),

        language: z.string().optional(),
        alternates: z.array(z.object({
          hreflang: z.string(),
          href: z.string()
        })).optional(),

        schemaOrg: defineSchemaOrgSchema(),

        links: z.array(z.object({
          label: z.string(),
          icon: z.string(),
          to: z.string(),
          target: z.string().optional()
        })).optional(),

        // Controls search visibility, independently of `listed`, which only controls
        // whether a page shows up in the blog's own listings.
        // `robots: false` means noindex/nofollow; a string sets the directive verbatim.
        robots: defineRobotsSchema({ z }),

        // What gets advertised must be exactly what exists and what we want indexed.
        // Drafts are never generated, so leaving one in the sitemap advertises a 404.
        // `robots: false` pages do exist, but asking Google to index a page that says
        // noindex earns a "Submitted URL marked noindex" error, so they come out too.
        // Redirecting pages come out for the same reason: they carry no content, point their
        // canonical at another URL and ask not to be indexed, so advertising them only sends
        // crawlers on a detour.
        // Note this filter is on us: unlike its Nuxt Content v2 integration, @nuxtjs/sitemap
        // does not exclude `robots: false` entries by itself on v3.
        // Unlisted pages stay in, they are real, reachable pages and `/about` is one.
        sitemap: defineSitemapSchema({
          name: 'page',
          z,
          filter: entry => entry.draft !== true
            && entry.robots !== false
            && !entry.redirect_to_full_url
            && !entry.redirect_to_domain,
        }),


      })
    })
  }
})