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,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,46 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { ExternalLink, Mail, Phone } from '@lucide/vue'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* How to book, the same on the home page, the contact page and every treatment page, always in this order: call (the
|
|
6
|
+
* number on the button, the phone hours right under it), email, and "Book online" when content/visit.md names a booking
|
|
7
|
+
* page. Each shows only when it exists; the first one is the main action. `subject`: the email's subject (a treatment
|
|
8
|
+
* page); `email`, `phone`: a person's own, else the practice's from content/site.md.
|
|
9
|
+
*/
|
|
10
|
+
const props = defineProps<{ subject?: string, email?: string, phone?: string }>()
|
|
11
|
+
const { contact, visit, booking } = useVisit()
|
|
12
|
+
const { t } = useI18n()
|
|
13
|
+
const langOf = useGinkoLang()
|
|
14
|
+
|
|
15
|
+
const phone = computed(() => props.phone || contact.value.phone)
|
|
16
|
+
const email = computed(() => props.email || contact.value.email)
|
|
17
|
+
const actions = computed(() => {
|
|
18
|
+
const call = phone.value ? { key: 'call', href: telHref(phone.value), label: t('visit.call', { phone: phone.value }), icon: Phone } : undefined
|
|
19
|
+
const mail = email.value
|
|
20
|
+
? { key: 'email', href: `mailto:${email.value}${props.subject ? `?subject=${encodeURIComponent(props.subject)}` : ''}`, label: t('visit.email'), icon: Mail }
|
|
21
|
+
: undefined
|
|
22
|
+
const online = booking.value ? { key: 'booking', href: booking.value, label: t('visit.bookOnline'), icon: ExternalLink } : undefined
|
|
23
|
+
return [call, mail, online].filter((action) => action !== undefined)
|
|
24
|
+
})
|
|
25
|
+
// "Mon–Fri 08:00–12:00, Mon–Thu also 14:00–17:00": each part stays on one line, so a day range never breaks at its dash.
|
|
26
|
+
const phoneHours = computed(() => visit.value.data.phoneHours?.split(/,\s*/).filter(Boolean) ?? [])
|
|
27
|
+
</script>
|
|
28
|
+
|
|
29
|
+
<template>
|
|
30
|
+
<div v-if="actions.length" class="flex flex-wrap gap-3">
|
|
31
|
+
<template v-for="(action, i) in actions" :key="action.key">
|
|
32
|
+
<Button as-child size="lg" :variant="i === 0 ? 'default' : 'outline'" class="max-sm:w-full">
|
|
33
|
+
<a :href="action.href" :rel="action.key === 'booking' ? 'noopener' : undefined">
|
|
34
|
+
<component :is="action.icon" aria-hidden="true" />{{ action.label }}
|
|
35
|
+
</a>
|
|
36
|
+
</Button>
|
|
37
|
+
<!-- Under the call button on phones; under the row of buttons from sm. -->
|
|
38
|
+
<p v-if="action.key === 'call' && phoneHours.length" class="basis-full text-small tabular-nums sm:order-last">
|
|
39
|
+
{{ t('visit.phoneHours') }}
|
|
40
|
+
<span :lang="langOf(visit, 'phoneHours')">
|
|
41
|
+
<template v-for="(part, j) in phoneHours" :key="part"><span class="whitespace-nowrap">{{ part }}</span>{{ j < phoneHours.length - 1 ? ', ' : '' }}</template>
|
|
42
|
+
</span>
|
|
43
|
+
</p>
|
|
44
|
+
</template>
|
|
45
|
+
</div>
|
|
46
|
+
</template>
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
// Synced from templates/_features/hours/app/composables/useHours.ts by `pnpm templates sync`. Edit the source, not this copy.
|
|
2
|
+
import {
|
|
3
|
+
calendarOfCountry, hoursLine, hoursOn, upcomingClosures, upcomingPlans, weekFor,
|
|
4
|
+
type DayHours, type HourPlan, type HoursContext, type HoursData, type Weekday,
|
|
5
|
+
} from '@lupinum/ginko/basics'
|
|
6
|
+
|
|
7
|
+
/** The days of the week in storage order. */
|
|
8
|
+
const KEYS: Weekday[] = ['mo', 'tu', 'we', 'th', 'fr', 'sa', 'su']
|
|
9
|
+
/** The owner's choices for public holidays (`HolidaySetting`). */
|
|
10
|
+
const HOLIDAY_SETTINGS = ['sunday', 'closed', 'normal'] as const
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* The opening hours of the site, read once per component: the `hours` single and the `hourPlans` entries, shaped for
|
|
14
|
+
* the rules of `@lupinum/ginko/basics`, with the site's country for public holidays. `now` is the time of the server's
|
|
15
|
+
* render, carried to the browser, so both show the same state; HoursToday moves it on every minute.
|
|
16
|
+
*/
|
|
17
|
+
export function useHours() {
|
|
18
|
+
const hours = useGinko('hours')
|
|
19
|
+
const hourPlans = useGinko('hourPlans')
|
|
20
|
+
const today = useGinkoToday()
|
|
21
|
+
const locale = useGinkoLocale()
|
|
22
|
+
const { timeZone } = useGinkoSite()
|
|
23
|
+
// `country` of ginko.config.ts (ISO 3166-1, '' when unset): its public holidays count, as in the Studio.
|
|
24
|
+
const country: string = useRuntimeConfig().public.ginko.country
|
|
25
|
+
const now = useState('hours:now', () => Date.now())
|
|
26
|
+
const { firstDay } = useGinkoWeek()
|
|
27
|
+
|
|
28
|
+
const data = computed<HoursData>(() => {
|
|
29
|
+
const { week, exceptions, closedOn, closedNote, holidays } = hours.value.data
|
|
30
|
+
return {
|
|
31
|
+
week: week.map((day) => ({ ...day, day: String(day.day), closed: day.closed === true })),
|
|
32
|
+
exceptions: exceptions.map((e) => ({ ...e, reason: e.reason ?? '', closed: e.closed === true })),
|
|
33
|
+
closedOn: closedOn ?? undefined,
|
|
34
|
+
closedNote: closedNote ?? undefined,
|
|
35
|
+
holidays: HOLIDAY_SETTINGS.find((setting) => setting === holidays),
|
|
36
|
+
}
|
|
37
|
+
})
|
|
38
|
+
const plans = computed<HourPlan[]>(() => hourPlans.value.items.map((plan) => ({
|
|
39
|
+
_id: plan.id,
|
|
40
|
+
label: plan.data.label,
|
|
41
|
+
from: plan.data.from,
|
|
42
|
+
to: plan.data.to ?? undefined,
|
|
43
|
+
yearly: plan.data.yearly === true,
|
|
44
|
+
week: plan.data.week.map((day) => ({ ...day, day: String(day.day), closed: day.closed === true })),
|
|
45
|
+
})))
|
|
46
|
+
const ctx = computed<HoursContext>(() => ({ hours: data.value, plans: plans.value, country }))
|
|
47
|
+
|
|
48
|
+
const line = computed(() => hoursLine(data.value, { timeZone, now: new Date(now.value), plans: plans.value, holidays: calendarOfCountry(country) ?? 'none' }))
|
|
49
|
+
const yesterday = computed(() => {
|
|
50
|
+
const rule = hoursOn(ctx.value, plusDays(today.value, -1))
|
|
51
|
+
return rule.closed ? [] : rule.times
|
|
52
|
+
})
|
|
53
|
+
const state = computed(() => hoursNow(line.value, clockIn(timeZone, now.value), locale.value, yesterday.value))
|
|
54
|
+
/** Today's opening spans (empty when closed). */
|
|
55
|
+
const todayRule = computed(() => hoursOn(ctx.value, today.value))
|
|
56
|
+
/** The next day after today on which the place opens, within two weeks, with its first opening time. */
|
|
57
|
+
const nextOpen = computed(() => {
|
|
58
|
+
for (let i = 1; i <= 14; i++) {
|
|
59
|
+
const date = plusDays(today.value, i)
|
|
60
|
+
const rule = hoursOn(ctx.value, date)
|
|
61
|
+
if (!rule.closed && rule.times[0]) return { date, from: rule.times[0].from }
|
|
62
|
+
}
|
|
63
|
+
return undefined
|
|
64
|
+
})
|
|
65
|
+
/** The week that applies today (a running season replaces the usual week), in the order of the site's week. */
|
|
66
|
+
const week = computed(() => {
|
|
67
|
+
const { week, plan } = weekFor(ctx.value, today.value)
|
|
68
|
+
const keys = [...KEYS.slice(firstDay - 1), ...KEYS.slice(0, firstDay - 1)]
|
|
69
|
+
return { plan, days: keys.map((key) => week.find((d) => d.day === key) ?? { day: key, closed: true } satisfies DayHours) }
|
|
70
|
+
})
|
|
71
|
+
/** Seasons and new hours that start within 120 days. */
|
|
72
|
+
const comingPlans = computed(() => upcomingPlans(plans.value, today.value, 120))
|
|
73
|
+
/** Closures that run on past today (a holiday that started) and those that start within 90 days (the owner's, a
|
|
74
|
+
* day set as closed, closing public holidays), the next first. */
|
|
75
|
+
const closures = computed(() => [
|
|
76
|
+
...data.value.exceptions.filter((e) => e.closed && e.when.from <= today.value && e.when.to > today.value),
|
|
77
|
+
...upcomingClosures(ctx.value, today.value, 90),
|
|
78
|
+
])
|
|
79
|
+
|
|
80
|
+
return { hours, ctx, now, today, state, todayRule, nextOpen, week, comingPlans, closures }
|
|
81
|
+
}
|
|
@@ -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,93 @@
|
|
|
1
|
+
// Synced from templates/_features/services/app/composables/useServices.ts by `pnpm templates sync`. Edit the source, not this copy.
|
|
2
|
+
import { formatMoney, type ImageValue, type Money } from '@lupinum/ginko'
|
|
3
|
+
import { offerJsonLd } from '@lupinum/ginko/basics'
|
|
4
|
+
import type { Card } from '~/components/block/Cards.vue'
|
|
5
|
+
|
|
6
|
+
/** What the services feature reads of an entry of the `services` brick (app/bricks/services.ts). */
|
|
7
|
+
export interface ServiceFacts {
|
|
8
|
+
title: string
|
|
9
|
+
/** `price` (a fixed price) or `onRequest`; a value the brick no longer offers counts as on request. */
|
|
10
|
+
pricing: string
|
|
11
|
+
price?: Money | null
|
|
12
|
+
duration?: number | null
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Texts of a service in the page's language: its price ("€390", "€12.50") or "On request", the label of the price
|
|
17
|
+
* (with "plus VAT" or "incl. VAT" from `vat` in app.config.ts), its duration ("45 minutes", "90 minutes", "2 hours"),
|
|
18
|
+
* and the main action: "Ask for a date" for a fixed price, the enquiry for one on request. A fixed price always has
|
|
19
|
+
* its amount: the brick refuses `pricing: price` without one.
|
|
20
|
+
*/
|
|
21
|
+
export function useServiceText() {
|
|
22
|
+
const { t, format, language } = useI18n('services')
|
|
23
|
+
const { vat } = useSiteAppConfig()
|
|
24
|
+
const amount = (service: ServiceFacts) => (service.pricing === 'price' ? service.price ?? undefined : undefined)
|
|
25
|
+
const price = (service: ServiceFacts) => {
|
|
26
|
+
const money = amount(service)
|
|
27
|
+
return money ? formatMoney(money, language.value, { wholeWithoutMinor: true }) : t('onRequest')
|
|
28
|
+
}
|
|
29
|
+
/** The label of the price: with the VAT note for a real price, plain "Price" when it is on request. */
|
|
30
|
+
const priceLabel = (service: ServiceFacts) => (!amount(service) ? t('price') : vat === 'excluded' ? t('priceNet') : vat === 'included' ? t('priceGross') : t('price'))
|
|
31
|
+
const duration = (service: ServiceFacts) => {
|
|
32
|
+
const minutes = service.duration
|
|
33
|
+
if (!minutes) return undefined
|
|
34
|
+
return minutes >= 60 && minutes % 60 === 0
|
|
35
|
+
? format.number(minutes / 60, { style: 'unit', unit: 'hour', unitDisplay: 'long' })
|
|
36
|
+
: format.number(minutes, { style: 'unit', unit: 'minute', unitDisplay: 'long' })
|
|
37
|
+
}
|
|
38
|
+
/** Price and duration in one line: "€390 · 2 hours". */
|
|
39
|
+
const meta = (service: ServiceFacts) => [price(service), duration(service)].filter(Boolean).join(' · ')
|
|
40
|
+
/** The label and email subject of the main action. */
|
|
41
|
+
const action = (service: ServiceFacts) => (amount(service)
|
|
42
|
+
? { label: t('book'), subject: t('bookSubject', { title: service.title }) }
|
|
43
|
+
: { label: t('enquire'), subject: t('subject', { title: service.title }) })
|
|
44
|
+
return { price, priceLabel, duration, meta, action }
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** The services in their order as cards (BlockCards): price and duration above the title, the summary, the photo. */
|
|
48
|
+
export function useServiceCards(limit?: () => number | undefined) {
|
|
49
|
+
const services = useGinko('services')
|
|
50
|
+
const { meta } = useServiceText()
|
|
51
|
+
return computed<Card[]>(() => services.value.items.slice(0, limit?.()).map((service) => ({
|
|
52
|
+
key: service.id,
|
|
53
|
+
title: service.data.title,
|
|
54
|
+
to: service.url,
|
|
55
|
+
text: service.data.summary,
|
|
56
|
+
meta: meta(service.data),
|
|
57
|
+
image: service.data.image,
|
|
58
|
+
})))
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** What the Service JSON-LD needs besides the texts: the address of the page and the photo. */
|
|
62
|
+
export interface ServiceJsonLdInput extends ServiceFacts {
|
|
63
|
+
summary: string
|
|
64
|
+
url: string
|
|
65
|
+
image?: ImageValue | null
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* schema.org Service for a service page: name, summary, address, photo, the business as provider and, with a fixed
|
|
70
|
+
* price, an Offer with the amount in major units, its currency and, with `vat` in app.config.ts, whether VAT is
|
|
71
|
+
* included. A service on request has no Offer, so search engines never read a price the page does not show.
|
|
72
|
+
*/
|
|
73
|
+
export function useServiceJsonLd(service: () => ServiceJsonLdInput) {
|
|
74
|
+
const { name, url } = useGinkoSite()
|
|
75
|
+
const { vat } = useSiteAppConfig()
|
|
76
|
+
const country: string = useRuntimeConfig().public.ginko.country
|
|
77
|
+
const absolute = (path: string) => new URL(path, url).href
|
|
78
|
+
return computed(() => {
|
|
79
|
+
const s = service()
|
|
80
|
+
const price = s.pricing === 'price' ? s.price : undefined
|
|
81
|
+
return {
|
|
82
|
+
'@context': 'https://schema.org',
|
|
83
|
+
'@type': 'Service',
|
|
84
|
+
name: s.title,
|
|
85
|
+
description: s.summary,
|
|
86
|
+
url: absolute(s.url),
|
|
87
|
+
...(s.image ? { image: absolute(s.image.url) } : {}),
|
|
88
|
+
provider: { '@type': 'Organization', name, url },
|
|
89
|
+
...(country ? { areaServed: { '@type': 'Country', name: country } } : {}),
|
|
90
|
+
...(price ? { offers: offerJsonLd(price, price.currency, vat ? { valueAddedTaxIncluded: vat === 'included' } : {}) } : {}),
|
|
91
|
+
}
|
|
92
|
+
})
|
|
93
|
+
}
|
|
@@ -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,19 @@
|
|
|
1
|
+
import { safeHref } from '@lupinum/ginko'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* How to book and how to get here, for the home page and the contact page: phone, email and address from
|
|
5
|
+
* content/site.md (written once, there), the phone hours, an online booking page and the directions from
|
|
6
|
+
* content/visit.md, and "Open in maps" as a link to OpenStreetMap with the address: no embedded map, so nothing
|
|
7
|
+
* loads from another company until the visitor chooses it.
|
|
8
|
+
*/
|
|
9
|
+
export function useVisit() {
|
|
10
|
+
const site = useGinko('site')
|
|
11
|
+
const visit = useGinko('visit')
|
|
12
|
+
const country: string = useRuntimeConfig().public.ginko.country
|
|
13
|
+
const contact = computed(() => site.value.data)
|
|
14
|
+
const address = computed(() => [contact.value.street, [contact.value.postalCode, contact.value.city].filter(Boolean).join(' ')].filter(Boolean))
|
|
15
|
+
const maps = computed(() => (address.value.length ? `https://www.openstreetmap.org/search?query=${encodeURIComponent([...address.value, country].filter(Boolean).join(', '))}` : undefined))
|
|
16
|
+
// An address the owner typed: safeHref drops unsafe schemes (javascript: …); the field itself accepts only URLs.
|
|
17
|
+
const booking = computed(() => (visit.value.data.bookingUrl ? safeHref(visit.value.data.bookingUrl) : undefined))
|
|
18
|
+
return { contact, visit, address, maps, booking }
|
|
19
|
+
}
|
|
@@ -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,36 @@
|
|
|
1
|
+
<!-- Synced from templates/_features/pages/app/pages/[...slug].vue by `pnpm templates sync`. Edit the source, not this copy. -->
|
|
2
|
+
<script setup lang="ts">
|
|
3
|
+
import type { Component } from 'vue'
|
|
4
|
+
import { safeHref } from '@lupinum/ginko'
|
|
5
|
+
|
|
6
|
+
// A page of content/pages/ at /<slug> (in other languages /<code>/<slug>). An unknown address is a real 404.
|
|
7
|
+
// A template can show more at the top of its pages with app/components/pages/Top.vue (prop `id`: the entry id, such
|
|
8
|
+
// as `pages/get-involved`); without that file, nothing is added.
|
|
9
|
+
const route = useRoute()
|
|
10
|
+
const page = useGinkoEntry('pages', () => route.params.slug)
|
|
11
|
+
const PagesTop = Object.values(import.meta.glob<Component>('~/components/pages/Top.vue', { eager: true, import: 'default' }))[0]
|
|
12
|
+
const action = computed(() => {
|
|
13
|
+
const href = safeHref(page.value.data.actionUrl)
|
|
14
|
+
return href && page.value.data.actionLabel ? { label: page.value.data.actionLabel, href } : undefined
|
|
15
|
+
})
|
|
16
|
+
usePageSeo(() => ({
|
|
17
|
+
title: page.value.data.title,
|
|
18
|
+
description: page.value.data.summary,
|
|
19
|
+
image: page.value.data.image,
|
|
20
|
+
}))
|
|
21
|
+
</script>
|
|
22
|
+
|
|
23
|
+
<template>
|
|
24
|
+
<article>
|
|
25
|
+
<BlockPageHeader :title="page.data.title" :lead="page.data.summary">
|
|
26
|
+
<Button v-if="action" as-child size="lg" class="self-start max-sm:self-stretch">
|
|
27
|
+
<a :href="action.href">{{ action.label }}</a>
|
|
28
|
+
</Button>
|
|
29
|
+
</BlockPageHeader>
|
|
30
|
+
<component :is="PagesTop" v-if="PagesTop" :id="page.id" />
|
|
31
|
+
<div v-if="page.data.image" class="mx-auto max-w-page px-gutter pb-10">
|
|
32
|
+
<GinkoImage :image="page.data.image" eager sizes="(min-width: 1216px) 1152px, 100vw" class="aspect-video w-full rounded-block bg-muted object-cover" />
|
|
33
|
+
</div>
|
|
34
|
+
<ProseBody :value="page.data.body" />
|
|
35
|
+
</article>
|
|
36
|
+
</template>
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { Accessibility, CircleParking, MapPin, TramFront } from '@lucide/vue'
|
|
3
|
+
|
|
4
|
+
// How to book and how to find the practice: whether it is open now, then booking as on the home page (call with the
|
|
5
|
+
// phone hours, email, the online booking page when content/visit.md names one); then the address with "Open in maps",
|
|
6
|
+
// access, parking and public transport, the opening hours, and photos of the practice. No form: nothing is sent to
|
|
7
|
+
// other companies. The address per language comes from `pages.contact` in ginko.config.ts.
|
|
8
|
+
const gallery = useGinko('gallery')
|
|
9
|
+
const { visit, address, maps } = useVisit()
|
|
10
|
+
const { name } = useGinkoSite()
|
|
11
|
+
const { t } = useI18n()
|
|
12
|
+
const langOf = useGinkoLang()
|
|
13
|
+
|
|
14
|
+
const directions = computed(() => [
|
|
15
|
+
{ key: 'access', icon: Accessibility, label: t('visit.access'), text: visit.value.data.access },
|
|
16
|
+
{ key: 'parking', icon: CircleParking, label: t('visit.parking'), text: visit.value.data.parking },
|
|
17
|
+
{ key: 'transit', icon: TramFront, label: t('visit.transit'), text: visit.value.data.transit },
|
|
18
|
+
].filter((row) => row.text))
|
|
19
|
+
const images = computed(() => gallery.value.data.images.map((entry) => entry.image))
|
|
20
|
+
usePageSeo(() => ({ title: t('contact.title'), description: t('contact.lead') }))
|
|
21
|
+
</script>
|
|
22
|
+
|
|
23
|
+
<template>
|
|
24
|
+
<div>
|
|
25
|
+
<BlockPageHeader :title="t('contact.title')" :lead="t('contact.lead')" />
|
|
26
|
+
|
|
27
|
+
<div class="mx-auto flex max-w-page flex-col gap-6 px-gutter">
|
|
28
|
+
<HoursToday />
|
|
29
|
+
<VisitBook />
|
|
30
|
+
</div>
|
|
31
|
+
|
|
32
|
+
<BlockSection :title="t('contact.directions')">
|
|
33
|
+
<div class="flex flex-col gap-8">
|
|
34
|
+
<div v-if="address.length" class="flex flex-col gap-2">
|
|
35
|
+
<address class="flex flex-col not-italic">
|
|
36
|
+
<span class="font-semibold"><bdi>{{ name }}</bdi></span>
|
|
37
|
+
<span v-for="line in address" :key="line"><bdi>{{ line }}</bdi></span>
|
|
38
|
+
</address>
|
|
39
|
+
<a v-if="maps" :href="maps" rel="noopener" class="inline-flex min-h-11 items-center gap-2 self-start font-medium text-primary underline underline-offset-4">
|
|
40
|
+
<MapPin class="size-4 shrink-0" aria-hidden="true" />{{ t('visit.maps') }}
|
|
41
|
+
</a>
|
|
42
|
+
</div>
|
|
43
|
+
<dl v-if="directions.length" class="flex flex-col border-b">
|
|
44
|
+
<div v-for="row in directions" :key="row.key" class="grid items-baseline gap-1 border-t py-4 sm:grid-cols-[minmax(0,14rem)_1fr] sm:gap-6">
|
|
45
|
+
<dt class="flex items-center gap-2 font-semibold">
|
|
46
|
+
<component :is="row.icon" class="size-4 shrink-0 text-muted-foreground" aria-hidden="true" />{{ row.label }}
|
|
47
|
+
</dt>
|
|
48
|
+
<dd :lang="langOf(visit, row.key)">{{ row.text }}</dd>
|
|
49
|
+
</div>
|
|
50
|
+
</dl>
|
|
51
|
+
</div>
|
|
52
|
+
</BlockSection>
|
|
53
|
+
|
|
54
|
+
<BlockSection :title="t('contact.hours')">
|
|
55
|
+
<HoursTable />
|
|
56
|
+
</BlockSection>
|
|
57
|
+
|
|
58
|
+
<BlockSection v-if="images.length" :title="t('contact.practice')" :side="false">
|
|
59
|
+
<BlockGallery :images="images" />
|
|
60
|
+
</BlockSection>
|
|
61
|
+
</div>
|
|
62
|
+
</template>
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
<!-- Synced from templates/_features/faq/app/pages/faq.vue by `pnpm templates sync`. Edit the source, not this copy. -->
|
|
2
|
+
<script setup lang="ts">
|
|
3
|
+
import type { Component } from 'vue'
|
|
4
|
+
import { faqJsonLd } from '@lupinum/ginko/basics'
|
|
5
|
+
|
|
6
|
+
// The FAQ page (page key `faq`): the questions and answers of content/faq/ in the owner's order, as an accordion whose
|
|
7
|
+
// questions are the page's h2, with FAQPage JSON-LD. Below them, one line leads to a person for a question that is not
|
|
8
|
+
// listed: the site's contact page (`pages/contact`) when it has one, else the email, phone and address of
|
|
9
|
+
// content/site.md (SiteContact). The address per language comes from `pages.faq` in ginko.config.ts; a template sets
|
|
10
|
+
// its own title and lead with `faq.title` and `faq.lead` in its i18n/<code>.json. A template may bring
|
|
11
|
+
// `app/components/site/PageCta.vue`, its closing band: it shows at the end of the page.
|
|
12
|
+
const cta = Object.values(import.meta.glob<Component>('../components/site/PageCta.vue', { eager: true, import: 'default' }))[0]
|
|
13
|
+
const questions = useGinko('faq')
|
|
14
|
+
const contact = useSiteLinks(() => [{ entry: 'pages/contact' }])
|
|
15
|
+
const { t } = useI18n('faq')
|
|
16
|
+
const items = computed(() => questions.value.items.map((item) => ({ id: item.id, question: item.data.question, answer: item.data.answer })))
|
|
17
|
+
usePageSeo(() => ({ title: t('title'), description: t('lead'), jsonLd: items.value.length ? [faqJsonLd(items.value)] : [] }))
|
|
18
|
+
</script>
|
|
19
|
+
|
|
20
|
+
<template>
|
|
21
|
+
<div>
|
|
22
|
+
<BlockPageHeader :title="t('title')" :lead="t('lead')" />
|
|
23
|
+
<div class="mx-auto max-w-page px-gutter">
|
|
24
|
+
<div v-if="items.length" class="flex max-w-prose flex-col gap-8">
|
|
25
|
+
<BlockFaq :items="items" heading-level="h2" />
|
|
26
|
+
<p v-if="contact[0]" data-faq-contact>
|
|
27
|
+
{{ t('more') }}
|
|
28
|
+
<NuxtLink :to="contact[0].to" class="-my-2.5 inline-block py-2.5 font-medium text-primary underline underline-offset-4">{{ contact[0].label }}</NuxtLink>
|
|
29
|
+
</p>
|
|
30
|
+
<div v-else class="flex flex-col gap-2" data-faq-contact>
|
|
31
|
+
<p>{{ t('more') }}</p>
|
|
32
|
+
<SiteContact />
|
|
33
|
+
</div>
|
|
34
|
+
</div>
|
|
35
|
+
<BlockEmpty v-else :title="t('empty')" path="content/faq/" />
|
|
36
|
+
</div>
|
|
37
|
+
<component :is="cta" v-if="cta" />
|
|
38
|
+
</div>
|
|
39
|
+
</template>
|