create-ginko 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +28 -0
- package/README.md +15 -8
- package/index.mjs +115 -44
- package/package.json +6 -1
- package/presets/gastro/app/pages/index.vue +6 -4
- package/presets/gastro-de/app/pages/index.vue +6 -4
- package/template-files.mjs +377 -0
- package/templates/blog/.env.example +8 -0
- package/templates/blog/.github/screenshots/home-dark.png +0 -0
- package/templates/blog/.github/screenshots/home-light.png +0 -0
- package/templates/blog/.github/workflows/ci.yml +27 -0
- package/templates/blog/DESIGN.md +197 -0
- package/templates/blog/LICENSE +21 -0
- package/templates/blog/MEDIA.md +29 -0
- package/templates/blog/NOTES.md +16 -0
- package/templates/blog/README.md +274 -0
- package/templates/blog/app/app.config.ts +29 -0
- package/templates/blog/app/app.vue +7 -0
- package/templates/blog/app/assets/css/main.css +18 -0
- package/templates/blog/app/assets/css/tokens.css +400 -0
- package/templates/blog/app/components/InitialsAvatar.vue +18 -0
- package/templates/blog/app/components/ProseBody.vue +13 -0
- package/templates/blog/app/components/block/Cards.vue +54 -0
- package/templates/blog/app/components/block/Cta.vue +26 -0
- package/templates/blog/app/components/block/Empty.vue +26 -0
- package/templates/blog/app/components/block/Features.vue +24 -0
- package/templates/blog/app/components/block/Hero.vue +47 -0
- package/templates/blog/app/components/block/PageHeader.vue +21 -0
- package/templates/blog/app/components/block/Section.vue +31 -0
- package/templates/blog/app/components/blog/Byline.vue +22 -0
- package/templates/blog/app/components/blog/PostList.vue +33 -0
- package/templates/blog/app/components/blog/TagList.vue +17 -0
- package/templates/blog/app/components/home/LatestPost.vue +31 -0
- package/templates/blog/app/components/people/List.vue +41 -0
- package/templates/blog/app/components/site/Contact.vue +38 -0
- package/templates/blog/app/components/site/Footer.vue +81 -0
- package/templates/blog/app/components/site/FooterStatus.vue +24 -0
- package/templates/blog/app/components/site/Header.vue +52 -0
- package/templates/blog/app/components/site/LanguageSwitch.vue +34 -0
- package/templates/blog/app/components/site/Logo.vue +17 -0
- package/templates/blog/app/components/site/NavLink.vue +19 -0
- package/templates/blog/app/components/site/NavSheet.vue +63 -0
- package/templates/blog/app/components/site/Notice.vue +21 -0
- package/templates/blog/app/components/site/PageCta.vue +14 -0
- package/templates/blog/app/components/site/SkipLink.vue +15 -0
- package/templates/blog/app/components/site/ThemeToggle.vue +28 -0
- package/templates/blog/app/components/ui/button/Button.vue +30 -0
- package/templates/blog/app/components/ui/button/index.ts +44 -0
- package/templates/blog/app/components/ui/sheet/Sheet.vue +16 -0
- package/templates/blog/app/components/ui/sheet/SheetClose.vue +13 -0
- package/templates/blog/app/components/ui/sheet/SheetContent.vue +54 -0
- package/templates/blog/app/components/ui/sheet/SheetDescription.vue +23 -0
- package/templates/blog/app/components/ui/sheet/SheetOverlay.vue +22 -0
- package/templates/blog/app/components/ui/sheet/SheetTitle.vue +23 -0
- package/templates/blog/app/components/ui/sheet/SheetTrigger.vue +13 -0
- package/templates/blog/app/components/ui/sheet/index.ts +7 -0
- package/templates/blog/app/composables/useBlog.ts +103 -0
- package/templates/blog/app/composables/usePageSeo.ts +50 -0
- package/templates/blog/app/composables/useSiteAppConfig.ts +79 -0
- package/templates/blog/app/error.vue +35 -0
- package/templates/blog/app/layouts/default.vue +23 -0
- package/templates/blog/app/lib/utils.ts +26 -0
- package/templates/blog/app/pages/about/[slug].vue +48 -0
- package/templates/blog/app/pages/index.vue +54 -0
- package/templates/blog/app/pages/legal/[slug].vue +46 -0
- package/templates/blog/app/pages/news/[slug].vue +94 -0
- package/templates/blog/app/pages/news/index.vue +54 -0
- package/templates/blog/app/pages/news/tags/[tag].vue +41 -0
- package/templates/blog/app/pages/team.vue +40 -0
- package/templates/blog/app/routes.ts +31 -0
- package/templates/blog/app/utils/telHref.ts +3 -0
- package/templates/blog/components.json +21 -0
- package/templates/blog/content/home.de.md +4 -0
- package/templates/blog/content/home.md +4 -0
- package/templates/blog/content/legal/1.privacy.de.md +30 -0
- package/templates/blog/content/legal/1.privacy.md +30 -0
- package/templates/blog/content/legal/2.terms.de.md +22 -0
- package/templates/blog/content/legal/2.terms.md +23 -0
- package/templates/blog/content/legal/3.imprint.de.md +14 -0
- package/templates/blog/content/legal/3.imprint.md +15 -0
- package/templates/blog/content/notices/1.sample.de.md +3 -0
- package/templates/blog/content/notices/1.sample.md +4 -0
- package/templates/blog/content/people/1.ida-wren.de.md +4 -0
- package/templates/blog/content/people/1.ida-wren.md +5 -0
- package/templates/blog/content/people/2.tom-marsh.de.md +4 -0
- package/templates/blog/content/people/2.tom-marsh.md +5 -0
- package/templates/blog/content/posts/counting-street-trees.de.md +24 -0
- package/templates/blog/content/posts/counting-street-trees.md +25 -0
- package/templates/blog/content/posts/forest-at-the-end-of-the-line.de.md +26 -0
- package/templates/blog/content/posts/forest-at-the-end-of-the-line.md +28 -0
- package/templates/blog/content/posts/lichen-on-the-old-bridge.de.md +11 -0
- package/templates/blog/content/posts/lichen-on-the-old-bridge.md +14 -0
- package/templates/blog/content/posts/owls-in-the-old-cemetery.de.md +22 -0
- package/templates/blog/content/posts/owls-in-the-old-cemetery.md +23 -0
- package/templates/blog/content/posts/rock-pools-at-low-tide.de.md +25 -0
- package/templates/blog/content/posts/rock-pools-at-low-tide.md +26 -0
- package/templates/blog/content/posts/rock-pools.jpg +0 -0
- package/templates/blog/content/posts/swifts-over-the-car-park.de.md +22 -0
- package/templates/blog/content/posts/swifts-over-the-car-park.md +23 -0
- package/templates/blog/content/posts/ten-minute-notebook.de.md +36 -0
- package/templates/blog/content/posts/ten-minute-notebook.md +38 -0
- package/templates/blog/content/posts/why-we-keep-field-notes.de.md +24 -0
- package/templates/blog/content/posts/why-we-keep-field-notes.md +25 -0
- package/templates/blog/content/posts/winter-birds-by-the-bike-shed.de.md +22 -0
- package/templates/blog/content/posts/winter-birds-by-the-bike-shed.md +23 -0
- package/templates/blog/content/site.md +4 -0
- package/templates/blog/eslint.config.mjs +12 -0
- package/templates/blog/eslint.tailwind.mjs +33 -0
- package/templates/blog/ginko.config.ts +59 -0
- package/templates/blog/gitignore +7 -0
- package/templates/blog/i18n/blog/de.json +18 -0
- package/templates/blog/i18n/blog/en.json +18 -0
- package/templates/blog/i18n/de.json +31 -0
- package/templates/blog/i18n/en.json +27 -0
- package/templates/blog/i18n/people/de.json +6 -0
- package/templates/blog/i18n/people/en.json +6 -0
- package/templates/blog/i18n/site/de.json +39 -0
- package/templates/blog/i18n/site/en.json +39 -0
- package/templates/blog/modules/feature-messages.ts +19 -0
- package/templates/blog/modules/feeds/index.ts +22 -0
- package/templates/blog/modules/feeds/routes.ts +13 -0
- package/templates/blog/modules/page-paths/index.ts +26 -0
- package/templates/blog/modules/page-paths/paths.ts +48 -0
- package/templates/blog/nuxt.config.ts +27 -0
- package/templates/blog/package.json +57 -0
- package/templates/blog/pnpm-workspace.yaml +6 -0
- package/templates/blog/public/media/forest-path.jpg +0 -0
- package/templates/blog/public/media/notebook.jpg +0 -0
- package/templates/blog/server/middleware/news-feed.ts +37 -0
- package/templates/blog/server/plugins/font-preload.ts +17 -0
- package/templates/blog/site-url.ts +21 -0
- package/templates/blog/tsconfig.json +9 -0
- package/templates/blog.json +11 -0
- package/templates/company/.env.example +8 -0
- package/templates/company/.github/screenshots/home-dark.png +0 -0
- package/templates/company/.github/screenshots/home-light.png +0 -0
- package/templates/company/.github/workflows/ci.yml +27 -0
- package/templates/company/DESIGN.md +197 -0
- package/templates/company/LICENSE +21 -0
- package/templates/company/MEDIA.md +32 -0
- package/templates/company/NOTES.md +19 -0
- package/templates/company/README.md +254 -0
- package/templates/company/app/app.config.ts +33 -0
- package/templates/company/app/app.vue +7 -0
- package/templates/company/app/assets/css/main.css +22 -0
- package/templates/company/app/assets/css/tokens.css +400 -0
- package/templates/company/app/bricks/logos-quotes.ts +47 -0
- package/templates/company/app/bricks/pages.ts +38 -0
- package/templates/company/app/bricks/services.ts +64 -0
- package/templates/company/app/components/InitialsAvatar.vue +18 -0
- package/templates/company/app/components/ProseBody.vue +13 -0
- package/templates/company/app/components/ServiceLine.vue +15 -0
- package/templates/company/app/components/block/Cards.vue +54 -0
- package/templates/company/app/components/block/Cta.vue +26 -0
- package/templates/company/app/components/block/Empty.vue +26 -0
- package/templates/company/app/components/block/Features.vue +24 -0
- package/templates/company/app/components/block/Hero.vue +47 -0
- package/templates/company/app/components/block/Logos.vue +22 -0
- package/templates/company/app/components/block/PageHeader.vue +21 -0
- package/templates/company/app/components/block/Quote.vue +19 -0
- package/templates/company/app/components/block/Section.vue +31 -0
- package/templates/company/app/components/blog/Byline.vue +22 -0
- package/templates/company/app/components/blog/PostList.vue +33 -0
- package/templates/company/app/components/blog/TagList.vue +17 -0
- package/templates/company/app/components/downloads/FileButton.vue +21 -0
- package/templates/company/app/components/downloads/List.vue +37 -0
- package/templates/company/app/components/event/Upcoming.vue +25 -0
- package/templates/company/app/components/jobs/List.vue +26 -0
- package/templates/company/app/components/people/List.vue +41 -0
- package/templates/company/app/components/people/TeamContact.vue +37 -0
- package/templates/company/app/components/site/Contact.vue +38 -0
- package/templates/company/app/components/site/Footer.vue +81 -0
- package/templates/company/app/components/site/Header.vue +52 -0
- package/templates/company/app/components/site/LanguageSwitch.vue +34 -0
- package/templates/company/app/components/site/Logo.vue +17 -0
- package/templates/company/app/components/site/NavLink.vue +19 -0
- package/templates/company/app/components/site/NavSheet.vue +63 -0
- package/templates/company/app/components/site/Notice.vue +21 -0
- package/templates/company/app/components/site/SkipLink.vue +15 -0
- package/templates/company/app/components/site/ThemeToggle.vue +28 -0
- package/templates/company/app/components/ui/button/Button.vue +30 -0
- package/templates/company/app/components/ui/button/index.ts +44 -0
- package/templates/company/app/components/ui/sheet/Sheet.vue +16 -0
- package/templates/company/app/components/ui/sheet/SheetClose.vue +13 -0
- package/templates/company/app/components/ui/sheet/SheetContent.vue +54 -0
- package/templates/company/app/components/ui/sheet/SheetDescription.vue +23 -0
- package/templates/company/app/components/ui/sheet/SheetOverlay.vue +22 -0
- package/templates/company/app/components/ui/sheet/SheetTitle.vue +23 -0
- package/templates/company/app/components/ui/sheet/SheetTrigger.vue +13 -0
- package/templates/company/app/components/ui/sheet/index.ts +7 -0
- package/templates/company/app/composables/useBlog.ts +103 -0
- package/templates/company/app/composables/useDownloads.ts +54 -0
- package/templates/company/app/composables/useEvents.ts +182 -0
- package/templates/company/app/composables/useJobs.ts +108 -0
- package/templates/company/app/composables/usePageSeo.ts +50 -0
- package/templates/company/app/composables/useServiceLine.ts +10 -0
- package/templates/company/app/composables/useServices.ts +93 -0
- package/templates/company/app/composables/useSiteAppConfig.ts +79 -0
- package/templates/company/app/error.vue +35 -0
- package/templates/company/app/layouts/default.vue +23 -0
- package/templates/company/app/lib/utils.ts +26 -0
- package/templates/company/app/pages/[...slug].vue +36 -0
- package/templates/company/app/pages/downloads.vue +20 -0
- package/templates/company/app/pages/events/[slug].vue +106 -0
- package/templates/company/app/pages/events/index.vue +20 -0
- package/templates/company/app/pages/index.vue +84 -0
- package/templates/company/app/pages/jobs/[slug].vue +63 -0
- package/templates/company/app/pages/jobs/index.vue +36 -0
- package/templates/company/app/pages/legal/[slug].vue +46 -0
- package/templates/company/app/pages/news/[slug].vue +94 -0
- package/templates/company/app/pages/news/index.vue +54 -0
- package/templates/company/app/pages/news/tags/[tag].vue +41 -0
- package/templates/company/app/pages/services/[slug].vue +90 -0
- package/templates/company/app/pages/services/index.vue +18 -0
- package/templates/company/app/pages/team.vue +40 -0
- package/templates/company/app/routes.ts +33 -0
- package/templates/company/app/utils/telHref.ts +3 -0
- package/templates/company/components.json +21 -0
- package/templates/company/content/downloads/hk-centrifugal-pumps.de.md +4 -0
- package/templates/company/content/downloads/hk-centrifugal-pumps.md +7 -0
- package/templates/company/content/downloads/pumping-stations.de.md +4 -0
- package/templates/company/content/downloads/pumping-stations.md +7 -0
- package/templates/company/content/downloads/ts-submersible-pumps.de.md +4 -0
- package/templates/company/content/downloads/ts-submersible-pumps.md +7 -0
- package/templates/company/content/events/1.municipal-water-forum.de.md +9 -0
- package/templates/company/content/events/1.municipal-water-forum.md +14 -0
- package/templates/company/content/events/2.pump-days-north.de.md +7 -0
- package/templates/company/content/events/2.pump-days-north.md +12 -0
- package/templates/company/content/events/3.industrial-water-expo.de.md +7 -0
- package/templates/company/content/events/3.industrial-water-expo.md +12 -0
- package/templates/company/content/home.de.md +6 -0
- package/templates/company/content/home.md +7 -0
- package/templates/company/content/jobs/apprenticeship-industrial-mechanic.de.md +22 -0
- package/templates/company/content/jobs/apprenticeship-industrial-mechanic.md +26 -0
- package/templates/company/content/jobs/sales-engineer.de.md +25 -0
- package/templates/company/content/jobs/sales-engineer.md +29 -0
- package/templates/company/content/jobs/service-technician.de.md +25 -0
- package/templates/company/content/jobs/service-technician.md +29 -0
- package/templates/company/content/jobs/summer-internship-assembly.de.md +8 -0
- package/templates/company/content/jobs/summer-internship-assembly.md +14 -0
- package/templates/company/content/legal/1.privacy.de.md +18 -0
- package/templates/company/content/legal/1.privacy.md +20 -0
- package/templates/company/content/legal/2.terms.de.md +19 -0
- package/templates/company/content/legal/2.terms.md +21 -0
- package/templates/company/content/legal/3.imprint.de.md +16 -0
- package/templates/company/content/legal/3.imprint.md +18 -0
- package/templates/company/content/logos/1.public-works.md +6 -0
- package/templates/company/content/logos/2.water-board.md +6 -0
- package/templates/company/content/logos/3.brewery.md +6 -0
- package/templates/company/content/logos/4.treatment-works.md +6 -0
- package/templates/company/content/notices/1.municipal-water-forum.de.md +3 -0
- package/templates/company/content/notices/1.municipal-water-forum.md +4 -0
- package/templates/company/content/pages/1.about.de.md +19 -0
- package/templates/company/content/pages/1.about.md +20 -0
- package/templates/company/content/people/1.katrin-albers.de.md +4 -0
- package/templates/company/content/people/1.katrin-albers.md +7 -0
- package/templates/company/content/people/2.tobias-brandt.de.md +4 -0
- package/templates/company/content/people/2.tobias-brandt.md +7 -0
- package/templates/company/content/people/3.miriam-ostendorf.de.md +4 -0
- package/templates/company/content/people/3.miriam-ostendorf.md +7 -0
- package/templates/company/content/people/4.sabine-krueger.de.md +4 -0
- package/templates/company/content/people/4.sabine-krueger.md +7 -0
- package/templates/company/content/posts/apprentices-start.de.md +12 -0
- package/templates/company/content/posts/apprentices-start.md +14 -0
- package/templates/company/content/posts/saturday-service.de.md +12 -0
- package/templates/company/content/posts/saturday-service.md +14 -0
- package/templates/company/content/posts/treatment-works-pumps.de.md +20 -0
- package/templates/company/content/posts/treatment-works-pumps.md +23 -0
- package/templates/company/content/posts/ts-pumps-atex.de.md +12 -0
- package/templates/company/content/posts/ts-pumps-atex.md +14 -0
- package/templates/company/content/quotes/1.public-works.de.md +4 -0
- package/templates/company/content/quotes/1.public-works.md +5 -0
- package/templates/company/content/quotes/2.brewery.de.md +4 -0
- package/templates/company/content/quotes/2.brewery.md +5 -0
- package/templates/company/content/serviceLine.de.md +3 -0
- package/templates/company/content/serviceLine.md +5 -0
- package/templates/company/content/services/1.hk-centrifugal-pumps.de.md +31 -0
- package/templates/company/content/services/1.hk-centrifugal-pumps.md +35 -0
- package/templates/company/content/services/2.ts-submersible-pumps.de.md +26 -0
- package/templates/company/content/services/2.ts-submersible-pumps.md +30 -0
- package/templates/company/content/services/3.pumping-stations.de.md +29 -0
- package/templates/company/content/services/3.pumping-stations.md +33 -0
- package/templates/company/content/services/4.pump-check.de.md +25 -0
- package/templates/company/content/services/4.pump-check.md +30 -0
- package/templates/company/content/services/5.repair-and-overhaul.de.md +20 -0
- package/templates/company/content/services/5.repair-and-overhaul.md +23 -0
- package/templates/company/content/site.de.md +3 -0
- package/templates/company/content/site.md +12 -0
- package/templates/company/eslint.config.mjs +12 -0
- package/templates/company/eslint.tailwind.mjs +33 -0
- package/templates/company/ginko.config.ts +98 -0
- package/templates/company/gitignore +7 -0
- package/templates/company/i18n/blog/de.json +18 -0
- package/templates/company/i18n/blog/en.json +18 -0
- package/templates/company/i18n/de.json +60 -0
- package/templates/company/i18n/downloads/de.json +6 -0
- package/templates/company/i18n/downloads/en.json +6 -0
- package/templates/company/i18n/en.json +58 -0
- package/templates/company/i18n/events/de.json +20 -0
- package/templates/company/i18n/events/en.json +20 -0
- package/templates/company/i18n/jobs/de.json +35 -0
- package/templates/company/i18n/jobs/en.json +35 -0
- package/templates/company/i18n/people/de.json +6 -0
- package/templates/company/i18n/people/en.json +6 -0
- package/templates/company/i18n/services/de.json +20 -0
- package/templates/company/i18n/services/en.json +20 -0
- package/templates/company/i18n/site/de.json +39 -0
- package/templates/company/i18n/site/en.json +39 -0
- package/templates/company/modules/feature-messages.ts +19 -0
- package/templates/company/modules/feeds/index.ts +22 -0
- package/templates/company/modules/feeds/routes.ts +13 -0
- package/templates/company/modules/page-paths/index.ts +26 -0
- package/templates/company/modules/page-paths/paths.ts +48 -0
- package/templates/company/nuxt.config.ts +29 -0
- package/templates/company/package.json +64 -0
- package/templates/company/pnpm-workspace.yaml +6 -0
- package/templates/company/public/logos/customer-four.svg +6 -0
- package/templates/company/public/logos/customer-one.svg +5 -0
- package/templates/company/public/logos/customer-three.svg +5 -0
- package/templates/company/public/logos/customer-two.svg +4 -0
- package/templates/company/public/media/pipework.jpg +0 -0
- package/templates/company/public/media/process-pumps.jpg +0 -0
- package/templates/company/public/media/pump-check.jpg +0 -0
- package/templates/company/public/media/treatment-works.jpg +0 -0
- package/templates/company/public/media/works-hall.jpg +0 -0
- package/templates/company/public/sheets/hk-centrifugal-pumps.pdf +0 -0
- package/templates/company/public/sheets/pumping-stations.pdf +0 -0
- package/templates/company/public/sheets/ts-submersible-pumps.pdf +0 -0
- package/templates/company/server/middleware/news-feed.ts +37 -0
- package/templates/company/server/plugins/font-preload.ts +17 -0
- package/templates/company/site-url.ts +21 -0
- package/templates/company/tsconfig.json +9 -0
- package/templates/company.json +18 -0
- package/templates/docs/.env.example +9 -0
- package/templates/docs/.github/screenshots/home-light.png +0 -0
- package/templates/docs/.github/screenshots/page-dark.png +0 -0
- package/templates/docs/.github/workflows/ci.yml +27 -0
- package/templates/docs/DESIGN.md +77 -0
- package/templates/docs/LICENSE +21 -0
- package/templates/docs/MEDIA.md +14 -0
- package/templates/docs/NOTES.md +18 -0
- package/templates/docs/README.md +255 -0
- package/templates/docs/app/app.config.ts +26 -0
- package/templates/docs/app/assets/css/main.css +14 -0
- package/templates/docs/content/changelog/v1-6-0.de.md +13 -0
- package/templates/docs/content/changelog/v1-6-0.md +18 -0
- package/templates/docs/content/changelog/v2-0-0.de.md +14 -0
- package/templates/docs/content/changelog/v2-0-0.md +19 -0
- package/templates/docs/content/changelog/v2-1-0.de.md +9 -0
- package/templates/docs/content/changelog/v2-1-0.md +14 -0
- package/templates/docs/content/docs/1.introduction.de.md +32 -0
- package/templates/docs/content/docs/1.introduction.md +31 -0
- package/templates/docs/content/docs/10.incidents-and-checks.de.md +82 -0
- package/templates/docs/content/docs/10.incidents-and-checks.md +81 -0
- package/templates/docs/content/docs/11.error-codes.de.md +36 -0
- package/templates/docs/content/docs/11.error-codes.md +35 -0
- package/templates/docs/content/docs/2.getting-started.de.md +57 -0
- package/templates/docs/content/docs/2.getting-started.md +56 -0
- package/templates/docs/content/docs/3.authentication.de.md +55 -0
- package/templates/docs/content/docs/3.authentication.md +54 -0
- package/templates/docs/content/docs/4.pagination.de.md +45 -0
- package/templates/docs/content/docs/4.pagination.md +44 -0
- package/templates/docs/content/docs/5.errors-and-retries.de.md +69 -0
- package/templates/docs/content/docs/5.errors-and-retries.md +66 -0
- package/templates/docs/content/docs/6.webhooks.de.md +53 -0
- package/templates/docs/content/docs/6.webhooks.md +52 -0
- package/templates/docs/content/docs/7.upgrading-to-v2.md +73 -0
- package/templates/docs/content/docs/8.client.de.md +57 -0
- package/templates/docs/content/docs/8.client.md +56 -0
- package/templates/docs/content/docs/9.monitors.de.md +96 -0
- package/templates/docs/content/docs/9.monitors.md +95 -0
- package/templates/docs/content/home.de.md +47 -0
- package/templates/docs/content/home.md +54 -0
- package/templates/docs/eslint.config.mjs +7 -0
- package/templates/docs/ginko.config.ts +36 -0
- package/templates/docs/gitignore +7 -0
- package/templates/docs/i18n/de.json +5 -0
- package/templates/docs/i18n/en.json +5 -0
- package/templates/docs/nuxt.config.ts +18 -0
- package/templates/docs/package.json +42 -0
- package/templates/docs/pnpm-workspace.yaml +6 -0
- package/templates/docs/public/favicon.svg +1 -0
- package/templates/docs/public/logo-dark.svg +1 -0
- package/templates/docs/public/logo.svg +1 -0
- package/templates/docs/site-url.ts +21 -0
- package/templates/docs/tsconfig.json +9 -0
- package/templates/docs.json +7 -0
- package/templates/events/.env.example +8 -0
- package/templates/events/.github/screenshots/home-dark.png +0 -0
- package/templates/events/.github/screenshots/home-light.png +0 -0
- package/templates/events/.github/workflows/ci.yml +27 -0
- package/templates/events/DESIGN.md +197 -0
- package/templates/events/LICENSE +21 -0
- package/templates/events/MEDIA.md +32 -0
- package/templates/events/NOTES.md +13 -0
- package/templates/events/README.md +247 -0
- package/templates/events/app/app.config.ts +30 -0
- package/templates/events/app/app.vue +7 -0
- package/templates/events/app/assets/css/main.css +22 -0
- package/templates/events/app/assets/css/tokens.css +400 -0
- package/templates/events/app/bricks/logos-quotes.ts +47 -0
- package/templates/events/app/bricks/pages.ts +38 -0
- package/templates/events/app/components/InitialsAvatar.vue +18 -0
- package/templates/events/app/components/ProseBody.vue +13 -0
- package/templates/events/app/components/block/Cards.vue +54 -0
- package/templates/events/app/components/block/Cta.vue +26 -0
- package/templates/events/app/components/block/Empty.vue +26 -0
- package/templates/events/app/components/block/Faq.vue +19 -0
- package/templates/events/app/components/block/Features.vue +24 -0
- package/templates/events/app/components/block/Gallery.vue +81 -0
- package/templates/events/app/components/block/Hero.vue +47 -0
- package/templates/events/app/components/block/Logos.vue +22 -0
- package/templates/events/app/components/block/PageHeader.vue +21 -0
- package/templates/events/app/components/block/Quote.vue +19 -0
- package/templates/events/app/components/block/Section.vue +31 -0
- package/templates/events/app/components/event/Programme.vue +16 -0
- package/templates/events/app/components/event/Upcoming.vue +25 -0
- package/templates/events/app/components/pages/Top.vue +11 -0
- package/templates/events/app/components/session/NowNext.vue +54 -0
- package/templates/events/app/components/session/Programme.vue +40 -0
- package/templates/events/app/components/session/Row.vue +61 -0
- package/templates/events/app/components/session/Speakers.vue +28 -0
- package/templates/events/app/components/site/Contact.vue +38 -0
- package/templates/events/app/components/site/Footer.vue +81 -0
- package/templates/events/app/components/site/Header.vue +52 -0
- package/templates/events/app/components/site/LanguageSwitch.vue +34 -0
- package/templates/events/app/components/site/Lightbox.vue +62 -0
- package/templates/events/app/components/site/Logo.vue +17 -0
- package/templates/events/app/components/site/NavLink.vue +19 -0
- package/templates/events/app/components/site/NavSheet.vue +63 -0
- package/templates/events/app/components/site/Notice.vue +21 -0
- package/templates/events/app/components/site/SkipLink.vue +15 -0
- package/templates/events/app/components/site/ThemeToggle.vue +28 -0
- package/templates/events/app/components/ui/accordion/Accordion.vue +16 -0
- package/templates/events/app/components/ui/accordion/AccordionContent.vue +26 -0
- package/templates/events/app/components/ui/accordion/AccordionItem.vue +24 -0
- package/templates/events/app/components/ui/accordion/AccordionTrigger.vue +35 -0
- package/templates/events/app/components/ui/accordion/index.ts +5 -0
- package/templates/events/app/components/ui/button/Button.vue +30 -0
- package/templates/events/app/components/ui/button/index.ts +44 -0
- package/templates/events/app/components/ui/sheet/Sheet.vue +16 -0
- package/templates/events/app/components/ui/sheet/SheetClose.vue +13 -0
- package/templates/events/app/components/ui/sheet/SheetContent.vue +54 -0
- package/templates/events/app/components/ui/sheet/SheetDescription.vue +23 -0
- package/templates/events/app/components/ui/sheet/SheetOverlay.vue +22 -0
- package/templates/events/app/components/ui/sheet/SheetTitle.vue +23 -0
- package/templates/events/app/components/ui/sheet/SheetTrigger.vue +13 -0
- package/templates/events/app/components/ui/sheet/index.ts +7 -0
- package/templates/events/app/composables/useEvents.ts +182 -0
- package/templates/events/app/composables/usePageSeo.ts +50 -0
- package/templates/events/app/composables/useSessions.ts +111 -0
- package/templates/events/app/composables/useSiteAppConfig.ts +79 -0
- package/templates/events/app/error.vue +35 -0
- package/templates/events/app/layouts/default.vue +23 -0
- package/templates/events/app/lib/utils.ts +26 -0
- package/templates/events/app/pages/[...slug].vue +36 -0
- package/templates/events/app/pages/events/[slug].vue +106 -0
- package/templates/events/app/pages/events/index.vue +20 -0
- package/templates/events/app/pages/faq.vue +39 -0
- package/templates/events/app/pages/index.vue +134 -0
- package/templates/events/app/pages/legal/[slug].vue +46 -0
- package/templates/events/app/pages/programme.vue +42 -0
- package/templates/events/app/pages/speakers/[slug].vue +62 -0
- package/templates/events/app/pages/speakers/index.vue +31 -0
- package/templates/events/app/routes.ts +31 -0
- package/templates/events/app/utils/sessions.ts +64 -0
- package/templates/events/app/utils/telHref.ts +3 -0
- package/templates/events/components.json +21 -0
- package/templates/events/content/events/1.open-data-days.de.md +9 -0
- package/templates/events/content/events/1.open-data-days.md +19 -0
- package/templates/events/content/events/2.open-data-meetup.de.md +7 -0
- package/templates/events/content/events/2.open-data-meetup.md +14 -0
- package/templates/events/content/events/3.last-edition.de.md +5 -0
- package/templates/events/content/events/3.last-edition.md +12 -0
- package/templates/events/content/events/4.next-edition.de.md +5 -0
- package/templates/events/content/events/4.next-edition.md +13 -0
- package/templates/events/content/faq/1.getting-there.de.md +4 -0
- package/templates/events/content/faq/1.getting-there.md +4 -0
- package/templates/events/content/faq/2.accessibility.de.md +4 -0
- package/templates/events/content/faq/2.accessibility.md +4 -0
- package/templates/events/content/faq/3.tickets.de.md +4 -0
- package/templates/events/content/faq/3.tickets.md +4 -0
- package/templates/events/content/faq/4.food.de.md +4 -0
- package/templates/events/content/faq/4.food.md +4 -0
- package/templates/events/content/faq/5.code-of-conduct.de.md +4 -0
- package/templates/events/content/faq/5.code-of-conduct.md +4 -0
- package/templates/events/content/faq/6.language.de.md +4 -0
- package/templates/events/content/faq/6.language.md +4 -0
- package/templates/events/content/faq/7.recordings.de.md +4 -0
- package/templates/events/content/faq/7.recordings.md +4 -0
- package/templates/events/content/faq/8.ticket-transfer.de.md +4 -0
- package/templates/events/content/faq/8.ticket-transfer.md +4 -0
- package/templates/events/content/gallery.de.md +9 -0
- package/templates/events/content/gallery.md +12 -0
- package/templates/events/content/home.de.md +6 -0
- package/templates/events/content/home.md +7 -0
- package/templates/events/content/legal/1.privacy.de.md +19 -0
- package/templates/events/content/legal/1.privacy.md +20 -0
- package/templates/events/content/legal/2.terms.de.md +19 -0
- package/templates/events/content/legal/2.terms.md +20 -0
- package/templates/events/content/legal/3.imprint.de.md +19 -0
- package/templates/events/content/legal/3.imprint.md +20 -0
- package/templates/events/content/logos/1.kaltenegger-it.md +6 -0
- package/templates/events/content/logos/2.nordlicht-hosting.md +6 -0
- package/templates/events/content/logos/3.hallgarten-stiftung.md +6 -0
- package/templates/events/content/logos/4.kanalcafe.md +6 -0
- package/templates/events/content/notices/1.ticket-sales.de.md +3 -0
- package/templates/events/content/notices/1.ticket-sales.md +4 -0
- package/templates/events/content/pages/1.venue.de.md +36 -0
- package/templates/events/content/pages/1.venue.md +37 -0
- package/templates/events/content/pages/2.code-of-conduct.de.md +25 -0
- package/templates/events/content/pages/2.code-of-conduct.md +25 -0
- package/templates/events/content/pages/3.sponsoring.de.md +17 -0
- package/templates/events/content/pages/3.sponsoring.md +17 -0
- package/templates/events/content/people/1.lena-hofer.de.md +4 -0
- package/templates/events/content/people/1.lena-hofer.md +6 -0
- package/templates/events/content/people/2.tobias-wagner.de.md +4 -0
- package/templates/events/content/people/2.tobias-wagner.md +6 -0
- package/templates/events/content/people/3.amira-haddad.de.md +4 -0
- package/templates/events/content/people/3.amira-haddad.md +6 -0
- package/templates/events/content/people/4.jonas-leitner.de.md +4 -0
- package/templates/events/content/people/4.jonas-leitner.md +6 -0
- package/templates/events/content/people/5.sophie-brunner.de.md +4 -0
- package/templates/events/content/people/5.sophie-brunner.md +6 -0
- package/templates/events/content/people/6.david-okafor.de.md +4 -0
- package/templates/events/content/people/6.david-okafor.md +6 -0
- package/templates/events/content/people/7.katrin-moser.de.md +4 -0
- package/templates/events/content/people/7.katrin-moser.md +6 -0
- package/templates/events/content/people/8.nina-pichler.de.md +4 -0
- package/templates/events/content/people/8.nina-pichler.md +6 -0
- package/templates/events/content/people/9.felix-gruber.de.md +3 -0
- package/templates/events/content/people/9.felix-gruber.md +5 -0
- package/templates/events/content/sessions/balcony-sensors.de.md +4 -0
- package/templates/events/content/sessions/balcony-sensors.md +10 -0
- package/templates/events/content/sessions/budget-stories.de.md +4 -0
- package/templates/events/content/sessions/budget-stories.md +11 -0
- package/templates/events/content/sessions/closing.de.md +4 -0
- package/templates/events/content/sessions/closing.md +11 -0
- package/templates/events/content/sessions/doors-open.de.md +3 -0
- package/templates/events/content/sessions/doors-open.md +9 -0
- package/templates/events/content/sessions/honest-charts.de.md +4 -0
- package/templates/events/content/sessions/honest-charts.md +11 -0
- package/templates/events/content/sessions/keynote-city.de.md +4 -0
- package/templates/events/content/sessions/keynote-city.md +11 -0
- package/templates/events/content/sessions/lightning-talks.de.md +4 -0
- package/templates/events/content/sessions/lightning-talks.md +10 -0
- package/templates/events/content/sessions/lunch-1.de.md +3 -0
- package/templates/events/content/sessions/lunch-1.md +9 -0
- package/templates/events/content/sessions/lunch-2.de.md +3 -0
- package/templates/events/content/sessions/lunch-2.md +9 -0
- package/templates/events/content/sessions/next-edition-keynote.de.md +3 -0
- package/templates/events/content/sessions/next-edition-keynote.md +9 -0
- package/templates/events/content/sessions/open-data-schools.de.md +4 -0
- package/templates/events/content/sessions/open-data-schools.md +11 -0
- package/templates/events/content/sessions/open-statistics.de.md +4 -0
- package/templates/events/content/sessions/open-statistics.md +11 -0
- package/templates/events/content/sessions/panel-who-pays.de.md +4 -0
- package/templates/events/content/sessions/panel-who-pays.md +11 -0
- package/templates/events/content/sessions/privacy-line.de.md +4 -0
- package/templates/events/content/sessions/privacy-line.md +11 -0
- package/templates/events/content/sessions/readable-metadata.de.md +4 -0
- package/templates/events/content/sessions/readable-metadata.md +11 -0
- package/templates/events/content/sessions/transport-data.de.md +4 -0
- package/templates/events/content/sessions/transport-data.md +11 -0
- package/templates/events/content/sessions/welcome.de.md +3 -0
- package/templates/events/content/sessions/welcome.md +10 -0
- package/templates/events/content/sessions/workshop-charts.de.md +4 -0
- package/templates/events/content/sessions/workshop-charts.md +11 -0
- package/templates/events/content/sessions/workshop-clean-data.de.md +4 -0
- package/templates/events/content/sessions/workshop-clean-data.md +11 -0
- package/templates/events/content/sessions/workshop-portal.de.md +4 -0
- package/templates/events/content/sessions/workshop-portal.md +11 -0
- package/templates/events/content/site.md +10 -0
- package/templates/events/eslint.config.mjs +12 -0
- package/templates/events/eslint.tailwind.mjs +33 -0
- package/templates/events/ginko.config.ts +75 -0
- package/templates/events/gitignore +7 -0
- package/templates/events/i18n/de.json +37 -0
- package/templates/events/i18n/en.json +37 -0
- package/templates/events/i18n/events/de.json +20 -0
- package/templates/events/i18n/events/en.json +20 -0
- package/templates/events/i18n/faq/de.json +6 -0
- package/templates/events/i18n/faq/en.json +6 -0
- package/templates/events/i18n/gallery/de.json +8 -0
- package/templates/events/i18n/gallery/en.json +8 -0
- package/templates/events/i18n/sessions/de.json +33 -0
- package/templates/events/i18n/sessions/en.json +33 -0
- package/templates/events/i18n/site/de.json +39 -0
- package/templates/events/i18n/site/en.json +39 -0
- package/templates/events/modules/feature-messages.ts +19 -0
- package/templates/events/modules/feeds/index.ts +22 -0
- package/templates/events/modules/feeds/routes.ts +13 -0
- package/templates/events/modules/page-paths/index.ts +26 -0
- package/templates/events/modules/page-paths/paths.ts +48 -0
- package/templates/events/nuxt.config.ts +27 -0
- package/templates/events/package.json +61 -0
- package/templates/events/pnpm-workspace.yaml +6 -0
- package/templates/events/public/logos/hallgarten-stiftung.svg +4 -0
- package/templates/events/public/logos/kaltenegger-it.svg +4 -0
- package/templates/events/public/logos/kanalcafe.svg +4 -0
- package/templates/events/public/logos/nordlicht-hosting.svg +4 -0
- package/templates/events/public/media/coffee-break.jpg +0 -0
- package/templates/events/public/media/hero.jpg +0 -0
- package/templates/events/public/media/talk.jpg +0 -0
- package/templates/events/public/media/venue.jpg +0 -0
- package/templates/events/public/media/workshop-tables.jpg +0 -0
- package/templates/events/server/plugins/font-preload.ts +17 -0
- package/templates/events/site-url.ts +21 -0
- package/templates/events/tsconfig.json +9 -0
- package/templates/events.json +18 -0
- package/templates/local-business/.env.example +8 -0
- package/templates/local-business/.github/screenshots/home-dark.png +0 -0
- package/templates/local-business/.github/screenshots/home-light.png +0 -0
- package/templates/local-business/.github/workflows/ci.yml +27 -0
- package/templates/local-business/DESIGN.md +197 -0
- package/templates/local-business/LICENSE +21 -0
- package/templates/local-business/MEDIA.md +27 -0
- package/templates/local-business/NOTES.md +31 -0
- package/templates/local-business/README.md +256 -0
- package/templates/local-business/app/app.config.ts +32 -0
- package/templates/local-business/app/app.vue +7 -0
- package/templates/local-business/app/assets/css/main.css +18 -0
- package/templates/local-business/app/assets/css/tokens.css +400 -0
- package/templates/local-business/app/bricks/pages.ts +38 -0
- package/templates/local-business/app/bricks/services.ts +64 -0
- package/templates/local-business/app/components/InitialsAvatar.vue +18 -0
- package/templates/local-business/app/components/ProseBody.vue +13 -0
- package/templates/local-business/app/components/block/Cards.vue +54 -0
- package/templates/local-business/app/components/block/Cta.vue +26 -0
- package/templates/local-business/app/components/block/Empty.vue +26 -0
- package/templates/local-business/app/components/block/Faq.vue +19 -0
- package/templates/local-business/app/components/block/Features.vue +24 -0
- package/templates/local-business/app/components/block/Gallery.vue +81 -0
- package/templates/local-business/app/components/block/Hero.vue +47 -0
- package/templates/local-business/app/components/block/PageHeader.vue +21 -0
- package/templates/local-business/app/components/block/Section.vue +31 -0
- package/templates/local-business/app/components/hours/Table.vue +119 -0
- package/templates/local-business/app/components/hours/Today.vue +55 -0
- package/templates/local-business/app/components/people/List.vue +41 -0
- package/templates/local-business/app/components/services/Actions.vue +18 -0
- package/templates/local-business/app/components/site/Contact.vue +38 -0
- package/templates/local-business/app/components/site/Footer.vue +81 -0
- package/templates/local-business/app/components/site/FooterStatus.vue +9 -0
- package/templates/local-business/app/components/site/Header.vue +52 -0
- package/templates/local-business/app/components/site/LanguageSwitch.vue +34 -0
- package/templates/local-business/app/components/site/Lightbox.vue +62 -0
- package/templates/local-business/app/components/site/Logo.vue +17 -0
- package/templates/local-business/app/components/site/NavLink.vue +19 -0
- package/templates/local-business/app/components/site/NavSheet.vue +63 -0
- package/templates/local-business/app/components/site/Notice.vue +21 -0
- package/templates/local-business/app/components/site/SkipLink.vue +15 -0
- package/templates/local-business/app/components/site/ThemeToggle.vue +28 -0
- package/templates/local-business/app/components/ui/accordion/Accordion.vue +16 -0
- package/templates/local-business/app/components/ui/accordion/AccordionContent.vue +26 -0
- package/templates/local-business/app/components/ui/accordion/AccordionItem.vue +24 -0
- package/templates/local-business/app/components/ui/accordion/AccordionTrigger.vue +35 -0
- package/templates/local-business/app/components/ui/accordion/index.ts +5 -0
- package/templates/local-business/app/components/ui/button/Button.vue +30 -0
- package/templates/local-business/app/components/ui/button/index.ts +44 -0
- package/templates/local-business/app/components/ui/sheet/Sheet.vue +16 -0
- package/templates/local-business/app/components/ui/sheet/SheetClose.vue +13 -0
- package/templates/local-business/app/components/ui/sheet/SheetContent.vue +54 -0
- package/templates/local-business/app/components/ui/sheet/SheetDescription.vue +23 -0
- package/templates/local-business/app/components/ui/sheet/SheetOverlay.vue +22 -0
- package/templates/local-business/app/components/ui/sheet/SheetTitle.vue +23 -0
- package/templates/local-business/app/components/ui/sheet/SheetTrigger.vue +13 -0
- package/templates/local-business/app/components/ui/sheet/index.ts +7 -0
- package/templates/local-business/app/components/visit/Book.vue +46 -0
- package/templates/local-business/app/composables/useHours.ts +81 -0
- package/templates/local-business/app/composables/usePageSeo.ts +50 -0
- package/templates/local-business/app/composables/useServices.ts +93 -0
- package/templates/local-business/app/composables/useSiteAppConfig.ts +79 -0
- package/templates/local-business/app/composables/useVisit.ts +19 -0
- package/templates/local-business/app/error.vue +35 -0
- package/templates/local-business/app/layouts/default.vue +23 -0
- package/templates/local-business/app/lib/utils.ts +26 -0
- package/templates/local-business/app/pages/[...slug].vue +36 -0
- package/templates/local-business/app/pages/contact.vue +62 -0
- package/templates/local-business/app/pages/faq.vue +39 -0
- package/templates/local-business/app/pages/index.vue +114 -0
- package/templates/local-business/app/pages/legal/[slug].vue +46 -0
- package/templates/local-business/app/pages/services/[slug].vue +90 -0
- package/templates/local-business/app/pages/services/index.vue +18 -0
- package/templates/local-business/app/pages/team.vue +40 -0
- package/templates/local-business/app/routes.ts +31 -0
- package/templates/local-business/app/utils/hours.ts +58 -0
- package/templates/local-business/app/utils/telHref.ts +3 -0
- package/templates/local-business/components.json +21 -0
- package/templates/local-business/content/faq/1.prescription.de.md +4 -0
- package/templates/local-business/content/faq/1.prescription.md +4 -0
- package/templates/local-business/content/faq/2.insurance.de.md +4 -0
- package/templates/local-business/content/faq/2.insurance.md +4 -0
- package/templates/local-business/content/faq/3.bring.de.md +4 -0
- package/templates/local-business/content/faq/3.bring.md +4 -0
- package/templates/local-business/content/faq/4.cancel.de.md +4 -0
- package/templates/local-business/content/faq/4.cancel.md +4 -0
- package/templates/local-business/content/faq/5.sessions.de.md +4 -0
- package/templates/local-business/content/faq/5.sessions.md +4 -0
- package/templates/local-business/content/faq/6.payment.de.md +4 -0
- package/templates/local-business/content/faq/6.payment.md +4 -0
- package/templates/local-business/content/gallery.de.md +7 -0
- package/templates/local-business/content/gallery.md +9 -0
- package/templates/local-business/content/home.de.md +5 -0
- package/templates/local-business/content/home.md +7 -0
- package/templates/local-business/content/hourPlans/1.summer-hours.de.md +3 -0
- package/templates/local-business/content/hourPlans/1.summer-hours.md +31 -0
- package/templates/local-business/content/hours.de.md +5 -0
- package/templates/local-business/content/hours.md +40 -0
- package/templates/local-business/content/legal/1.privacy.de.md +39 -0
- package/templates/local-business/content/legal/1.privacy.md +38 -0
- package/templates/local-business/content/legal/2.terms.de.md +22 -0
- package/templates/local-business/content/legal/2.terms.md +22 -0
- package/templates/local-business/content/legal/3.imprint.de.md +17 -0
- package/templates/local-business/content/legal/3.imprint.md +17 -0
- package/templates/local-business/content/notices/1.courtyard-works.de.md +3 -0
- package/templates/local-business/content/notices/1.courtyard-works.md +4 -0
- package/templates/local-business/content/pages/1.about.de.md +23 -0
- package/templates/local-business/content/pages/1.about.md +24 -0
- package/templates/local-business/content/people/1.anna-hofer.de.md +4 -0
- package/templates/local-business/content/people/1.anna-hofer.md +5 -0
- package/templates/local-business/content/people/2.lukas-brandstaetter.de.md +4 -0
- package/templates/local-business/content/people/2.lukas-brandstaetter.md +5 -0
- package/templates/local-business/content/people/3.mira-kovac.de.md +4 -0
- package/templates/local-business/content/people/3.mira-kovac.md +5 -0
- package/templates/local-business/content/people/4.elisabeth-gruber.de.md +4 -0
- package/templates/local-business/content/people/4.elisabeth-gruber.md +5 -0
- package/templates/local-business/content/services/1.physiotherapy.de.md +22 -0
- package/templates/local-business/content/services/1.physiotherapy.md +25 -0
- package/templates/local-business/content/services/2.manual-therapy.de.md +11 -0
- package/templates/local-business/content/services/2.manual-therapy.md +15 -0
- package/templates/local-business/content/services/3.sports-physiotherapy.de.md +18 -0
- package/templates/local-business/content/services/3.sports-physiotherapy.md +22 -0
- package/templates/local-business/content/services/4.lymphatic-drainage.de.md +18 -0
- package/templates/local-business/content/services/4.lymphatic-drainage.md +22 -0
- package/templates/local-business/content/services/5.massage.de.md +11 -0
- package/templates/local-business/content/services/5.massage.md +14 -0
- package/templates/local-business/content/services/6.home-visits.de.md +11 -0
- package/templates/local-business/content/services/6.home-visits.md +12 -0
- package/templates/local-business/content/site.de.md +3 -0
- package/templates/local-business/content/site.md +11 -0
- package/templates/local-business/content/visit.de.md +6 -0
- package/templates/local-business/content/visit.md +7 -0
- package/templates/local-business/eslint.config.mjs +12 -0
- package/templates/local-business/eslint.tailwind.mjs +33 -0
- package/templates/local-business/ginko.config.ts +97 -0
- package/templates/local-business/gitignore +7 -0
- package/templates/local-business/i18n/de.json +49 -0
- package/templates/local-business/i18n/en.json +49 -0
- package/templates/local-business/i18n/faq/de.json +6 -0
- package/templates/local-business/i18n/faq/en.json +6 -0
- package/templates/local-business/i18n/gallery/de.json +8 -0
- package/templates/local-business/i18n/gallery/en.json +8 -0
- package/templates/local-business/i18n/hours/de.json +27 -0
- package/templates/local-business/i18n/hours/en.json +27 -0
- package/templates/local-business/i18n/people/de.json +6 -0
- package/templates/local-business/i18n/people/en.json +6 -0
- package/templates/local-business/i18n/services/de.json +20 -0
- package/templates/local-business/i18n/services/en.json +20 -0
- package/templates/local-business/i18n/site/de.json +39 -0
- package/templates/local-business/i18n/site/en.json +39 -0
- package/templates/local-business/modules/feature-messages.ts +19 -0
- package/templates/local-business/modules/feeds/index.ts +22 -0
- package/templates/local-business/modules/feeds/routes.ts +13 -0
- package/templates/local-business/modules/page-paths/index.ts +26 -0
- package/templates/local-business/modules/page-paths/paths.ts +48 -0
- package/templates/local-business/nuxt.config.ts +29 -0
- package/templates/local-business/package.json +62 -0
- package/templates/local-business/pnpm-workspace.yaml +6 -0
- package/templates/local-business/public/media/massage.jpg +0 -0
- package/templates/local-business/public/media/treatment-room.jpg +0 -0
- package/templates/local-business/server/plugins/font-preload.ts +17 -0
- package/templates/local-business/site-url.ts +21 -0
- package/templates/local-business/tsconfig.json +9 -0
- package/templates/local-business.json +11 -0
- package/templates/nonprofit/.env.example +8 -0
- package/templates/nonprofit/.github/screenshots/home-dark.png +0 -0
- package/templates/nonprofit/.github/screenshots/home-light.png +0 -0
- package/templates/nonprofit/.github/workflows/ci.yml +27 -0
- package/templates/nonprofit/DESIGN.md +197 -0
- package/templates/nonprofit/LICENSE +21 -0
- package/templates/nonprofit/MEDIA.md +34 -0
- package/templates/nonprofit/NOTES.md +18 -0
- package/templates/nonprofit/README.md +227 -0
- package/templates/nonprofit/app/app.config.ts +34 -0
- package/templates/nonprofit/app/app.vue +7 -0
- package/templates/nonprofit/app/assets/css/main.css +35 -0
- package/templates/nonprofit/app/assets/css/tokens.css +400 -0
- package/templates/nonprofit/app/bricks/logos-quotes.ts +47 -0
- package/templates/nonprofit/app/bricks/pages.ts +38 -0
- package/templates/nonprofit/app/bricks/projects.ts +114 -0
- package/templates/nonprofit/app/components/InitialsAvatar.vue +18 -0
- package/templates/nonprofit/app/components/ProseBody.vue +13 -0
- package/templates/nonprofit/app/components/block/Cards.vue +54 -0
- package/templates/nonprofit/app/components/block/Cta.vue +26 -0
- package/templates/nonprofit/app/components/block/Empty.vue +26 -0
- package/templates/nonprofit/app/components/block/Features.vue +24 -0
- package/templates/nonprofit/app/components/block/Hero.vue +47 -0
- package/templates/nonprofit/app/components/block/Logos.vue +22 -0
- package/templates/nonprofit/app/components/block/PageHeader.vue +21 -0
- package/templates/nonprofit/app/components/block/Quote.vue +19 -0
- package/templates/nonprofit/app/components/block/Section.vue +31 -0
- package/templates/nonprofit/app/components/blog/Byline.vue +22 -0
- package/templates/nonprofit/app/components/blog/PostList.vue +33 -0
- package/templates/nonprofit/app/components/blog/TagList.vue +17 -0
- package/templates/nonprofit/app/components/downloads/FileButton.vue +21 -0
- package/templates/nonprofit/app/components/downloads/List.vue +37 -0
- package/templates/nonprofit/app/components/event/Next.vue +24 -0
- package/templates/nonprofit/app/components/event/Upcoming.vue +25 -0
- package/templates/nonprofit/app/components/pages/Top.vue +19 -0
- package/templates/nonprofit/app/components/people/List.vue +41 -0
- package/templates/nonprofit/app/components/people/TeamContact.vue +7 -0
- package/templates/nonprofit/app/components/site/Contact.vue +38 -0
- package/templates/nonprofit/app/components/site/Footer.vue +81 -0
- package/templates/nonprofit/app/components/site/Header.vue +52 -0
- package/templates/nonprofit/app/components/site/LanguageSwitch.vue +34 -0
- package/templates/nonprofit/app/components/site/Logo.vue +17 -0
- package/templates/nonprofit/app/components/site/NavLink.vue +19 -0
- package/templates/nonprofit/app/components/site/NavSheet.vue +63 -0
- package/templates/nonprofit/app/components/site/Notice.vue +21 -0
- package/templates/nonprofit/app/components/site/SkipLink.vue +15 -0
- package/templates/nonprofit/app/components/site/ThemeToggle.vue +28 -0
- package/templates/nonprofit/app/components/ui/button/Button.vue +30 -0
- package/templates/nonprofit/app/components/ui/button/index.ts +44 -0
- package/templates/nonprofit/app/components/ui/sheet/Sheet.vue +16 -0
- package/templates/nonprofit/app/components/ui/sheet/SheetClose.vue +13 -0
- package/templates/nonprofit/app/components/ui/sheet/SheetContent.vue +54 -0
- package/templates/nonprofit/app/components/ui/sheet/SheetDescription.vue +23 -0
- package/templates/nonprofit/app/components/ui/sheet/SheetOverlay.vue +22 -0
- package/templates/nonprofit/app/components/ui/sheet/SheetTitle.vue +23 -0
- package/templates/nonprofit/app/components/ui/sheet/SheetTrigger.vue +13 -0
- package/templates/nonprofit/app/components/ui/sheet/index.ts +7 -0
- package/templates/nonprofit/app/composables/useBlog.ts +103 -0
- package/templates/nonprofit/app/composables/useDownloads.ts +54 -0
- package/templates/nonprofit/app/composables/useEvents.ts +182 -0
- package/templates/nonprofit/app/composables/usePageSeo.ts +50 -0
- package/templates/nonprofit/app/composables/useProjects.ts +31 -0
- package/templates/nonprofit/app/composables/useSiteAppConfig.ts +79 -0
- package/templates/nonprofit/app/error.vue +35 -0
- package/templates/nonprofit/app/layouts/default.vue +23 -0
- package/templates/nonprofit/app/lib/utils.ts +26 -0
- package/templates/nonprofit/app/pages/[...slug].vue +36 -0
- package/templates/nonprofit/app/pages/downloads.vue +20 -0
- package/templates/nonprofit/app/pages/events/[slug].vue +106 -0
- package/templates/nonprofit/app/pages/events/index.vue +20 -0
- package/templates/nonprofit/app/pages/index.vue +64 -0
- package/templates/nonprofit/app/pages/legal/[slug].vue +46 -0
- package/templates/nonprofit/app/pages/news/[slug].vue +94 -0
- package/templates/nonprofit/app/pages/news/index.vue +54 -0
- package/templates/nonprofit/app/pages/news/tags/[tag].vue +41 -0
- package/templates/nonprofit/app/pages/projects/[slug].vue +49 -0
- package/templates/nonprofit/app/pages/projects/index.vue +24 -0
- package/templates/nonprofit/app/pages/team.vue +40 -0
- package/templates/nonprofit/app/routes.ts +32 -0
- package/templates/nonprofit/app/utils/telHref.ts +3 -0
- package/templates/nonprofit/components.json +21 -0
- package/templates/nonprofit/content/downloads/annual-report.ar.md +4 -0
- package/templates/nonprofit/content/downloads/annual-report.de.md +4 -0
- package/templates/nonprofit/content/downloads/annual-report.fr.md +4 -0
- package/templates/nonprofit/content/downloads/annual-report.md +7 -0
- package/templates/nonprofit/content/events/1.winter-clean-up.ar.md +9 -0
- package/templates/nonprofit/content/events/1.winter-clean-up.de.md +9 -0
- package/templates/nonprofit/content/events/1.winter-clean-up.fr.md +9 -0
- package/templates/nonprofit/content/events/1.winter-clean-up.md +14 -0
- package/templates/nonprofit/content/events/2.members-meeting.ar.md +9 -0
- package/templates/nonprofit/content/events/2.members-meeting.de.md +9 -0
- package/templates/nonprofit/content/events/2.members-meeting.fr.md +9 -0
- package/templates/nonprofit/content/events/2.members-meeting.md +15 -0
- package/templates/nonprofit/content/events/3.spring-clean-up.ar.md +9 -0
- package/templates/nonprofit/content/events/3.spring-clean-up.de.md +9 -0
- package/templates/nonprofit/content/events/3.spring-clean-up.fr.md +9 -0
- package/templates/nonprofit/content/events/3.spring-clean-up.md +14 -0
- package/templates/nonprofit/content/home.ar.md +6 -0
- package/templates/nonprofit/content/home.de.md +6 -0
- package/templates/nonprofit/content/home.fr.md +6 -0
- package/templates/nonprofit/content/home.md +7 -0
- package/templates/nonprofit/content/legal/1.privacy.ar.md +18 -0
- package/templates/nonprofit/content/legal/1.privacy.de.md +18 -0
- package/templates/nonprofit/content/legal/1.privacy.fr.md +18 -0
- package/templates/nonprofit/content/legal/1.privacy.md +20 -0
- package/templates/nonprofit/content/legal/2.terms.ar.md +17 -0
- package/templates/nonprofit/content/legal/2.terms.de.md +17 -0
- package/templates/nonprofit/content/legal/2.terms.fr.md +17 -0
- package/templates/nonprofit/content/legal/2.terms.md +19 -0
- package/templates/nonprofit/content/legal/3.imprint.ar.md +16 -0
- package/templates/nonprofit/content/legal/3.imprint.de.md +16 -0
- package/templates/nonprofit/content/legal/3.imprint.fr.md +16 -0
- package/templates/nonprofit/content/legal/3.imprint.md +18 -0
- package/templates/nonprofit/content/logos/1.partner-one.md +6 -0
- package/templates/nonprofit/content/logos/2.partner-two.md +6 -0
- package/templates/nonprofit/content/logos/3.partner-three.md +6 -0
- package/templates/nonprofit/content/notices/1.annual-report-online.ar.md +3 -0
- package/templates/nonprofit/content/notices/1.annual-report-online.de.md +3 -0
- package/templates/nonprofit/content/notices/1.annual-report-online.fr.md +3 -0
- package/templates/nonprofit/content/notices/1.annual-report-online.md +4 -0
- package/templates/nonprofit/content/pages/1.about.ar.md +21 -0
- package/templates/nonprofit/content/pages/1.about.de.md +21 -0
- package/templates/nonprofit/content/pages/1.about.fr.md +21 -0
- package/templates/nonprofit/content/pages/1.about.md +21 -0
- package/templates/nonprofit/content/pages/2.get-involved.ar.md +19 -0
- package/templates/nonprofit/content/pages/2.get-involved.de.md +19 -0
- package/templates/nonprofit/content/pages/2.get-involved.fr.md +19 -0
- package/templates/nonprofit/content/pages/2.get-involved.md +20 -0
- package/templates/nonprofit/content/pages/3.donate.ar.md +26 -0
- package/templates/nonprofit/content/pages/3.donate.de.md +26 -0
- package/templates/nonprofit/content/pages/3.donate.fr.md +26 -0
- package/templates/nonprofit/content/pages/3.donate.md +27 -0
- package/templates/nonprofit/content/people/1.jana-becker.ar.md +4 -0
- package/templates/nonprofit/content/people/1.jana-becker.de.md +4 -0
- package/templates/nonprofit/content/people/1.jana-becker.fr.md +4 -0
- package/templates/nonprofit/content/people/1.jana-becker.md +5 -0
- package/templates/nonprofit/content/people/2.yusuf-demir.ar.md +4 -0
- package/templates/nonprofit/content/people/2.yusuf-demir.de.md +4 -0
- package/templates/nonprofit/content/people/2.yusuf-demir.fr.md +4 -0
- package/templates/nonprofit/content/people/2.yusuf-demir.md +5 -0
- package/templates/nonprofit/content/people/3.claire-martin.ar.md +4 -0
- package/templates/nonprofit/content/people/3.claire-martin.de.md +4 -0
- package/templates/nonprofit/content/people/3.claire-martin.fr.md +4 -0
- package/templates/nonprofit/content/people/3.claire-martin.md +5 -0
- package/templates/nonprofit/content/people/4.lukas-hoffmann.ar.md +4 -0
- package/templates/nonprofit/content/people/4.lukas-hoffmann.de.md +4 -0
- package/templates/nonprofit/content/people/4.lukas-hoffmann.fr.md +4 -0
- package/templates/nonprofit/content/people/4.lukas-hoffmann.md +6 -0
- package/templates/nonprofit/content/posts/a-home-for-our-tools.ar.md +10 -0
- package/templates/nonprofit/content/posts/a-home-for-our-tools.de.md +10 -0
- package/templates/nonprofit/content/posts/a-home-for-our-tools.fr.md +10 -0
- package/templates/nonprofit/content/posts/a-home-for-our-tools.md +12 -0
- package/templates/nonprofit/content/posts/autumn-clean-up.ar.md +20 -0
- package/templates/nonprofit/content/posts/autumn-clean-up.de.md +20 -0
- package/templates/nonprofit/content/posts/autumn-clean-up.fr.md +20 -0
- package/templates/nonprofit/content/posts/autumn-clean-up.md +23 -0
- package/templates/nonprofit/content/posts/hedge-planting-plan.md +12 -0
- package/templates/nonprofit/content/posts/water-tests-with-schools.ar.md +16 -0
- package/templates/nonprofit/content/posts/water-tests-with-schools.de.md +16 -0
- package/templates/nonprofit/content/posts/water-tests-with-schools.fr.md +16 -0
- package/templates/nonprofit/content/posts/water-tests-with-schools.md +18 -0
- package/templates/nonprofit/content/posts/winter-clean-up.ar.md +14 -0
- package/templates/nonprofit/content/posts/winter-clean-up.de.md +14 -0
- package/templates/nonprofit/content/posts/winter-clean-up.fr.md +14 -0
- package/templates/nonprofit/content/posts/winter-clean-up.md +16 -0
- package/templates/nonprofit/content/projects/1.clean-banks.ar.md +9 -0
- package/templates/nonprofit/content/projects/1.clean-banks.de.md +9 -0
- package/templates/nonprofit/content/projects/1.clean-banks.fr.md +9 -0
- package/templates/nonprofit/content/projects/1.clean-banks.md +10 -0
- package/templates/nonprofit/content/projects/2.water-tests.ar.md +9 -0
- package/templates/nonprofit/content/projects/2.water-tests.de.md +9 -0
- package/templates/nonprofit/content/projects/2.water-tests.fr.md +9 -0
- package/templates/nonprofit/content/projects/2.water-tests.md +10 -0
- package/templates/nonprofit/content/projects/3.hedge-campaign.ar.md +10 -0
- package/templates/nonprofit/content/projects/3.hedge-campaign.de.md +10 -0
- package/templates/nonprofit/content/projects/3.hedge-campaign.fr.md +10 -0
- package/templates/nonprofit/content/projects/3.hedge-campaign.md +13 -0
- package/templates/nonprofit/content/projects/4.gloves-appeal.md +9 -0
- package/templates/nonprofit/content/quotes/1.volunteer.ar.md +4 -0
- package/templates/nonprofit/content/quotes/1.volunteer.de.md +4 -0
- package/templates/nonprofit/content/quotes/1.volunteer.fr.md +4 -0
- package/templates/nonprofit/content/quotes/1.volunteer.md +5 -0
- package/templates/nonprofit/content/quotes/2.teacher.ar.md +4 -0
- package/templates/nonprofit/content/quotes/2.teacher.de.md +4 -0
- package/templates/nonprofit/content/quotes/2.teacher.fr.md +4 -0
- package/templates/nonprofit/content/quotes/2.teacher.md +5 -0
- package/templates/nonprofit/content/site.ar.md +3 -0
- package/templates/nonprofit/content/site.de.md +3 -0
- package/templates/nonprofit/content/site.fr.md +3 -0
- package/templates/nonprofit/content/site.md +11 -0
- package/templates/nonprofit/eslint.config.mjs +12 -0
- package/templates/nonprofit/eslint.tailwind.mjs +33 -0
- package/templates/nonprofit/ginko.config.ts +77 -0
- package/templates/nonprofit/gitignore +7 -0
- package/templates/nonprofit/i18n/ar.json +37 -0
- package/templates/nonprofit/i18n/blog/ar.json +18 -0
- package/templates/nonprofit/i18n/blog/de.json +18 -0
- package/templates/nonprofit/i18n/blog/en.json +18 -0
- package/templates/nonprofit/i18n/blog/fr.json +18 -0
- package/templates/nonprofit/i18n/de.json +37 -0
- package/templates/nonprofit/i18n/downloads/ar.json +6 -0
- package/templates/nonprofit/i18n/downloads/de.json +6 -0
- package/templates/nonprofit/i18n/downloads/en.json +6 -0
- package/templates/nonprofit/i18n/downloads/fr.json +6 -0
- package/templates/nonprofit/i18n/en.json +37 -0
- package/templates/nonprofit/i18n/events/ar.json +20 -0
- package/templates/nonprofit/i18n/events/de.json +20 -0
- package/templates/nonprofit/i18n/events/en.json +20 -0
- package/templates/nonprofit/i18n/events/fr.json +20 -0
- package/templates/nonprofit/i18n/fr.json +37 -0
- package/templates/nonprofit/i18n/people/ar.json +6 -0
- package/templates/nonprofit/i18n/people/de.json +6 -0
- package/templates/nonprofit/i18n/people/en.json +6 -0
- package/templates/nonprofit/i18n/people/fr.json +6 -0
- package/templates/nonprofit/i18n/projects/ar.json +7 -0
- package/templates/nonprofit/i18n/projects/de.json +7 -0
- package/templates/nonprofit/i18n/projects/en.json +7 -0
- package/templates/nonprofit/i18n/projects/fr.json +7 -0
- package/templates/nonprofit/i18n/site/ar.json +39 -0
- package/templates/nonprofit/i18n/site/de.json +39 -0
- package/templates/nonprofit/i18n/site/en.json +39 -0
- package/templates/nonprofit/i18n/site/fr.json +39 -0
- package/templates/nonprofit/modules/feature-messages.ts +19 -0
- package/templates/nonprofit/modules/feeds/index.ts +22 -0
- package/templates/nonprofit/modules/feeds/routes.ts +13 -0
- package/templates/nonprofit/modules/page-paths/index.ts +26 -0
- package/templates/nonprofit/modules/page-paths/paths.ts +48 -0
- package/templates/nonprofit/nuxt.config.ts +36 -0
- package/templates/nonprofit/package.json +63 -0
- package/templates/nonprofit/pnpm-workspace.yaml +6 -0
- package/templates/nonprofit/public/files/annual-report-2025.pdf +0 -0
- package/templates/nonprofit/public/logos/partner-one.svg +5 -0
- package/templates/nonprofit/public/logos/partner-three.svg +5 -0
- package/templates/nonprofit/public/logos/partner-two.svg +4 -0
- package/templates/nonprofit/public/media/bank-clean-up.jpg +0 -0
- package/templates/nonprofit/public/media/forest-stream.jpg +0 -0
- package/templates/nonprofit/public/media/green-bank.jpg +0 -0
- package/templates/nonprofit/public/media/planting.jpg +0 -0
- package/templates/nonprofit/public/media/river-town.jpg +0 -0
- package/templates/nonprofit/public/media/workshop.jpg +0 -0
- package/templates/nonprofit/server/middleware/news-feed.ts +37 -0
- package/templates/nonprofit/server/plugins/font-preload.ts +17 -0
- package/templates/nonprofit/site-url.ts +21 -0
- package/templates/nonprofit/tsconfig.json +9 -0
- package/templates/nonprofit.json +20 -0
- package/templates/portfolio/.env.example +8 -0
- package/templates/portfolio/.github/screenshots/home-dark.png +0 -0
- package/templates/portfolio/.github/screenshots/home-light.png +0 -0
- package/templates/portfolio/.github/workflows/ci.yml +27 -0
- package/templates/portfolio/DESIGN.md +197 -0
- package/templates/portfolio/LICENSE +21 -0
- package/templates/portfolio/MEDIA.md +35 -0
- package/templates/portfolio/NOTES.md +18 -0
- package/templates/portfolio/README.md +267 -0
- package/templates/portfolio/app/app.config.ts +27 -0
- package/templates/portfolio/app/app.vue +7 -0
- package/templates/portfolio/app/assets/css/main.css +56 -0
- package/templates/portfolio/app/assets/css/tokens.css +400 -0
- package/templates/portfolio/app/bricks/pages.ts +38 -0
- package/templates/portfolio/app/bricks/projects.ts +114 -0
- package/templates/portfolio/app/components/InitialsAvatar.vue +18 -0
- package/templates/portfolio/app/components/ProseBody.vue +13 -0
- package/templates/portfolio/app/components/StartProject.vue +15 -0
- package/templates/portfolio/app/components/block/Cards.vue +54 -0
- package/templates/portfolio/app/components/block/Cta.vue +26 -0
- package/templates/portfolio/app/components/block/Empty.vue +26 -0
- package/templates/portfolio/app/components/block/Features.vue +24 -0
- package/templates/portfolio/app/components/block/Gallery.vue +81 -0
- package/templates/portfolio/app/components/block/Hero.vue +47 -0
- package/templates/portfolio/app/components/block/PageHeader.vue +21 -0
- package/templates/portfolio/app/components/block/Section.vue +31 -0
- package/templates/portfolio/app/components/blog/Byline.vue +22 -0
- package/templates/portfolio/app/components/blog/PostList.vue +33 -0
- package/templates/portfolio/app/components/blog/TagList.vue +17 -0
- package/templates/portfolio/app/components/pages/Top.vue +12 -0
- package/templates/portfolio/app/components/people/List.vue +41 -0
- package/templates/portfolio/app/components/people/TeamContact.vue +9 -0
- package/templates/portfolio/app/components/projects/Body.vue +62 -0
- package/templates/portfolio/app/components/projects/List.vue +38 -0
- package/templates/portfolio/app/components/site/Contact.vue +38 -0
- package/templates/portfolio/app/components/site/Footer.vue +81 -0
- package/templates/portfolio/app/components/site/Header.vue +52 -0
- package/templates/portfolio/app/components/site/LanguageSwitch.vue +34 -0
- package/templates/portfolio/app/components/site/Lightbox.vue +62 -0
- package/templates/portfolio/app/components/site/Logo.vue +17 -0
- package/templates/portfolio/app/components/site/NavLink.vue +19 -0
- package/templates/portfolio/app/components/site/NavSheet.vue +63 -0
- package/templates/portfolio/app/components/site/Notice.vue +21 -0
- package/templates/portfolio/app/components/site/SkipLink.vue +15 -0
- package/templates/portfolio/app/components/site/ThemeToggle.vue +28 -0
- package/templates/portfolio/app/components/ui/button/Button.vue +30 -0
- package/templates/portfolio/app/components/ui/button/index.ts +44 -0
- package/templates/portfolio/app/components/ui/sheet/Sheet.vue +16 -0
- package/templates/portfolio/app/components/ui/sheet/SheetClose.vue +13 -0
- package/templates/portfolio/app/components/ui/sheet/SheetContent.vue +54 -0
- package/templates/portfolio/app/components/ui/sheet/SheetDescription.vue +23 -0
- package/templates/portfolio/app/components/ui/sheet/SheetOverlay.vue +22 -0
- package/templates/portfolio/app/components/ui/sheet/SheetTitle.vue +23 -0
- package/templates/portfolio/app/components/ui/sheet/SheetTrigger.vue +13 -0
- package/templates/portfolio/app/components/ui/sheet/index.ts +7 -0
- package/templates/portfolio/app/composables/useBlog.ts +103 -0
- package/templates/portfolio/app/composables/usePageSeo.ts +50 -0
- package/templates/portfolio/app/composables/useProjectJsonLd.ts +26 -0
- package/templates/portfolio/app/composables/useProjects.ts +31 -0
- package/templates/portfolio/app/composables/useSiteAppConfig.ts +79 -0
- package/templates/portfolio/app/composables/useStartProject.ts +12 -0
- package/templates/portfolio/app/error.vue +35 -0
- package/templates/portfolio/app/layouts/default.vue +23 -0
- package/templates/portfolio/app/lib/utils.ts +26 -0
- package/templates/portfolio/app/pages/[...slug].vue +36 -0
- package/templates/portfolio/app/pages/index.vue +60 -0
- package/templates/portfolio/app/pages/legal/[slug].vue +46 -0
- package/templates/portfolio/app/pages/news/[slug].vue +94 -0
- package/templates/portfolio/app/pages/news/index.vue +54 -0
- package/templates/portfolio/app/pages/news/tags/[tag].vue +41 -0
- package/templates/portfolio/app/pages/projects/[slug].vue +49 -0
- package/templates/portfolio/app/pages/projects/index.vue +24 -0
- package/templates/portfolio/app/pages/team.vue +40 -0
- package/templates/portfolio/app/routes.ts +30 -0
- package/templates/portfolio/app/utils/telHref.ts +3 -0
- package/templates/portfolio/components.json +21 -0
- package/templates/portfolio/content/home.de.md +4 -0
- package/templates/portfolio/content/home.md +4 -0
- package/templates/portfolio/content/legal/1.privacy.de.md +19 -0
- package/templates/portfolio/content/legal/1.privacy.md +21 -0
- package/templates/portfolio/content/legal/2.imprint.de.md +15 -0
- package/templates/portfolio/content/legal/2.imprint.md +17 -0
- package/templates/portfolio/content/notices/1.holm-chair.de.md +3 -0
- package/templates/portfolio/content/notices/1.holm-chair.md +4 -0
- package/templates/portfolio/content/pages/1.how-we-work.de.md +23 -0
- package/templates/portfolio/content/pages/1.how-we-work.md +23 -0
- package/templates/portfolio/content/people/1.maren-holt.de.md +4 -0
- package/templates/portfolio/content/people/1.maren-holt.md +6 -0
- package/templates/portfolio/content/people/2.ole-petersen.de.md +4 -0
- package/templates/portfolio/content/people/2.ole-petersen.md +6 -0
- package/templates/portfolio/content/posts/full-size-drawings.de.md +11 -0
- package/templates/portfolio/content/posts/full-size-drawings.md +13 -0
- package/templates/portfolio/content/posts/lime-plaster.de.md +11 -0
- package/templates/portfolio/content/posts/lime-plaster.md +13 -0
- package/templates/portfolio/content/projects/1.attic-flat-ottensen.de.md +19 -0
- package/templates/portfolio/content/projects/1.attic-flat-ottensen.md +22 -0
- package/templates/portfolio/content/projects/2.elbsand-vases.de.md +18 -0
- package/templates/portfolio/content/projects/2.elbsand-vases.md +21 -0
- package/templates/portfolio/content/projects/3.werftblick-entrance-hall.de.md +18 -0
- package/templates/portfolio/content/projects/3.werftblick-entrance-hall.md +22 -0
- package/templates/portfolio/content/projects/4.holm-chair.de.md +18 -0
- package/templates/portfolio/content/projects/4.holm-chair.md +21 -0
- package/templates/portfolio/content/site.md +13 -0
- package/templates/portfolio/eslint.config.mjs +12 -0
- package/templates/portfolio/eslint.tailwind.mjs +33 -0
- package/templates/portfolio/ginko.config.ts +70 -0
- package/templates/portfolio/gitignore +7 -0
- package/templates/portfolio/i18n/blog/de.json +18 -0
- package/templates/portfolio/i18n/blog/en.json +18 -0
- package/templates/portfolio/i18n/de.json +47 -0
- package/templates/portfolio/i18n/en.json +47 -0
- package/templates/portfolio/i18n/gallery/de.json +8 -0
- package/templates/portfolio/i18n/gallery/en.json +8 -0
- package/templates/portfolio/i18n/people/de.json +6 -0
- package/templates/portfolio/i18n/people/en.json +6 -0
- package/templates/portfolio/i18n/projects/de.json +7 -0
- package/templates/portfolio/i18n/projects/en.json +7 -0
- package/templates/portfolio/i18n/site/de.json +39 -0
- package/templates/portfolio/i18n/site/en.json +39 -0
- package/templates/portfolio/modules/feature-messages.ts +19 -0
- package/templates/portfolio/modules/feeds/index.ts +22 -0
- package/templates/portfolio/modules/feeds/routes.ts +13 -0
- package/templates/portfolio/modules/page-paths/index.ts +26 -0
- package/templates/portfolio/modules/page-paths/paths.ts +48 -0
- package/templates/portfolio/nuxt.config.ts +30 -0
- package/templates/portfolio/package.json +60 -0
- package/templates/portfolio/pnpm-workspace.yaml +6 -0
- package/templates/portfolio/public/media/attic-light.jpg +0 -0
- package/templates/portfolio/public/media/ceramic-vases.jpg +0 -0
- package/templates/portfolio/public/media/concrete-stair.jpg +0 -0
- package/templates/portfolio/public/media/material-samples.jpg +0 -0
- package/templates/portfolio/public/media/oak-chair.jpg +0 -0
- package/templates/portfolio/public/media/workshop-drawings.jpg +0 -0
- package/templates/portfolio/server/middleware/news-feed.ts +37 -0
- package/templates/portfolio/server/plugins/font-preload.ts +17 -0
- package/templates/portfolio/site-url.ts +21 -0
- package/templates/portfolio/tsconfig.json +9 -0
- package/templates/portfolio.json +11 -0
- package/templates/restaurant/.env.example +8 -0
- package/templates/restaurant/.github/screenshots/home-dark.png +0 -0
- package/templates/restaurant/.github/screenshots/home-light.png +0 -0
- package/templates/restaurant/.github/workflows/ci.yml +27 -0
- package/templates/restaurant/DESIGN.md +197 -0
- package/templates/restaurant/LICENSE +21 -0
- package/templates/restaurant/MEDIA.md +37 -0
- package/templates/restaurant/README.md +249 -0
- package/templates/restaurant/app/app.config.ts +33 -0
- package/templates/restaurant/app/app.vue +7 -0
- package/templates/restaurant/app/assets/css/main.css +20 -0
- package/templates/restaurant/app/assets/css/tokens.css +400 -0
- package/templates/restaurant/app/bricks/pages.ts +38 -0
- package/templates/restaurant/app/components/InitialsAvatar.vue +18 -0
- package/templates/restaurant/app/components/ProseBody.vue +13 -0
- package/templates/restaurant/app/components/block/Cards.vue +54 -0
- package/templates/restaurant/app/components/block/Cta.vue +26 -0
- package/templates/restaurant/app/components/block/Empty.vue +26 -0
- package/templates/restaurant/app/components/block/Features.vue +24 -0
- package/templates/restaurant/app/components/block/Gallery.vue +81 -0
- package/templates/restaurant/app/components/block/Hero.vue +47 -0
- package/templates/restaurant/app/components/block/PageHeader.vue +21 -0
- package/templates/restaurant/app/components/block/Section.vue +31 -0
- package/templates/restaurant/app/components/event/Upcoming.vue +25 -0
- package/templates/restaurant/app/components/hours/Table.vue +119 -0
- package/templates/restaurant/app/components/hours/Today.vue +55 -0
- package/templates/restaurant/app/components/menu/AllergenKey.vue +17 -0
- package/templates/restaurant/app/components/menu/Allergens.vue +24 -0
- package/templates/restaurant/app/components/menu/Diet.vue +16 -0
- package/templates/restaurant/app/components/menu/Dish.vue +30 -0
- package/templates/restaurant/app/components/menu/LunchDays.vue +42 -0
- package/templates/restaurant/app/components/site/Contact.vue +38 -0
- package/templates/restaurant/app/components/site/Footer.vue +81 -0
- package/templates/restaurant/app/components/site/FooterStatus.vue +9 -0
- package/templates/restaurant/app/components/site/Header.vue +52 -0
- package/templates/restaurant/app/components/site/LanguageSwitch.vue +34 -0
- package/templates/restaurant/app/components/site/Lightbox.vue +62 -0
- package/templates/restaurant/app/components/site/Logo.vue +17 -0
- package/templates/restaurant/app/components/site/NavLink.vue +19 -0
- package/templates/restaurant/app/components/site/NavSheet.vue +63 -0
- package/templates/restaurant/app/components/site/Notice.vue +21 -0
- package/templates/restaurant/app/components/site/SkipLink.vue +15 -0
- package/templates/restaurant/app/components/site/ThemeToggle.vue +28 -0
- package/templates/restaurant/app/components/ui/button/Button.vue +30 -0
- package/templates/restaurant/app/components/ui/button/index.ts +44 -0
- package/templates/restaurant/app/components/ui/sheet/Sheet.vue +16 -0
- package/templates/restaurant/app/components/ui/sheet/SheetClose.vue +13 -0
- package/templates/restaurant/app/components/ui/sheet/SheetContent.vue +54 -0
- package/templates/restaurant/app/components/ui/sheet/SheetDescription.vue +23 -0
- package/templates/restaurant/app/components/ui/sheet/SheetOverlay.vue +22 -0
- package/templates/restaurant/app/components/ui/sheet/SheetTitle.vue +23 -0
- package/templates/restaurant/app/components/ui/sheet/SheetTrigger.vue +13 -0
- package/templates/restaurant/app/components/ui/sheet/index.ts +7 -0
- package/templates/restaurant/app/composables/useEvents.ts +182 -0
- package/templates/restaurant/app/composables/useHours.ts +81 -0
- package/templates/restaurant/app/composables/useMenu.ts +76 -0
- package/templates/restaurant/app/composables/usePageSeo.ts +50 -0
- package/templates/restaurant/app/composables/useSiteAppConfig.ts +79 -0
- package/templates/restaurant/app/error.vue +35 -0
- package/templates/restaurant/app/layouts/default.vue +23 -0
- package/templates/restaurant/app/layouts/print.vue +9 -0
- package/templates/restaurant/app/lib/utils.ts +26 -0
- package/templates/restaurant/app/pages/[...slug].vue +36 -0
- package/templates/restaurant/app/pages/events/[slug].vue +106 -0
- package/templates/restaurant/app/pages/events/index.vue +20 -0
- package/templates/restaurant/app/pages/gallery.vue +17 -0
- package/templates/restaurant/app/pages/index.vue +163 -0
- package/templates/restaurant/app/pages/legal/[slug].vue +46 -0
- package/templates/restaurant/app/pages/lunch.vue +30 -0
- package/templates/restaurant/app/pages/menu/index.vue +46 -0
- package/templates/restaurant/app/pages/menu/print.vue +69 -0
- package/templates/restaurant/app/pages/reservations.vue +52 -0
- package/templates/restaurant/app/routes.ts +33 -0
- package/templates/restaurant/app/utils/hours.ts +58 -0
- package/templates/restaurant/app/utils/telHref.ts +3 -0
- package/templates/restaurant/components.json +21 -0
- package/templates/restaurant/content/events/1.wine-evening.de.md +10 -0
- package/templates/restaurant/content/events/1.wine-evening.it.md +10 -0
- package/templates/restaurant/content/events/1.wine-evening.md +16 -0
- package/templates/restaurant/content/events/2.cooking-class.de.md +10 -0
- package/templates/restaurant/content/events/2.cooking-class.it.md +10 -0
- package/templates/restaurant/content/events/2.cooking-class.md +16 -0
- package/templates/restaurant/content/gallery.de.md +15 -0
- package/templates/restaurant/content/gallery.it.md +15 -0
- package/templates/restaurant/content/gallery.md +21 -0
- package/templates/restaurant/content/home.de.md +6 -0
- package/templates/restaurant/content/home.it.md +6 -0
- package/templates/restaurant/content/home.md +7 -0
- package/templates/restaurant/content/hourPlans/1.winter-hours.de.md +3 -0
- package/templates/restaurant/content/hourPlans/1.winter-hours.it.md +3 -0
- package/templates/restaurant/content/hourPlans/1.winter-hours.md +41 -0
- package/templates/restaurant/content/hours.de.md +4 -0
- package/templates/restaurant/content/hours.it.md +4 -0
- package/templates/restaurant/content/hours.md +45 -0
- package/templates/restaurant/content/legal/1.privacy.de.md +28 -0
- package/templates/restaurant/content/legal/1.privacy.it.md +28 -0
- package/templates/restaurant/content/legal/1.privacy.md +29 -0
- package/templates/restaurant/content/legal/2.terms.de.md +21 -0
- package/templates/restaurant/content/legal/2.terms.it.md +21 -0
- package/templates/restaurant/content/legal/2.terms.md +22 -0
- package/templates/restaurant/content/legal/3.imprint.de.md +15 -0
- package/templates/restaurant/content/legal/3.imprint.it.md +15 -0
- package/templates/restaurant/content/legal/3.imprint.md +16 -0
- package/templates/restaurant/content/lunch.de.md +3 -0
- package/templates/restaurant/content/lunch.it.md +3 -0
- package/templates/restaurant/content/lunch.md +25 -0
- package/templates/restaurant/content/menu/1.liptauer.de.md +4 -0
- package/templates/restaurant/content/menu/1.liptauer.it.md +4 -0
- package/templates/restaurant/content/menu/1.liptauer.md +8 -0
- package/templates/restaurant/content/menu/10.kaiserschmarrn.de.md +4 -0
- package/templates/restaurant/content/menu/10.kaiserschmarrn.it.md +4 -0
- package/templates/restaurant/content/menu/10.kaiserschmarrn.md +8 -0
- package/templates/restaurant/content/menu/11.apple-strudel.de.md +4 -0
- package/templates/restaurant/content/menu/11.apple-strudel.it.md +4 -0
- package/templates/restaurant/content/menu/11.apple-strudel.md +8 -0
- package/templates/restaurant/content/menu/12.apple-spritzer.de.md +4 -0
- package/templates/restaurant/content/menu/12.apple-spritzer.it.md +4 -0
- package/templates/restaurant/content/menu/12.apple-spritzer.md +8 -0
- package/templates/restaurant/content/menu/13.elderflower-soda.de.md +3 -0
- package/templates/restaurant/content/menu/13.elderflower-soda.it.md +3 -0
- package/templates/restaurant/content/menu/13.elderflower-soda.md +7 -0
- package/templates/restaurant/content/menu/14.melange.de.md +4 -0
- package/templates/restaurant/content/menu/14.melange.it.md +4 -0
- package/templates/restaurant/content/menu/14.melange.md +8 -0
- package/templates/restaurant/content/menu/15.gruener-veltliner.de.md +4 -0
- package/templates/restaurant/content/menu/15.gruener-veltliner.it.md +4 -0
- package/templates/restaurant/content/menu/15.gruener-veltliner.md +8 -0
- package/templates/restaurant/content/menu/16.zweigelt.de.md +4 -0
- package/templates/restaurant/content/menu/16.zweigelt.it.md +4 -0
- package/templates/restaurant/content/menu/16.zweigelt.md +8 -0
- package/templates/restaurant/content/menu/17.maerzen.de.md +4 -0
- package/templates/restaurant/content/menu/17.maerzen.it.md +4 -0
- package/templates/restaurant/content/menu/17.maerzen.md +8 -0
- package/templates/restaurant/content/menu/2.cured-char.de.md +4 -0
- package/templates/restaurant/content/menu/2.cured-char.it.md +4 -0
- package/templates/restaurant/content/menu/2.cured-char.md +8 -0
- package/templates/restaurant/content/menu/3.frittaten-soup.de.md +4 -0
- package/templates/restaurant/content/menu/3.frittaten-soup.it.md +4 -0
- package/templates/restaurant/content/menu/3.frittaten-soup.md +8 -0
- package/templates/restaurant/content/menu/4.pumpkin-soup.de.md +4 -0
- package/templates/restaurant/content/menu/4.pumpkin-soup.it.md +4 -0
- package/templates/restaurant/content/menu/4.pumpkin-soup.md +8 -0
- package/templates/restaurant/content/menu/5.wiener-schnitzel.de.md +4 -0
- package/templates/restaurant/content/menu/5.wiener-schnitzel.it.md +4 -0
- package/templates/restaurant/content/menu/5.wiener-schnitzel.md +8 -0
- package/templates/restaurant/content/menu/6.tafelspitz.de.md +4 -0
- package/templates/restaurant/content/menu/6.tafelspitz.it.md +4 -0
- package/templates/restaurant/content/menu/6.tafelspitz.md +8 -0
- package/templates/restaurant/content/menu/7.roast-pork.de.md +4 -0
- package/templates/restaurant/content/menu/7.roast-pork.it.md +4 -0
- package/templates/restaurant/content/menu/7.roast-pork.md +8 -0
- package/templates/restaurant/content/menu/8.kasnocken.de.md +4 -0
- package/templates/restaurant/content/menu/8.kasnocken.it.md +4 -0
- package/templates/restaurant/content/menu/8.kasnocken.md +8 -0
- package/templates/restaurant/content/menu/9.lentil-goulash.de.md +4 -0
- package/templates/restaurant/content/menu/9.lentil-goulash.it.md +4 -0
- package/templates/restaurant/content/menu/9.lentil-goulash.md +8 -0
- package/templates/restaurant/content/notices/1.cook-wanted.de.md +3 -0
- package/templates/restaurant/content/notices/1.cook-wanted.it.md +3 -0
- package/templates/restaurant/content/notices/1.cook-wanted.md +4 -0
- package/templates/restaurant/content/pages/1.about.de.md +23 -0
- package/templates/restaurant/content/pages/1.about.it.md +23 -0
- package/templates/restaurant/content/pages/1.about.md +24 -0
- package/templates/restaurant/content/reservations.de.md +20 -0
- package/templates/restaurant/content/reservations.it.md +20 -0
- package/templates/restaurant/content/reservations.md +20 -0
- package/templates/restaurant/content/site.de.md +3 -0
- package/templates/restaurant/content/site.it.md +3 -0
- package/templates/restaurant/content/site.md +12 -0
- package/templates/restaurant/eslint.config.mjs +12 -0
- package/templates/restaurant/eslint.tailwind.mjs +33 -0
- package/templates/restaurant/ginko.config.ts +78 -0
- package/templates/restaurant/gitignore +7 -0
- package/templates/restaurant/i18n/de.json +31 -0
- package/templates/restaurant/i18n/en.json +31 -0
- package/templates/restaurant/i18n/events/de.json +20 -0
- package/templates/restaurant/i18n/events/en.json +20 -0
- package/templates/restaurant/i18n/events/it.json +20 -0
- package/templates/restaurant/i18n/gallery/de.json +8 -0
- package/templates/restaurant/i18n/gallery/en.json +8 -0
- package/templates/restaurant/i18n/gallery/it.json +8 -0
- package/templates/restaurant/i18n/hours/de.json +27 -0
- package/templates/restaurant/i18n/hours/en.json +27 -0
- package/templates/restaurant/i18n/hours/it.json +27 -0
- package/templates/restaurant/i18n/it.json +31 -0
- package/templates/restaurant/i18n/menu/de.json +54 -0
- package/templates/restaurant/i18n/menu/en.json +54 -0
- package/templates/restaurant/i18n/menu/it.json +54 -0
- package/templates/restaurant/i18n/site/de.json +39 -0
- package/templates/restaurant/i18n/site/en.json +39 -0
- package/templates/restaurant/i18n/site/it.json +39 -0
- package/templates/restaurant/modules/feature-messages.ts +19 -0
- package/templates/restaurant/modules/feeds/index.ts +22 -0
- package/templates/restaurant/modules/feeds/routes.ts +13 -0
- package/templates/restaurant/modules/page-paths/index.ts +26 -0
- package/templates/restaurant/modules/page-paths/paths.ts +48 -0
- package/templates/restaurant/nuxt.config.ts +27 -0
- package/templates/restaurant/package.json +61 -0
- package/templates/restaurant/pnpm-workspace.yaml +6 -0
- package/templates/restaurant/public/media/garten.jpg +0 -0
- package/templates/restaurant/public/media/gastraum.jpg +0 -0
- package/templates/restaurant/public/media/gaststube.jpg +0 -0
- package/templates/restaurant/public/media/kueche.jpg +0 -0
- package/templates/restaurant/public/media/schnitzel.jpg +0 -0
- package/templates/restaurant/public/media/strudel.jpg +0 -0
- package/templates/restaurant/public/media/weinabend.jpg +0 -0
- package/templates/restaurant/server/plugins/font-preload.ts +17 -0
- package/templates/restaurant/site-url.ts +21 -0
- package/templates/restaurant/tsconfig.json +9 -0
- package/templates/restaurant.json +19 -0
- package/templates/saas/.env.example +8 -0
- package/templates/saas/.github/screenshots/home-dark.png +0 -0
- package/templates/saas/.github/screenshots/home-light.png +0 -0
- package/templates/saas/.github/workflows/ci.yml +27 -0
- package/templates/saas/DESIGN.md +197 -0
- package/templates/saas/LICENSE +21 -0
- package/templates/saas/MEDIA.md +20 -0
- package/templates/saas/NOTES.md +23 -0
- package/templates/saas/README.md +264 -0
- package/templates/saas/app/app.config.ts +37 -0
- package/templates/saas/app/app.vue +7 -0
- package/templates/saas/app/assets/css/main.css +30 -0
- package/templates/saas/app/assets/css/tokens.css +400 -0
- package/templates/saas/app/bricks/logos-quotes.ts +47 -0
- package/templates/saas/app/bricks/pages.ts +38 -0
- package/templates/saas/app/bricks/pricing.ts +60 -0
- package/templates/saas/app/components/DocsPageEnd.vue +8 -0
- package/templates/saas/app/components/InitialsAvatar.vue +18 -0
- package/templates/saas/app/components/ProseBody.vue +13 -0
- package/templates/saas/app/components/block/Cards.vue +54 -0
- package/templates/saas/app/components/block/Cta.vue +26 -0
- package/templates/saas/app/components/block/Empty.vue +26 -0
- package/templates/saas/app/components/block/Faq.vue +19 -0
- package/templates/saas/app/components/block/Features.vue +24 -0
- package/templates/saas/app/components/block/Hero.vue +47 -0
- package/templates/saas/app/components/block/Logos.vue +22 -0
- package/templates/saas/app/components/block/PageHeader.vue +21 -0
- package/templates/saas/app/components/block/Quote.vue +19 -0
- package/templates/saas/app/components/block/Section.vue +31 -0
- package/templates/saas/app/components/blog/Byline.vue +22 -0
- package/templates/saas/app/components/blog/PostList.vue +33 -0
- package/templates/saas/app/components/blog/TagList.vue +17 -0
- package/templates/saas/app/components/changelog/Latest.vue +32 -0
- package/templates/saas/app/components/help/Contact.vue +14 -0
- package/templates/saas/app/components/pages/Top.vue +30 -0
- package/templates/saas/app/components/pricing/More.vue +21 -0
- package/templates/saas/app/components/pricing/Plans.vue +60 -0
- package/templates/saas/app/components/site/Contact.vue +38 -0
- package/templates/saas/app/components/site/Footer.vue +81 -0
- package/templates/saas/app/components/site/Header.vue +52 -0
- package/templates/saas/app/components/site/LanguageSwitch.vue +34 -0
- package/templates/saas/app/components/site/Logo.vue +17 -0
- package/templates/saas/app/components/site/NavLink.vue +19 -0
- package/templates/saas/app/components/site/NavSheet.vue +63 -0
- package/templates/saas/app/components/site/Notice.vue +21 -0
- package/templates/saas/app/components/site/PageCta.vue +12 -0
- package/templates/saas/app/components/site/SkipLink.vue +15 -0
- package/templates/saas/app/components/site/ThemeToggle.vue +28 -0
- package/templates/saas/app/components/ui/accordion/Accordion.vue +16 -0
- package/templates/saas/app/components/ui/accordion/AccordionContent.vue +26 -0
- package/templates/saas/app/components/ui/accordion/AccordionItem.vue +24 -0
- package/templates/saas/app/components/ui/accordion/AccordionTrigger.vue +35 -0
- package/templates/saas/app/components/ui/accordion/index.ts +5 -0
- package/templates/saas/app/components/ui/button/Button.vue +30 -0
- package/templates/saas/app/components/ui/button/index.ts +44 -0
- package/templates/saas/app/components/ui/sheet/Sheet.vue +16 -0
- package/templates/saas/app/components/ui/sheet/SheetClose.vue +13 -0
- package/templates/saas/app/components/ui/sheet/SheetContent.vue +54 -0
- package/templates/saas/app/components/ui/sheet/SheetDescription.vue +23 -0
- package/templates/saas/app/components/ui/sheet/SheetOverlay.vue +22 -0
- package/templates/saas/app/components/ui/sheet/SheetTitle.vue +23 -0
- package/templates/saas/app/components/ui/sheet/SheetTrigger.vue +13 -0
- package/templates/saas/app/components/ui/sheet/index.ts +7 -0
- package/templates/saas/app/composables/useBlog.ts +103 -0
- package/templates/saas/app/composables/useChangelog.ts +54 -0
- package/templates/saas/app/composables/usePageSeo.ts +50 -0
- package/templates/saas/app/composables/usePricing.ts +110 -0
- package/templates/saas/app/composables/useSiteAppConfig.ts +79 -0
- package/templates/saas/app/error.vue +35 -0
- package/templates/saas/app/layouts/default.vue +23 -0
- package/templates/saas/app/lib/utils.ts +26 -0
- package/templates/saas/app/pages/[...slug].vue +36 -0
- package/templates/saas/app/pages/changelog.vue +47 -0
- package/templates/saas/app/pages/faq.vue +39 -0
- package/templates/saas/app/pages/help/index.vue +21 -0
- package/templates/saas/app/pages/index.vue +67 -0
- package/templates/saas/app/pages/legal/[slug].vue +46 -0
- package/templates/saas/app/pages/news/[slug].vue +94 -0
- package/templates/saas/app/pages/news/index.vue +54 -0
- package/templates/saas/app/pages/news/tags/[tag].vue +41 -0
- package/templates/saas/app/pages/pricing.vue +27 -0
- package/templates/saas/app/routes.ts +31 -0
- package/templates/saas/app/utils/telHref.ts +3 -0
- package/templates/saas/components.json +21 -0
- package/templates/saas/content/changelog/v4-3-0.de.md +18 -0
- package/templates/saas/content/changelog/v4-3-0.fr.md +18 -0
- package/templates/saas/content/changelog/v4-3-0.md +20 -0
- package/templates/saas/content/changelog/v4-4-0.de.md +15 -0
- package/templates/saas/content/changelog/v4-4-0.fr.md +15 -0
- package/templates/saas/content/changelog/v4-4-0.md +17 -0
- package/templates/saas/content/changelog/v4-4-1.de.md +11 -0
- package/templates/saas/content/changelog/v4-4-1.fr.md +11 -0
- package/templates/saas/content/changelog/v4-4-1.md +13 -0
- package/templates/saas/content/changelog/v4-5-0.de.md +19 -0
- package/templates/saas/content/changelog/v4-5-0.fr.md +19 -0
- package/templates/saas/content/changelog/v4-5-0.md +21 -0
- package/templates/saas/content/changelog/v4-6-0.de.md +19 -0
- package/templates/saas/content/changelog/v4-6-0.fr.md +19 -0
- package/templates/saas/content/changelog/v4-6-0.md +21 -0
- package/templates/saas/content/docs/1.getting-started.de.md +33 -0
- package/templates/saas/content/docs/1.getting-started.fr.md +33 -0
- package/templates/saas/content/docs/1.getting-started.md +32 -0
- package/templates/saas/content/docs/2.shifts.de.md +24 -0
- package/templates/saas/content/docs/2.shifts.fr.md +24 -0
- package/templates/saas/content/docs/2.shifts.md +23 -0
- package/templates/saas/content/docs/3.export.de.md +21 -0
- package/templates/saas/content/docs/3.export.fr.md +21 -0
- package/templates/saas/content/docs/3.export.md +20 -0
- package/templates/saas/content/faq/1.billing.de.md +4 -0
- package/templates/saas/content/faq/1.billing.fr.md +4 -0
- package/templates/saas/content/faq/1.billing.md +4 -0
- package/templates/saas/content/faq/2.cancellation.de.md +4 -0
- package/templates/saas/content/faq/2.cancellation.fr.md +4 -0
- package/templates/saas/content/faq/2.cancellation.md +4 -0
- package/templates/saas/content/faq/3.data-export.de.md +4 -0
- package/templates/saas/content/faq/3.data-export.fr.md +4 -0
- package/templates/saas/content/faq/3.data-export.md +4 -0
- package/templates/saas/content/faq/4.change-plan.de.md +4 -0
- package/templates/saas/content/faq/4.change-plan.fr.md +4 -0
- package/templates/saas/content/faq/4.change-plan.md +4 -0
- package/templates/saas/content/faq/5.trial.de.md +4 -0
- package/templates/saas/content/faq/5.trial.fr.md +4 -0
- package/templates/saas/content/faq/5.trial.md +4 -0
- package/templates/saas/content/faq/6.data-location.de.md +4 -0
- package/templates/saas/content/faq/6.data-location.fr.md +4 -0
- package/templates/saas/content/faq/6.data-location.md +4 -0
- package/templates/saas/content/faq/7.data-processing.de.md +4 -0
- package/templates/saas/content/faq/7.data-processing.fr.md +4 -0
- package/templates/saas/content/faq/7.data-processing.md +4 -0
- package/templates/saas/content/home.de.md +24 -0
- package/templates/saas/content/home.fr.md +24 -0
- package/templates/saas/content/home.md +26 -0
- package/templates/saas/content/legal/1.privacy.de.md +20 -0
- package/templates/saas/content/legal/1.privacy.fr.md +20 -0
- package/templates/saas/content/legal/1.privacy.md +22 -0
- package/templates/saas/content/legal/2.terms.de.md +20 -0
- package/templates/saas/content/legal/2.terms.fr.md +20 -0
- package/templates/saas/content/legal/2.terms.md +22 -0
- package/templates/saas/content/legal/3.imprint.de.md +16 -0
- package/templates/saas/content/legal/3.imprint.fr.md +16 -0
- package/templates/saas/content/legal/3.imprint.md +18 -0
- package/templates/saas/content/logos/1.sonnenlinde.md +6 -0
- package/templates/saas/content/logos/2.elsterau.md +6 -0
- package/templates/saas/content/logos/3.rosental.md +6 -0
- package/templates/saas/content/logos/4.muldental.md +6 -0
- package/templates/saas/content/notices/5.swap-requests.de.md +3 -0
- package/templates/saas/content/notices/5.swap-requests.fr.md +3 -0
- package/templates/saas/content/notices/5.swap-requests.md +4 -0
- package/templates/saas/content/pages/1.security.de.md +25 -0
- package/templates/saas/content/pages/1.security.fr.md +25 -0
- package/templates/saas/content/pages/1.security.md +25 -0
- package/templates/saas/content/pages/2.about.de.md +17 -0
- package/templates/saas/content/pages/2.about.fr.md +17 -0
- package/templates/saas/content/pages/2.about.md +17 -0
- package/templates/saas/content/pages/3.contact.de.md +15 -0
- package/templates/saas/content/pages/3.contact.fr.md +15 -0
- package/templates/saas/content/pages/3.contact.md +15 -0
- package/templates/saas/content/people/1.lena-hartmann.de.md +4 -0
- package/templates/saas/content/people/1.lena-hartmann.fr.md +4 -0
- package/templates/saas/content/people/1.lena-hartmann.md +5 -0
- package/templates/saas/content/people/2.jonas-pohl.de.md +4 -0
- package/templates/saas/content/people/2.jonas-pohl.fr.md +4 -0
- package/templates/saas/content/people/2.jonas-pohl.md +5 -0
- package/templates/saas/content/posts/rest-periods.de.md +20 -0
- package/templates/saas/content/posts/rest-periods.fr.md +20 -0
- package/templates/saas/content/posts/rest-periods.md +22 -0
- package/templates/saas/content/posts/summer-holidays.de.md +16 -0
- package/templates/saas/content/posts/summer-holidays.fr.md +16 -0
- package/templates/saas/content/posts/summer-holidays.md +18 -0
- package/templates/saas/content/posts/swap-requests.de.md +18 -0
- package/templates/saas/content/posts/swap-requests.fr.md +18 -0
- package/templates/saas/content/posts/swap-requests.md +20 -0
- package/templates/saas/content/pricing/1.small.de.md +11 -0
- package/templates/saas/content/pricing/1.small.fr.md +11 -0
- package/templates/saas/content/pricing/1.small.md +15 -0
- package/templates/saas/content/pricing/2.standard.de.md +11 -0
- package/templates/saas/content/pricing/2.standard.fr.md +11 -0
- package/templates/saas/content/pricing/2.standard.md +16 -0
- package/templates/saas/content/pricing/3.group.de.md +11 -0
- package/templates/saas/content/pricing/3.group.fr.md +11 -0
- package/templates/saas/content/pricing/3.group.md +12 -0
- package/templates/saas/content/quotes/1.ward-lead.de.md +4 -0
- package/templates/saas/content/quotes/1.ward-lead.fr.md +4 -0
- package/templates/saas/content/quotes/1.ward-lead.md +5 -0
- package/templates/saas/content/site.de.md +3 -0
- package/templates/saas/content/site.fr.md +3 -0
- package/templates/saas/content/site.md +12 -0
- package/templates/saas/eslint.config.mjs +12 -0
- package/templates/saas/eslint.tailwind.mjs +33 -0
- package/templates/saas/ginko.config.ts +108 -0
- package/templates/saas/gitignore +7 -0
- package/templates/saas/i18n/blog/de.json +18 -0
- package/templates/saas/i18n/blog/en.json +18 -0
- package/templates/saas/i18n/blog/fr.json +18 -0
- package/templates/saas/i18n/changelog/de.json +9 -0
- package/templates/saas/i18n/changelog/en.json +9 -0
- package/templates/saas/i18n/changelog/fr.json +9 -0
- package/templates/saas/i18n/de.json +48 -0
- package/templates/saas/i18n/en.json +48 -0
- package/templates/saas/i18n/faq/de.json +6 -0
- package/templates/saas/i18n/faq/en.json +6 -0
- package/templates/saas/i18n/faq/fr.json +6 -0
- package/templates/saas/i18n/fr.json +48 -0
- package/templates/saas/i18n/pricing/de.json +14 -0
- package/templates/saas/i18n/pricing/en.json +14 -0
- package/templates/saas/i18n/pricing/fr.json +14 -0
- package/templates/saas/i18n/site/de.json +39 -0
- package/templates/saas/i18n/site/en.json +39 -0
- package/templates/saas/i18n/site/fr.json +39 -0
- package/templates/saas/modules/feature-messages.ts +19 -0
- package/templates/saas/modules/feeds/index.ts +22 -0
- package/templates/saas/modules/feeds/routes.ts +13 -0
- package/templates/saas/modules/page-paths/index.ts +26 -0
- package/templates/saas/modules/page-paths/paths.ts +48 -0
- package/templates/saas/nuxt.config.ts +30 -0
- package/templates/saas/package.json +63 -0
- package/templates/saas/pnpm-workspace.yaml +6 -0
- package/templates/saas/public/logos/care-home-four.svg +4 -0
- package/templates/saas/public/logos/care-home-one.svg +4 -0
- package/templates/saas/public/logos/care-home-two.svg +4 -0
- package/templates/saas/public/logos/clinic-three.svg +4 -0
- package/templates/saas/public/media/rota.svg +76 -0
- package/templates/saas/server/middleware/changelog-feed.ts +50 -0
- package/templates/saas/server/middleware/news-feed.ts +37 -0
- package/templates/saas/server/plugins/font-preload.ts +17 -0
- package/templates/saas/shared/utils/changelog.ts +13 -0
- package/templates/saas/site-url.ts +21 -0
- package/templates/saas/tsconfig.json +9 -0
- package/templates/saas.json +12 -0
- package/templates/starter/.env.example +8 -0
- package/templates/starter/.github/screenshots/home-dark.png +0 -0
- package/templates/starter/.github/screenshots/home-light.png +0 -0
- package/templates/starter/.github/workflows/ci.yml +27 -0
- package/templates/starter/DESIGN.md +197 -0
- package/templates/starter/LICENSE +21 -0
- package/templates/starter/MEDIA.md +11 -0
- package/templates/starter/README.md +199 -0
- package/templates/starter/app/app.config.ts +21 -0
- package/templates/starter/app/app.vue +7 -0
- package/templates/starter/app/assets/css/main.css +19 -0
- package/templates/starter/app/assets/css/tokens.css +400 -0
- package/templates/starter/app/bricks/pages.ts +38 -0
- package/templates/starter/app/components/InitialsAvatar.vue +18 -0
- package/templates/starter/app/components/ProseBody.vue +13 -0
- package/templates/starter/app/components/block/Cards.vue +54 -0
- package/templates/starter/app/components/block/Cta.vue +26 -0
- package/templates/starter/app/components/block/Empty.vue +26 -0
- package/templates/starter/app/components/block/Features.vue +24 -0
- package/templates/starter/app/components/block/Hero.vue +47 -0
- package/templates/starter/app/components/block/PageHeader.vue +21 -0
- package/templates/starter/app/components/block/Section.vue +31 -0
- package/templates/starter/app/components/pages/Top.vue +11 -0
- package/templates/starter/app/components/site/Contact.vue +38 -0
- package/templates/starter/app/components/site/Footer.vue +81 -0
- package/templates/starter/app/components/site/Header.vue +52 -0
- package/templates/starter/app/components/site/LanguageSwitch.vue +34 -0
- package/templates/starter/app/components/site/Logo.vue +17 -0
- package/templates/starter/app/components/site/NavLink.vue +19 -0
- package/templates/starter/app/components/site/NavSheet.vue +63 -0
- package/templates/starter/app/components/site/Notice.vue +21 -0
- package/templates/starter/app/components/site/SkipLink.vue +15 -0
- package/templates/starter/app/components/site/ThemeToggle.vue +28 -0
- package/templates/starter/app/components/ui/button/Button.vue +30 -0
- package/templates/starter/app/components/ui/button/index.ts +44 -0
- package/templates/starter/app/components/ui/sheet/Sheet.vue +16 -0
- package/templates/starter/app/components/ui/sheet/SheetClose.vue +13 -0
- package/templates/starter/app/components/ui/sheet/SheetContent.vue +54 -0
- package/templates/starter/app/components/ui/sheet/SheetDescription.vue +23 -0
- package/templates/starter/app/components/ui/sheet/SheetOverlay.vue +22 -0
- package/templates/starter/app/components/ui/sheet/SheetTitle.vue +23 -0
- package/templates/starter/app/components/ui/sheet/SheetTrigger.vue +13 -0
- package/templates/starter/app/components/ui/sheet/index.ts +7 -0
- package/templates/starter/app/composables/usePageSeo.ts +50 -0
- package/templates/starter/app/composables/useSiteAppConfig.ts +79 -0
- package/templates/starter/app/error.vue +35 -0
- package/templates/starter/app/layouts/default.vue +23 -0
- package/templates/starter/app/lib/utils.ts +26 -0
- package/templates/starter/app/pages/[...slug].vue +36 -0
- package/templates/starter/app/pages/index.vue +24 -0
- package/templates/starter/app/pages/legal/[slug].vue +46 -0
- package/templates/starter/app/routes.ts +14 -0
- package/templates/starter/app/utils/telHref.ts +3 -0
- package/templates/starter/components.json +21 -0
- package/templates/starter/content/home.de.md +16 -0
- package/templates/starter/content/home.md +16 -0
- package/templates/starter/content/legal/1.privacy.de.md +28 -0
- package/templates/starter/content/legal/1.privacy.md +29 -0
- package/templates/starter/content/legal/2.terms.de.md +21 -0
- package/templates/starter/content/legal/2.terms.md +22 -0
- package/templates/starter/content/legal/3.imprint.de.md +16 -0
- package/templates/starter/content/legal/3.imprint.md +16 -0
- package/templates/starter/content/notices/1.welcome.de.md +4 -0
- package/templates/starter/content/notices/1.welcome.md +5 -0
- package/templates/starter/content/pages/1.about.de.md +20 -0
- package/templates/starter/content/pages/1.about.md +18 -0
- package/templates/starter/content/pages/2.contact.de.md +17 -0
- package/templates/starter/content/pages/2.contact.md +15 -0
- package/templates/starter/content/site.md +12 -0
- package/templates/starter/eslint.config.mjs +12 -0
- package/templates/starter/eslint.tailwind.mjs +33 -0
- package/templates/starter/ginko.config.ts +42 -0
- package/templates/starter/gitignore +7 -0
- package/templates/starter/i18n/de.json +6 -0
- package/templates/starter/i18n/en.json +6 -0
- package/templates/starter/i18n/site/de.json +39 -0
- package/templates/starter/i18n/site/en.json +39 -0
- package/templates/starter/modules/feature-messages.ts +19 -0
- package/templates/starter/modules/feeds/index.ts +22 -0
- package/templates/starter/modules/feeds/routes.ts +13 -0
- package/templates/starter/modules/page-paths/index.ts +26 -0
- package/templates/starter/modules/page-paths/paths.ts +48 -0
- package/templates/starter/nuxt.config.ts +27 -0
- package/templates/starter/package.json +55 -0
- package/templates/starter/pnpm-workspace.yaml +6 -0
- package/templates/starter/server/plugins/font-preload.ts +17 -0
- package/templates/starter/site-url.ts +21 -0
- package/templates/starter/tsconfig.json +9 -0
- package/templates/starter.json +11 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// Synced from templates/_features/ui/app/components/ui/button/index.ts by `pnpm templates sync`. Edit the source, not this copy.
|
|
2
|
+
import type { VariantProps } from 'class-variance-authority'
|
|
3
|
+
import { cva } from 'class-variance-authority'
|
|
4
|
+
|
|
5
|
+
export { default as Button } from './Button.vue'
|
|
6
|
+
|
|
7
|
+
// shadcn-vue's variant and size names, so shadcn examples and blocks work as written; the look comes from the tokens
|
|
8
|
+
// (tokens.css). Focus is the global :focus-visible ring. Sizes are at least 44px high on touch screens, the touch
|
|
9
|
+
// target of the design rules; `sm` and `icon-sm` are smaller only with a mouse (`pointer-coarse`).
|
|
10
|
+
export const buttonVariants = cva(
|
|
11
|
+
'inline-flex shrink-0 items-center justify-center gap-2 rounded-md font-medium whitespace-nowrap transition-[color,background-color,border-color] duration-150 ease-out select-none disabled:pointer-events-none disabled:opacity-60 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*=size-])]:size-5',
|
|
12
|
+
{
|
|
13
|
+
variants: {
|
|
14
|
+
variant: {
|
|
15
|
+
/** The main action. One per view. On paper an outline, as printers leave out backgrounds. */
|
|
16
|
+
default: 'bg-primary text-primary-foreground hover:bg-primary/90 print:border print:bg-transparent print:text-foreground',
|
|
17
|
+
/** A second action next to the main one. */
|
|
18
|
+
outline: 'border border-input text-foreground hover:bg-accent',
|
|
19
|
+
/** A quiet filled action, for example in a toolbar. */
|
|
20
|
+
secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80',
|
|
21
|
+
/** An action that deletes or cannot be undone. `text-background` keeps the contrast in both schemes. */
|
|
22
|
+
destructive: 'bg-destructive text-background hover:bg-destructive/90',
|
|
23
|
+
/** Icon buttons and quiet actions, for example in the header. */
|
|
24
|
+
ghost: 'text-foreground hover:bg-accent',
|
|
25
|
+
/** An action that reads as a link. */
|
|
26
|
+
link: 'text-primary underline underline-offset-4 hover:decoration-2',
|
|
27
|
+
},
|
|
28
|
+
size: {
|
|
29
|
+
default: 'h-11 px-5 text-small',
|
|
30
|
+
sm: 'h-9 px-3 text-small pointer-coarse:h-11',
|
|
31
|
+
lg: 'h-12 px-6 text-body',
|
|
32
|
+
icon: 'size-11',
|
|
33
|
+
'icon-sm': 'size-9 pointer-coarse:size-11',
|
|
34
|
+
'icon-lg': 'size-12',
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
compoundVariants: [{ variant: 'link', class: 'h-auto px-0' }],
|
|
38
|
+
defaultVariants: {
|
|
39
|
+
variant: 'default',
|
|
40
|
+
size: 'default',
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
)
|
|
44
|
+
export type ButtonVariants = VariantProps<typeof buttonVariants>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<!-- Synced from templates/_features/ui/app/components/ui/sheet/Sheet.vue by `pnpm templates sync`. Edit the source, not this copy. -->
|
|
2
|
+
<script setup lang="ts">
|
|
3
|
+
import type { DialogRootEmits, DialogRootProps } from 'reka-ui'
|
|
4
|
+
import { DialogRoot, useForwardPropsEmits } from 'reka-ui'
|
|
5
|
+
|
|
6
|
+
const props = defineProps<DialogRootProps>()
|
|
7
|
+
const emits = defineEmits<DialogRootEmits>()
|
|
8
|
+
|
|
9
|
+
const forwarded = useForwardPropsEmits(props, emits)
|
|
10
|
+
</script>
|
|
11
|
+
|
|
12
|
+
<template>
|
|
13
|
+
<DialogRoot v-slot="slotProps" data-slot="sheet" v-bind="forwarded">
|
|
14
|
+
<slot v-bind="slotProps" />
|
|
15
|
+
</DialogRoot>
|
|
16
|
+
</template>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<!-- Synced from templates/_features/ui/app/components/ui/sheet/SheetClose.vue by `pnpm templates sync`. Edit the source, not this copy. -->
|
|
2
|
+
<script setup lang="ts">
|
|
3
|
+
import type { DialogCloseProps } from 'reka-ui'
|
|
4
|
+
import { DialogClose } from 'reka-ui'
|
|
5
|
+
|
|
6
|
+
const props = defineProps<DialogCloseProps>()
|
|
7
|
+
</script>
|
|
8
|
+
|
|
9
|
+
<template>
|
|
10
|
+
<DialogClose data-slot="sheet-close" v-bind="props">
|
|
11
|
+
<slot />
|
|
12
|
+
</DialogClose>
|
|
13
|
+
</template>
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
<!-- Synced from templates/_features/ui/app/components/ui/sheet/SheetContent.vue by `pnpm templates sync`. Edit the source, not this copy. -->
|
|
2
|
+
<script setup lang="ts">
|
|
3
|
+
import type { DialogContentEmits, DialogContentProps } from 'reka-ui'
|
|
4
|
+
import type { HTMLAttributes } from 'vue'
|
|
5
|
+
import { X } from '@lucide/vue'
|
|
6
|
+
import { reactiveOmit } from '@vueuse/core'
|
|
7
|
+
import { DialogClose, DialogContent, DialogPortal, useForwardPropsEmits } from 'reka-ui'
|
|
8
|
+
import { cn } from '@/lib/utils'
|
|
9
|
+
import SheetOverlay from './SheetOverlay.vue'
|
|
10
|
+
|
|
11
|
+
// Trimmed from shadcn-vue: a panel from the inline start or end, so it opens from the right in right-to-left
|
|
12
|
+
// languages. Focus trap, Escape and focus return come from reka-ui. The close button's label is a prop, because
|
|
13
|
+
// this component has no texts of its own.
|
|
14
|
+
interface SheetContentProps extends DialogContentProps {
|
|
15
|
+
class?: HTMLAttributes['class']
|
|
16
|
+
side?: 'start' | 'end'
|
|
17
|
+
closeLabel?: string
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
defineOptions({ inheritAttrs: false })
|
|
21
|
+
|
|
22
|
+
const props = withDefaults(defineProps<SheetContentProps>(), {
|
|
23
|
+
side: 'start',
|
|
24
|
+
closeLabel: 'Close',
|
|
25
|
+
})
|
|
26
|
+
const emits = defineEmits<DialogContentEmits>()
|
|
27
|
+
|
|
28
|
+
const delegatedProps = reactiveOmit(props, 'class', 'side', 'closeLabel')
|
|
29
|
+
const forwarded = useForwardPropsEmits(delegatedProps, emits)
|
|
30
|
+
</script>
|
|
31
|
+
|
|
32
|
+
<template>
|
|
33
|
+
<DialogPortal>
|
|
34
|
+
<SheetOverlay />
|
|
35
|
+
<DialogContent
|
|
36
|
+
data-slot="sheet-content"
|
|
37
|
+
:class="cn(
|
|
38
|
+
'fixed inset-y-0 z-50 flex h-full w-11/12 max-w-sm flex-col gap-6 bg-background shadow-overlay data-[state=closed]:animate-out data-[state=closed]:duration-200 data-[state=open]:animate-in data-[state=open]:duration-300 data-[state=open]:ease-out',
|
|
39
|
+
side === 'start' && 'start-0 border-e data-[state=closed]:slide-out-to-start data-[state=open]:slide-in-from-start',
|
|
40
|
+
side === 'end' && 'end-0 border-s data-[state=closed]:slide-out-to-end data-[state=open]:slide-in-from-end',
|
|
41
|
+
props.class)"
|
|
42
|
+
v-bind="{ ...$attrs, ...forwarded }"
|
|
43
|
+
>
|
|
44
|
+
<slot />
|
|
45
|
+
|
|
46
|
+
<DialogClose
|
|
47
|
+
class="absolute end-3 top-3 inline-flex size-11 items-center justify-center rounded-md text-foreground transition-[color,background-color,border-color] duration-150 hover:bg-accent"
|
|
48
|
+
>
|
|
49
|
+
<X class="size-5" aria-hidden="true" />
|
|
50
|
+
<span class="sr-only">{{ closeLabel }}</span>
|
|
51
|
+
</DialogClose>
|
|
52
|
+
</DialogContent>
|
|
53
|
+
</DialogPortal>
|
|
54
|
+
</template>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
<!-- Synced from templates/_features/ui/app/components/ui/sheet/SheetDescription.vue by `pnpm templates sync`. Edit the source, not this copy. -->
|
|
2
|
+
<script setup lang="ts">
|
|
3
|
+
import type { DialogDescriptionProps } from 'reka-ui'
|
|
4
|
+
import type { HTMLAttributes } from 'vue'
|
|
5
|
+
import { reactiveOmit } from '@vueuse/core'
|
|
6
|
+
import { DialogDescription, useForwardProps } from 'reka-ui'
|
|
7
|
+
import { cn } from '@/lib/utils'
|
|
8
|
+
|
|
9
|
+
const props = defineProps<DialogDescriptionProps & { class?: HTMLAttributes['class'] }>()
|
|
10
|
+
|
|
11
|
+
const delegatedProps = reactiveOmit(props, 'class')
|
|
12
|
+
const forwardedProps = useForwardProps(delegatedProps)
|
|
13
|
+
</script>
|
|
14
|
+
|
|
15
|
+
<template>
|
|
16
|
+
<DialogDescription
|
|
17
|
+
data-slot="sheet-description"
|
|
18
|
+
v-bind="forwardedProps"
|
|
19
|
+
:class="cn('text-small text-muted-foreground', props.class)"
|
|
20
|
+
>
|
|
21
|
+
<slot />
|
|
22
|
+
</DialogDescription>
|
|
23
|
+
</template>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
<!-- Synced from templates/_features/ui/app/components/ui/sheet/SheetOverlay.vue by `pnpm templates sync`. Edit the source, not this copy. -->
|
|
2
|
+
<script setup lang="ts">
|
|
3
|
+
import type { DialogOverlayProps } from 'reka-ui'
|
|
4
|
+
import type { HTMLAttributes } from 'vue'
|
|
5
|
+
import { reactiveOmit } from '@vueuse/core'
|
|
6
|
+
import { DialogOverlay } from 'reka-ui'
|
|
7
|
+
import { cn } from '@/lib/utils'
|
|
8
|
+
|
|
9
|
+
const props = defineProps<DialogOverlayProps & { class?: HTMLAttributes['class'] }>()
|
|
10
|
+
|
|
11
|
+
const delegatedProps = reactiveOmit(props, 'class')
|
|
12
|
+
</script>
|
|
13
|
+
|
|
14
|
+
<template>
|
|
15
|
+
<DialogOverlay
|
|
16
|
+
data-slot="sheet-overlay"
|
|
17
|
+
v-bind="delegatedProps"
|
|
18
|
+
:class="cn('fixed inset-0 z-50 bg-scrim data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:animate-in data-[state=open]:fade-in-0', props.class)"
|
|
19
|
+
>
|
|
20
|
+
<slot />
|
|
21
|
+
</DialogOverlay>
|
|
22
|
+
</template>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
<!-- Synced from templates/_features/ui/app/components/ui/sheet/SheetTitle.vue by `pnpm templates sync`. Edit the source, not this copy. -->
|
|
2
|
+
<script setup lang="ts">
|
|
3
|
+
import type { DialogTitleProps } from 'reka-ui'
|
|
4
|
+
import type { HTMLAttributes } from 'vue'
|
|
5
|
+
import { reactiveOmit } from '@vueuse/core'
|
|
6
|
+
import { DialogTitle, useForwardProps } from 'reka-ui'
|
|
7
|
+
import { cn } from '@/lib/utils'
|
|
8
|
+
|
|
9
|
+
const props = defineProps<DialogTitleProps & { class?: HTMLAttributes['class'] }>()
|
|
10
|
+
|
|
11
|
+
const delegatedProps = reactiveOmit(props, 'class')
|
|
12
|
+
const forwardedProps = useForwardProps(delegatedProps)
|
|
13
|
+
</script>
|
|
14
|
+
|
|
15
|
+
<template>
|
|
16
|
+
<DialogTitle
|
|
17
|
+
data-slot="sheet-title"
|
|
18
|
+
v-bind="forwardedProps"
|
|
19
|
+
:class="cn('font-semibold', props.class)"
|
|
20
|
+
>
|
|
21
|
+
<slot />
|
|
22
|
+
</DialogTitle>
|
|
23
|
+
</template>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<!-- Synced from templates/_features/ui/app/components/ui/sheet/SheetTrigger.vue by `pnpm templates sync`. Edit the source, not this copy. -->
|
|
2
|
+
<script setup lang="ts">
|
|
3
|
+
import type { DialogTriggerProps } from 'reka-ui'
|
|
4
|
+
import { DialogTrigger } from 'reka-ui'
|
|
5
|
+
|
|
6
|
+
const props = defineProps<DialogTriggerProps>()
|
|
7
|
+
</script>
|
|
8
|
+
|
|
9
|
+
<template>
|
|
10
|
+
<DialogTrigger data-slot="sheet-trigger" v-bind="props">
|
|
11
|
+
<slot />
|
|
12
|
+
</DialogTrigger>
|
|
13
|
+
</template>
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// Synced from templates/_features/ui/app/components/ui/sheet/index.ts by `pnpm templates sync`. Edit the source, not this copy.
|
|
2
|
+
export { default as Sheet } from './Sheet.vue'
|
|
3
|
+
export { default as SheetClose } from './SheetClose.vue'
|
|
4
|
+
export { default as SheetContent } from './SheetContent.vue'
|
|
5
|
+
export { default as SheetDescription } from './SheetDescription.vue'
|
|
6
|
+
export { default as SheetTitle } from './SheetTitle.vue'
|
|
7
|
+
export { default as SheetTrigger } from './SheetTrigger.vue'
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
// Synced from templates/_features/blog/app/composables/useBlog.ts by `pnpm templates sync`. Edit the source, not this copy.
|
|
2
|
+
import { wordsOf } from '@lupinum/ginko'
|
|
3
|
+
|
|
4
|
+
/** A post as the blog's lists and pages show it: the entry plus its authors' names and roles from `people`. */
|
|
5
|
+
export interface BlogPost {
|
|
6
|
+
id: string
|
|
7
|
+
title: string
|
|
8
|
+
to: string
|
|
9
|
+
date: string
|
|
10
|
+
description?: string
|
|
11
|
+
image?: GinkoItem<'posts'>['data']['image']
|
|
12
|
+
tags: string[]
|
|
13
|
+
/** Reading time in whole minutes, at least 1; 0 when the text's length is unknown. */
|
|
14
|
+
minutes: number
|
|
15
|
+
/** `to` is the author's page when `people` has a route. */
|
|
16
|
+
authors: { id: string, name: string, role?: string, to?: string }[]
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/** Words a reader reads in a minute, for the reading time. */
|
|
20
|
+
const WORDS_PER_MINUTE = 200
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* The visible posts in the current language, newest first, with their authors (entries of `people`, by id). A draft
|
|
24
|
+
* (`draft: true` in its file) and a post dated after the build day are never among them: they stay out of the build.
|
|
25
|
+
*/
|
|
26
|
+
export function useBlogPosts() {
|
|
27
|
+
const posts = useGinko('posts')
|
|
28
|
+
const people = useGinko('people')
|
|
29
|
+
const locale = useGinkoLocale()
|
|
30
|
+
return computed<BlogPost[]>(() => {
|
|
31
|
+
const byId = new Map(people.value.items.map((person) => [person.id, person]))
|
|
32
|
+
return posts.value.items.map((post) => {
|
|
33
|
+
// The bundle carries the text's word count next to its reference, so a list needs no text to show the time.
|
|
34
|
+
const words = wordsOf(post.data.body) ?? 0
|
|
35
|
+
return {
|
|
36
|
+
id: post.id,
|
|
37
|
+
title: post.data.title,
|
|
38
|
+
to: post.urls?.[locale.value] ?? '',
|
|
39
|
+
date: post.data.date,
|
|
40
|
+
description: post.data.description,
|
|
41
|
+
image: post.data.image,
|
|
42
|
+
// A tag without letters or digits has no address (empty slug), so it is left out instead of breaking the route.
|
|
43
|
+
tags: (post.data.tags ?? []).map((row) => row.tag).filter((tag) => tagSlug(tag)),
|
|
44
|
+
minutes: words ? Math.max(1, Math.round(words / WORDS_PER_MINUTE)) : 0,
|
|
45
|
+
authors: (post.data.authors ?? []).flatMap((id) => {
|
|
46
|
+
const person = byId.get(id)
|
|
47
|
+
return person ? [{ id, name: person.data.name, role: person.data.role, to: person.urls?.[locale.value] }] : []
|
|
48
|
+
}),
|
|
49
|
+
}
|
|
50
|
+
})
|
|
51
|
+
})
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** The address word of a tag: "Street trees" → "street-trees", "Vögel" → "voegel". Tags are free text per language. */
|
|
55
|
+
export function tagSlug(tag: string) {
|
|
56
|
+
return tag
|
|
57
|
+
.replace(/[äöüÄÖÜß]/g, (c) => ({ ä: 'ae', ö: 'oe', ü: 'ue', Ä: 'ae', Ö: 'oe', Ü: 'ue', ß: 'ss' })[c] ?? c)
|
|
58
|
+
.normalize('NFKD')
|
|
59
|
+
.replace(/\p{M}/gu, '')
|
|
60
|
+
.toLowerCase()
|
|
61
|
+
.replace(/[^\p{L}\p{N}]+/gu, '-')
|
|
62
|
+
.replace(/^-+|-+$/g, '')
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** A tag as a visitor reads it: tags are free text and often lowercase in the files ("tips"), so the first letter is upper-cased. */
|
|
66
|
+
export function tagLabel(tag: string) {
|
|
67
|
+
return tag.charAt(0).toLocaleUpperCase() + tag.slice(1)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* The address of a tag's page (news/tags/[tag].vue) in the current language: `/news/tags/water`, or with the words
|
|
72
|
+
* of `segments` in app/routes.ts `/de/aktuelles/themen/wasser`. The page has no `pages` key, so the address comes from
|
|
73
|
+
* its route (ginko-i18n names the route of each language `<name>__<code>`).
|
|
74
|
+
*/
|
|
75
|
+
export function useTagPath() {
|
|
76
|
+
const router = useRouter()
|
|
77
|
+
const locale = useGinkoLocale()
|
|
78
|
+
return (tag: string) => router.resolve({ name: `news-tags-tag__${locale.value}`, params: { tag: tagSlug(tag) } }).path
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/** Every tag of the visible posts, most used first, with the number of posts and its page. */
|
|
82
|
+
export function useBlogTags() {
|
|
83
|
+
const posts = useBlogPosts()
|
|
84
|
+
const tagPath = useTagPath()
|
|
85
|
+
return computed(() => {
|
|
86
|
+
const tags = new Map<string, { name: string, slug: string, to: string, count: number }>()
|
|
87
|
+
for (const post of posts.value) {
|
|
88
|
+
for (const name of new Set(post.tags)) {
|
|
89
|
+
const slug = tagSlug(name)
|
|
90
|
+
const tag = tags.get(slug)
|
|
91
|
+
if (tag) tag.count++
|
|
92
|
+
else tags.set(slug, { name: tagLabel(name), slug, to: tagPath(name), count: 1 })
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return [...tags.values()].sort((a, b) => b.count - a.count || a.name.localeCompare(b.name, undefined, { numeric: true }))
|
|
96
|
+
})
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/** The path of the news feed of the current language: `<news page>/rss.xml`. */
|
|
100
|
+
export function useFeedPath() {
|
|
101
|
+
const path = useGinkoPath()
|
|
102
|
+
return computed(() => `${path('news')}/rss.xml`)
|
|
103
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// Synced from templates/_features/site/app/composables/usePageSeo.ts by `pnpm templates sync`. Edit the source, not this copy.
|
|
2
|
+
import { breadcrumbJsonLd } from '@lupinum/ginko'
|
|
3
|
+
import { siteJsonLd } from '@lupinum/ginko/basics'
|
|
4
|
+
|
|
5
|
+
export interface PageSeoInput {
|
|
6
|
+
title?: string
|
|
7
|
+
description?: string
|
|
8
|
+
image?: GinkoSeoInput['image']
|
|
9
|
+
/** The home page: the organisation from the `site` brick instead of WebPage and BreadcrumbList. */
|
|
10
|
+
home?: boolean
|
|
11
|
+
/** Home page: more properties of the organisation, which win over those from content/site.md (a subtype such as
|
|
12
|
+
* `Restaurant`, opening hours, a menu). */
|
|
13
|
+
organization?: Record<string, unknown>
|
|
14
|
+
/** Keeps the page out of search engines (a print version). */
|
|
15
|
+
noindex?: boolean
|
|
16
|
+
/** More JSON-LD for this page, for example a FAQPage. */
|
|
17
|
+
jsonLd?: Record<string, unknown>[]
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Title, description, share card and JSON-LD of a page (useGinkoSeo). The home page describes the organisation
|
|
22
|
+
* (Organization, LocalBusiness or NGO from app.config.ts, with address and contact from content/site.md and the
|
|
23
|
+
* country from ginko.config.ts); every other page is a WebPage with a BreadcrumbList from home to itself.
|
|
24
|
+
*/
|
|
25
|
+
export function usePageSeo(input: () => PageSeoInput) {
|
|
26
|
+
const site = useGinko('site')
|
|
27
|
+
const config = useSiteAppConfig()
|
|
28
|
+
const { name, url } = useGinkoSite()
|
|
29
|
+
const route = useRoute()
|
|
30
|
+
const path = useGinkoPath()
|
|
31
|
+
const { t, language } = useI18n('site')
|
|
32
|
+
const absolute = (p: string) => new URL(p, url).href
|
|
33
|
+
useGinkoSeo(() => {
|
|
34
|
+
const page = input()
|
|
35
|
+
const own = page.jsonLd ?? []
|
|
36
|
+
if (page.home) {
|
|
37
|
+
const organization = siteJsonLd(site.value.data, {
|
|
38
|
+
name,
|
|
39
|
+
url,
|
|
40
|
+
type: config.organization,
|
|
41
|
+
logo: config.logo ? absolute(config.logo.src) : undefined,
|
|
42
|
+
sameAs: config.socials.map((social) => social.url),
|
|
43
|
+
})
|
|
44
|
+
return { title: page.title, description: page.description, image: page.image, noindex: page.noindex, jsonLd: [{ ...organization, ...page.organization }, ...own] }
|
|
45
|
+
}
|
|
46
|
+
const webPage = { '@context': 'https://schema.org', '@type': 'WebPage', name: page.title, url: absolute(route.path), description: page.description, inLanguage: language.value }
|
|
47
|
+
const breadcrumbs = breadcrumbJsonLd([{ title: t('home'), path: path('home') }, { title: page.title ?? name, path: route.path }], url)
|
|
48
|
+
return { title: page.title, description: page.description, image: page.image, noindex: page.noindex, jsonLd: [webPage, breadcrumbs, ...own] }
|
|
49
|
+
})
|
|
50
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
// Synced from templates/_features/site/app/composables/useSiteAppConfig.ts by `pnpm templates sync`. Edit the source, not this copy.
|
|
2
|
+
/** A navigation item: a collection entry by id (`pages/about`, title and address from the content), a page of
|
|
3
|
+
* `pages` in ginko.config.ts with its label per language, or an address on another site (`url`, for example the
|
|
4
|
+
* sign-in of an app) with its label per language. */
|
|
5
|
+
export type SiteNavItem = { entry: string } | { page: string, label: Record<string, string> } | { url: string, label: Record<string, string> }
|
|
6
|
+
|
|
7
|
+
/** `site` in app/app.config.ts: the brand and navigation of the template. Name, address and contact come from
|
|
8
|
+
* ginko.config.ts (`name`) and the `site` brick (content/site.md). */
|
|
9
|
+
export interface SiteAppConfig {
|
|
10
|
+
/** Shown instead of the name in the header on phones. Default: the name from ginko.config.ts. */
|
|
11
|
+
shortName?: string
|
|
12
|
+
/** A logo file in public/ with its size in pixels. Without it, the header shows the name. */
|
|
13
|
+
logo?: { src: string, width: number, height: number }
|
|
14
|
+
/** One line under the name in the footer, per language code: `{ en: '…', de: '…' }`. A language without one shows none. */
|
|
15
|
+
tagline?: Record<string, string>
|
|
16
|
+
/** The schema.org type of the organisation on the home page. */
|
|
17
|
+
organization: 'Organization' | 'LocalBusiness' | 'NGO'
|
|
18
|
+
/** The header navigation: at most 6 items. The footer repeats it. */
|
|
19
|
+
nav: SiteNavItem[]
|
|
20
|
+
/** More links in the footer, for example a newsletter page. */
|
|
21
|
+
footer: SiteNavItem[]
|
|
22
|
+
/** Profiles elsewhere, as text links in the footer (no third-party icons or scripts). */
|
|
23
|
+
socials: { label: string, url: string }[]
|
|
24
|
+
/** Whether the site's prices include VAT: `excluded` for net prices to businesses ("Price (plus VAT)"), `included`
|
|
25
|
+
* for prices to consumers. Price labels and the price's JSON-LD say so. Default: no VAT note. */
|
|
26
|
+
vat?: 'included' | 'excluded'
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** The collection keys useGinkoNav takes. */
|
|
30
|
+
type NavBricks = Extract<Parameters<typeof useGinkoNav>[0], readonly unknown[]>
|
|
31
|
+
|
|
32
|
+
/** The `site` part of app.config.ts. */
|
|
33
|
+
export function useSiteAppConfig(): SiteAppConfig {
|
|
34
|
+
return useAppConfig().site
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** Entries already reported as missing, so the log names each one once. */
|
|
38
|
+
const reported = new Set<string>()
|
|
39
|
+
const overLimit = '\0over-limit'
|
|
40
|
+
|
|
41
|
+
/** The items of a navigation list with their label and path in the current language. An entry that does not exist
|
|
42
|
+
* in this language (untranslated or removed) is left out; one missing in the main language is also reported in the
|
|
43
|
+
* dev server and build log, because it is a typo or a deleted file. With `limit`, a longer list is reported once
|
|
44
|
+
* too (the header holds 6 links; the rest stay in the menu). */
|
|
45
|
+
export function useSiteLinks(items: () => SiteNavItem[], limit?: number) {
|
|
46
|
+
const path = useGinkoPath()
|
|
47
|
+
const locale = useGinkoLocale()
|
|
48
|
+
const { mainLocale } = useGinkoSite()
|
|
49
|
+
// useGinkoNav takes the site's collection keys; the ids in app.config.ts are plain strings (`pages/about`), and a
|
|
50
|
+
// key that is no collection of this site is skipped by it.
|
|
51
|
+
const tree = useGinkoNav(() => [...new Set(items().flatMap((item) => ('entry' in item ? [item.entry.split('/')[0]!] : [])))] as NavBricks)
|
|
52
|
+
return computed(() => {
|
|
53
|
+
if (import.meta.server && limit && !reported.has(overLimit) && items().length > limit) {
|
|
54
|
+
reported.add(overLimit)
|
|
55
|
+
console.warn(`[site] app/app.config.ts has ${items().length} navigation entries; the header holds ${limit}, so the menu stays in the sheet.`)
|
|
56
|
+
}
|
|
57
|
+
const byId = new Map<string, { title: string, path: string }>()
|
|
58
|
+
const walk = (nodes: typeof tree.value) => nodes.forEach((node) => {
|
|
59
|
+
if (node.id) byId.set(node.id, node)
|
|
60
|
+
walk(node.children)
|
|
61
|
+
})
|
|
62
|
+
walk(tree.value)
|
|
63
|
+
return items().flatMap((item) => {
|
|
64
|
+
if ('entry' in item) {
|
|
65
|
+
const node = byId.get(item.entry)
|
|
66
|
+
if (node) return [{ key: item.entry, label: node.title, to: node.path }]
|
|
67
|
+
// An empty tree is content not loaded yet, not a missing entry.
|
|
68
|
+
if (import.meta.server && locale.value === mainLocale && tree.value.length > 0 && !reported.has(item.entry)) {
|
|
69
|
+
reported.add(item.entry)
|
|
70
|
+
console.warn(`[site] The navigation entry “${item.entry}” in app/app.config.ts matches no file in content/, so it is left out. An id is the folder and the file name without number: content/pages/1.about.md is pages/about.`)
|
|
71
|
+
}
|
|
72
|
+
return []
|
|
73
|
+
}
|
|
74
|
+
const label = item.label[locale.value] ?? item.label[mainLocale]
|
|
75
|
+
if (!label) return []
|
|
76
|
+
return 'url' in item ? [{ key: item.url, label, to: item.url }] : [{ key: item.page, label, to: path(item.page as GinkoPageKey) }]
|
|
77
|
+
})
|
|
78
|
+
})
|
|
79
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
<!-- Synced from templates/_features/site/app/error.vue by `pnpm templates sync`. Edit the source, not this copy. -->
|
|
2
|
+
<script setup lang="ts">
|
|
3
|
+
import type { NuxtError } from '#app'
|
|
4
|
+
|
|
5
|
+
// 404 and other errors, in the site's layout and language, never indexed. The way out is the home page.
|
|
6
|
+
const props = defineProps<{ error: NuxtError }>()
|
|
7
|
+
const { t } = useI18n('site')
|
|
8
|
+
const path = useGinkoPath()
|
|
9
|
+
const notFound = computed(() => props.error.statusCode === 404)
|
|
10
|
+
const title = computed(() => (notFound.value ? t('error.notFound') : t('error.failed')))
|
|
11
|
+
// The title through seo.titleTemplate of ginko.config.ts, like every other page.
|
|
12
|
+
useGinkoSeo(() => ({ title: title.value, noindex: true }))
|
|
13
|
+
|
|
14
|
+
/** Leaves the error state, so the next page renders normally. */
|
|
15
|
+
function home() {
|
|
16
|
+
clearError({ redirect: path('home') })
|
|
17
|
+
}
|
|
18
|
+
</script>
|
|
19
|
+
|
|
20
|
+
<template>
|
|
21
|
+
<NuxtLayout>
|
|
22
|
+
<div class="mx-auto max-w-page px-gutter pt-12 md:pt-20">
|
|
23
|
+
<div class="flex max-w-3xl flex-col gap-5">
|
|
24
|
+
<p class="text-small font-medium text-muted-foreground tabular-nums">{{ t('error.code', { code: String(error.statusCode) }) }}</p>
|
|
25
|
+
<h1 class="text-h1">{{ title }}</h1>
|
|
26
|
+
<p class="text-lead text-muted-foreground">{{ notFound ? t('error.notFoundText') : t('error.failedText') }}</p>
|
|
27
|
+
<div class="mt-2">
|
|
28
|
+
<Button as-child size="lg">
|
|
29
|
+
<a :href="path('home')" @click.prevent="home">{{ t('error.home') }}</a>
|
|
30
|
+
</Button>
|
|
31
|
+
</div>
|
|
32
|
+
</div>
|
|
33
|
+
</div>
|
|
34
|
+
</NuxtLayout>
|
|
35
|
+
</template>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
<!-- Synced from templates/_features/site/app/layouts/default.vue by `pnpm templates sync`. Edit the source, not this copy. -->
|
|
2
|
+
<script setup lang="ts">
|
|
3
|
+
import { ConfigProvider } from 'reka-ui'
|
|
4
|
+
|
|
5
|
+
// Every page: skip link, notices, header, content, footer. Reka's ConfigProvider gives its parts (sheet, menus,
|
|
6
|
+
// accordion) the text direction of the language, so arrows and the sheet's side follow right-to-left languages.
|
|
7
|
+
const { locale, locales } = useI18n()
|
|
8
|
+
const dir = computed(() => locales.find((l) => l.code === locale.value)?.dir ?? 'ltr')
|
|
9
|
+
</script>
|
|
10
|
+
|
|
11
|
+
<template>
|
|
12
|
+
<ConfigProvider :dir="dir">
|
|
13
|
+
<div class="flex min-h-dvh flex-col">
|
|
14
|
+
<SiteSkipLink />
|
|
15
|
+
<SiteNotice />
|
|
16
|
+
<SiteHeader />
|
|
17
|
+
<main id="main" tabindex="-1" class="flex-1 focus-visible:outline-none">
|
|
18
|
+
<slot />
|
|
19
|
+
</main>
|
|
20
|
+
<SiteFooter />
|
|
21
|
+
</div>
|
|
22
|
+
</ConfigProvider>
|
|
23
|
+
</template>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// Synced from templates/_features/ui/app/lib/utils.ts by `pnpm templates sync`. Edit the source, not this copy.
|
|
2
|
+
import type { ClassValue } from 'clsx'
|
|
3
|
+
import { clsx } from 'clsx'
|
|
4
|
+
import { extendTailwindMerge } from 'tailwind-merge'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* tailwind-merge, told about the theme of tokens.css. Without it, `text-small` reads as a colour and `p-gutter` or
|
|
8
|
+
* `max-w-page` as unknown, so a conflicting class would not replace the component's own.
|
|
9
|
+
*/
|
|
10
|
+
const twMerge = extendTailwindMerge({
|
|
11
|
+
extend: {
|
|
12
|
+
theme: {
|
|
13
|
+
text: ['h1', 'h2', 'h3', 'lead', 'body', 'small', 'xs'],
|
|
14
|
+
font: ['display'],
|
|
15
|
+
radius: ['block'],
|
|
16
|
+
shadow: ['overlay'],
|
|
17
|
+
spacing: ['section', 'gutter'],
|
|
18
|
+
container: ['page', 'prose'],
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
/** Joins class names (strings, arrays, `{ class: condition }`); a later class wins over a conflicting earlier one. */
|
|
24
|
+
export function cn(...inputs: ClassValue[]) {
|
|
25
|
+
return twMerge(clsx(inputs))
|
|
26
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { personJsonLd } from '@lupinum/ginko/basics'
|
|
3
|
+
import { ArrowRight } from '@lucide/vue'
|
|
4
|
+
|
|
5
|
+
// One author: initials, name, role, short bio, and their posts, newest first, with Person JSON-LD. The address comes
|
|
6
|
+
// from the `people` route in ginko.config.ts (/about/<slug>); an unknown author is a 404.
|
|
7
|
+
const route = useRoute()
|
|
8
|
+
const person = useGinkoEntry('people', () => route.params.slug)
|
|
9
|
+
const posts = useBlogPosts()
|
|
10
|
+
const path = useGinkoPath()
|
|
11
|
+
const { url, name } = useGinkoSite()
|
|
12
|
+
const { t } = useI18n()
|
|
13
|
+
const written = computed(() => posts.value.filter((post) => post.authors.some((author) => author.id === person.value.id)))
|
|
14
|
+
usePageSeo(() => ({
|
|
15
|
+
title: person.value.data.name,
|
|
16
|
+
description: person.value.data.bio ?? person.value.data.role,
|
|
17
|
+
jsonLd: [personJsonLd({
|
|
18
|
+
name: person.value.data.name,
|
|
19
|
+
role: person.value.data.role,
|
|
20
|
+
bio: person.value.data.bio,
|
|
21
|
+
url: new URL(person.value.url, url).href,
|
|
22
|
+
worksFor: { name, url },
|
|
23
|
+
})],
|
|
24
|
+
}))
|
|
25
|
+
</script>
|
|
26
|
+
|
|
27
|
+
<template>
|
|
28
|
+
<article>
|
|
29
|
+
<header class="mx-auto max-w-page px-gutter pt-12 pb-8 md:pt-20 md:pb-12">
|
|
30
|
+
<div class="flex max-w-3xl flex-col gap-5">
|
|
31
|
+
<InitialsAvatar :name="person.data.name" size="lg" />
|
|
32
|
+
<h1 class="text-h1">{{ person.data.name }}</h1>
|
|
33
|
+
<p v-if="person.data.role" class="text-lead text-muted-foreground">{{ person.data.role }}</p>
|
|
34
|
+
<p v-if="person.data.bio" class="max-w-prose">{{ person.data.bio }}</p>
|
|
35
|
+
</div>
|
|
36
|
+
</header>
|
|
37
|
+
<section aria-labelledby="author-posts" class="mx-auto max-w-page px-gutter">
|
|
38
|
+
<div class="max-w-4xl">
|
|
39
|
+
<h2 id="author-posts" class="pb-2 text-h3">{{ t('author.posts', { name: person.data.name }) }}</h2>
|
|
40
|
+
<BlogPostList v-if="written.length" :items="written" heading-level="h3" />
|
|
41
|
+
<p v-else class="border-t py-8 text-muted-foreground">{{ t('author.none') }}</p>
|
|
42
|
+
<NuxtLink :to="path('news')" class="mt-6 inline-flex min-h-11 items-center gap-2 font-medium text-primary underline-offset-4 hover:underline">
|
|
43
|
+
{{ t('blog.all') }}<ArrowRight class="size-4 rtl:-scale-x-100" aria-hidden="true" />
|
|
44
|
+
</NuxtLink>
|
|
45
|
+
</div>
|
|
46
|
+
</section>
|
|
47
|
+
</article>
|
|
48
|
+
</template>
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { ArrowRight } from '@lucide/vue'
|
|
3
|
+
|
|
4
|
+
// The home page answers "what is new?" in the first screen: one line on what the blog is (content/home.md), then the
|
|
5
|
+
// newest post with its photo, date, reading time and authors. Below: the next posts, the topics and the two writers.
|
|
6
|
+
// The feed is in the footer of every page. A section whose list is empty is left out.
|
|
7
|
+
const home = useGinko('home')
|
|
8
|
+
const posts = useBlogPosts()
|
|
9
|
+
const tags = useBlogTags()
|
|
10
|
+
const people = useGinko('people')
|
|
11
|
+
const path = useGinkoPath()
|
|
12
|
+
const locale = useGinkoLocale()
|
|
13
|
+
const { t } = useI18n()
|
|
14
|
+
const newest = computed(() => posts.value[0])
|
|
15
|
+
const more = computed(() => posts.value.slice(1, 5))
|
|
16
|
+
usePageSeo(() => ({ home: true, description: home.value.data.lead }))
|
|
17
|
+
</script>
|
|
18
|
+
|
|
19
|
+
<template>
|
|
20
|
+
<div>
|
|
21
|
+
<BlockHero :title="home.data.title" :lead="home.data.lead" />
|
|
22
|
+
|
|
23
|
+
<div class="mx-auto max-w-page px-gutter pt-12 md:pt-16">
|
|
24
|
+
<HomeLatestPost v-if="newest" :post="newest" />
|
|
25
|
+
<BlockEmpty v-else :title="t('blog.empty')" path="content/posts/" />
|
|
26
|
+
</div>
|
|
27
|
+
|
|
28
|
+
<BlockSection v-if="more.length" :title="t('home.more')">
|
|
29
|
+
<BlogPostList :items="more" heading-level="h3" />
|
|
30
|
+
<NuxtLink :to="path('news')" class="mt-6 inline-flex min-h-11 items-center gap-2 font-medium text-primary underline-offset-4 hover:underline">
|
|
31
|
+
{{ t('blog.all') }}<ArrowRight class="size-4 rtl:-scale-x-100" aria-hidden="true" />
|
|
32
|
+
</NuxtLink>
|
|
33
|
+
</BlockSection>
|
|
34
|
+
|
|
35
|
+
<BlockSection v-if="tags.length" :title="t('blog.tags')">
|
|
36
|
+
<BlogTagList :tags="tags" />
|
|
37
|
+
</BlockSection>
|
|
38
|
+
|
|
39
|
+
<BlockSection v-if="people.items.length" :title="t('home.authors')">
|
|
40
|
+
<ul class="grid gap-x-10 gap-y-8 sm:grid-cols-2">
|
|
41
|
+
<li v-for="person in people.items" :key="person.id" class="flex items-start gap-4">
|
|
42
|
+
<InitialsAvatar :name="person.data.name" />
|
|
43
|
+
<div class="flex flex-col gap-1">
|
|
44
|
+
<h3 class="font-medium">
|
|
45
|
+
<NuxtLink v-if="person.urls?.[locale]" :to="person.urls[locale]" class="underline-offset-4 hover:underline">{{ person.data.name }}</NuxtLink>
|
|
46
|
+
<template v-else>{{ person.data.name }}</template>
|
|
47
|
+
</h3>
|
|
48
|
+
<p v-if="person.data.role" class="text-small text-muted-foreground">{{ person.data.role }}</p>
|
|
49
|
+
</div>
|
|
50
|
+
</li>
|
|
51
|
+
</ul>
|
|
52
|
+
</BlockSection>
|
|
53
|
+
</div>
|
|
54
|
+
</template>
|