@edgedev/create-edge-site 1.0.13 → 1.0.15

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.
Files changed (34) hide show
  1. package/{components → app/components}/edgeNavbar.vue +15 -5
  2. package/{components → app/components}/edgeScrollRevealAnim.vue +5 -8
  3. package/{components → app/components}/titleSection.vue +2 -2
  4. package/{directives → app/directives}/scrollReveal.ts +1 -1
  5. package/app/pages/[collection]/[slug].vue +30 -0
  6. package/app/pages/[collection]/index.vue +33 -0
  7. package/{pages → app/pages}/contact.vue +1 -1
  8. package/{pages → app/pages}/index.vue +1 -1
  9. package/{pages → app/pages}/stuff.vue +1 -1
  10. package/content/projects/test.md +6 -0
  11. package/content/projects/test2.md +6 -0
  12. package/content.config.ts +14 -0
  13. package/eslint.config.mjs +32 -12
  14. package/nuxt.config.ts +4 -1
  15. package/package.json +4 -1
  16. package/scripts/generateImageManifest.mjs +1 -1
  17. package/server/api/images/[...path].ts +5 -2
  18. package/server/api/images/index.ts +6 -2
  19. package/server/api/kv/[key].ts +1 -1
  20. package/server/routes/sitemap.xml.ts +33 -0
  21. package/tailwind.config.js +23 -23
  22. /package/{app.vue → app/app.vue} +0 -0
  23. /package/{assets → app/assets}/css/global.css +0 -0
  24. /package/{components → app/components}/Input.vue +0 -0
  25. /package/{components → app/components}/Select.vue +0 -0
  26. /package/{components → app/components}/Textarea.vue +0 -0
  27. /package/{components → app/components}/edgeFooter.vue +0 -0
  28. /package/{components → app/components}/edgeFormFling.vue +0 -0
  29. /package/{components → app/components}/edgeGallery.vue +0 -0
  30. /package/{components → app/components}/edgeSwiper.vue +0 -0
  31. /package/{pages → app/pages}/[...404].vue +0 -0
  32. /package/{plugins → app/plugins}/scrollReveal.ts +0 -0
  33. /package/{plugins → app/plugins}/vee-validate-rules.js +0 -0
  34. /package/{plugins → app/plugins}/vue-imask.js +0 -0
@@ -43,7 +43,7 @@ onUnmounted(() => {
43
43
  <div class="container mx-auto flex items-center justify-between h-[128px]">
44
44
  <!-- Logo -->
45
45
  <NuxtLink to="/" class="text-xl font-bold">
46
- <img src="/images/logo.png" alt="MT" class="w-full h-auto" />
46
+ <img src="/images/logo.png" alt="MT" class="w-full h-auto">
47
47
  </NuxtLink>
48
48
 
49
49
  <!-- Mobile Menu Button -->
@@ -68,6 +68,11 @@ onUnmounted(() => {
68
68
  Stuff
69
69
  </NuxtLink>
70
70
  </li>
71
+ <li>
72
+ <NuxtLink to="/projects" class="nav-item">
73
+ Projects
74
+ </NuxtLink>
75
+ </li>
71
76
  <li>
72
77
  <NuxtLink to="/contact" class="nav-item">
73
78
  Contact
@@ -86,18 +91,18 @@ onUnmounted(() => {
86
91
  </button>
87
92
 
88
93
  <!-- Mobile Logo -->
89
- <a href="/"><img src="/images/logo.png" alt="Logo" class="mb-4 w-50" /></a>
94
+ <a href="/"><img src="/images/logo.png" alt="Logo" class="mb-4 w-50"></a>
90
95
 
91
96
  <!-- Social Media Icons -->
92
97
  <div class="flex justify-center my-6 space-x-4">
93
98
  <a href="#" class="flex items-center justify-center w-12 h-12 transition rounded-full bg-lblue text-dblue hover:bg-opacity-80">
94
- <i class="fab fa-facebook-f fa-lg"></i>
99
+ <i class="fab fa-facebook-f fa-lg" />
95
100
  </a>
96
101
  <a href="#" class="flex items-center justify-center w-12 h-12 transition rounded-full bg-lblue text-dblue hover:bg-opacity-80">
97
- <i class="fab fa-instagram fa-lg"></i>
102
+ <i class="fab fa-instagram fa-lg" />
98
103
  </a>
99
104
  <a href="#" class="flex items-center justify-center w-12 h-12 transition rounded-full bg-lblue text-dblue hover:bg-opacity-80">
100
- <i class="fab fa-houzz fa-lg"></i> <!-- Houzz or custom icon -->
105
+ <i class="fab fa-houzz fa-lg" /> <!-- Houzz or custom icon -->
101
106
  </a>
102
107
  </div>
103
108
 
@@ -113,6 +118,11 @@ onUnmounted(() => {
113
118
  Stuff
114
119
  </NuxtLink>
115
120
  </li>
121
+ <li class="border-t border-b border-lblue">
122
+ <NuxtLink to="/projects" class="text-lg tracking-widest uppercase" @click="closeMenu">
123
+ Projects
124
+ </NuxtLink>
125
+ </li>
116
126
  <li class="border-t border-b border-lblue">
117
127
  <NuxtLink to="/contact" class="text-lg tracking-widest uppercase" @click="closeMenu">
118
128
  Contact
@@ -1,8 +1,9 @@
1
1
  <script setup>
2
- import ScrollReveal from 'scrollreveal'
3
2
  import { onMounted } from 'vue'
4
3
 
5
- function initObserver() {
4
+ onMounted(async () => {
5
+ const ScrollReveal = (await import('scrollreveal')).default
6
+
6
7
  const rows = document.querySelectorAll('.sr-row')
7
8
 
8
9
  const observer = new IntersectionObserver((entries, obs) => {
@@ -21,18 +22,14 @@ function initObserver() {
21
22
  reset: false,
22
23
  })
23
24
 
24
- obs.unobserve(row) // only trigger once
25
+ obs.unobserve(row)
25
26
  }
26
27
  })
27
28
  }, {
28
- threshold: 0.3, // only trigger when 30% of the row is visible
29
+ threshold: 0.3,
29
30
  })
30
31
 
31
32
  rows.forEach(row => observer.observe(row))
32
- }
33
-
34
- onMounted(() => {
35
- initObserver()
36
33
  })
37
34
  </script>
38
35
 
@@ -31,13 +31,13 @@ onMounted(() => {
31
31
  :class="isVisible ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-4'"
32
32
  >
33
33
  <h6
34
- class="inline-flex items-center gap-2 mb-4 transition-all duration-700 ease-out super-head"
34
+ class="inline-flex capitalize items-center gap-2 mb-4 transition-all duration-700 ease-out super-head"
35
35
  :class="isVisible ? 'opacity-100 translate-x-0' : 'opacity-0 -translate-x-4'"
36
36
  >
37
37
  {{ page }}
38
38
  </h6>
39
39
  <h1
40
- class="text-3xl font-light !leading-tight font-fancy md:text-5xl md:pr-80 transition-all duration-700 ease-out delay-100"
40
+ class="text-3xl capitalize font-light !leading-tight font-fancy md:text-5xl md:pr-80 transition-all duration-700 ease-out delay-100"
41
41
  :class="isVisible ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-4'"
42
42
  >
43
43
  {{ headline }}
@@ -15,7 +15,7 @@ const scrollReveal: ObjectDirective = {
15
15
 
16
16
  const observer = new IntersectionObserver(
17
17
  ([entry]) => {
18
- if (entry.isIntersecting) {
18
+ if (entry && entry.isIntersecting) {
19
19
  setTimeout(() => {
20
20
  el.classList.remove('opacity-0', 'translate-y-8')
21
21
  el.classList.add('opacity-100', 'translate-y-0')
@@ -0,0 +1,30 @@
1
+ <script setup>
2
+ import { useAsyncData } from '#imports'
3
+ import { useRoute } from 'vue-router'
4
+
5
+ const route = useRoute()
6
+ const { collection, slug } = route.params
7
+
8
+ const { data: project } = await useAsyncData(`${collection}-${slug}`, () => {
9
+ return queryCollection(collection).path(`/${collection}/${slug}`).first()
10
+ })
11
+ </script>
12
+
13
+ <template>
14
+ <Head>
15
+ <Title>Edge Website - An awesome Edge website</Title>
16
+ <Meta name="description" content="This is an Edge website template" />
17
+ <Link rel="canonical" href="https://edgemarketingdesign.com/contact" />
18
+ </Head>
19
+
20
+ <titleSection
21
+ :page="collection"
22
+ :headline="project.title"
23
+ />
24
+
25
+ <div class="container flex flex-col items-center justify-center w-full max-w-6xl px-6 pt-10 pb-64 mx-auto">
26
+ <article class="max-w-4xl px-4 py-16 mx-auto">
27
+ <ContentRenderer :value="project" />
28
+ </article>
29
+ </div>
30
+ </template>
@@ -0,0 +1,33 @@
1
+ <script setup>
2
+ import { NuxtLink } from '#components'
3
+ import { useAsyncData } from '#imports'
4
+ import { useRoute } from 'vue-router'
5
+
6
+ const route = useRoute()
7
+ const { collection } = route.params
8
+
9
+ const { data: projects } = await useAsyncData(collection, () => {
10
+ return queryCollection(collection).order('date', 'DESC').all()
11
+ })
12
+ </script>
13
+
14
+ <template>
15
+ <Head>
16
+ <Title>Edge Website - An awesome Edge website</Title>
17
+ <Meta name="description" content="This is an Edge website template" />
18
+ <Link rel="canonical" href="https://edgemarketingdesign.com/contact" />
19
+ </Head>
20
+
21
+ <titleSection
22
+ page="Content"
23
+ :headline="collection"
24
+ />
25
+
26
+ <div class="container flex flex-col items-center justify-center w-full max-w-6xl px-6 pt-10 pb-64 mx-auto">
27
+ <div v-for="project in projects" :key="project._id" class="mb-12">
28
+ <NuxtLink :to="`${project.path}`">
29
+ {{ project.title }}
30
+ </NuxtLink>
31
+ </div>
32
+ </div>
33
+ </template>
@@ -30,7 +30,7 @@ onMounted(() => {
30
30
  <Head>
31
31
  <Title>Edge Website - An awesome Edge website</Title>
32
32
  <Meta name="description" content="This is an Edge website template" />
33
- <Link rel="canonical" href="https://edgemarketingdesign.com/" />
33
+ <Link rel="canonical" href="https://edgemarketingdesign.com/contact" />
34
34
  </Head>
35
35
 
36
36
  <titleSection
@@ -11,6 +11,6 @@ onMounted(() => {
11
11
  <Link rel="canonical" href="https://edgemarketingdesign.com/" />
12
12
  </Head>
13
13
  <div class="min-h-[calc(100vh_-_328px)] w-full items-center justify-center flex flex-col">
14
- <img src="/images/edge_logo.png" class="w-[400px] h-auto" alt="Edge Marketing Design Logo" />
14
+ <img src="/images/edge_logo.png" class="w-[400px] h-auto" alt="Edge Marketing Design Logo">
15
15
  </div>
16
16
  </template>
@@ -8,7 +8,7 @@ onMounted(() => {
8
8
  <Head>
9
9
  <Title>Edge Website - An awesome Edge website</Title>
10
10
  <Meta name="description" content="This is an Edge website template" />
11
- <Link rel="canonical" href="https://edgemarketingdesign.com/" />
11
+ <Link rel="canonical" href="https://edgemarketingdesign.com/stuff" />
12
12
  </Head>
13
13
 
14
14
  <titleSection
@@ -0,0 +1,6 @@
1
+ ---
2
+ title: "Test Project"
3
+ date: "2025-01-01"
4
+ ---
5
+
6
+ This is just a test.
@@ -0,0 +1,6 @@
1
+ ---
2
+ title: "Test Project 2"
3
+ date: "2025-08-25"
4
+ ---
5
+
6
+ This is just another test.
@@ -0,0 +1,14 @@
1
+ import { defineCollection, defineContentConfig, z } from '@nuxt/content'
2
+
3
+ export default defineContentConfig({
4
+ collections: {
5
+ projects: defineCollection({
6
+ type: 'page',
7
+ source: 'projects/*.md',
8
+ schema: z.object({
9
+ title: z.string(),
10
+ date: z.date(),
11
+ }),
12
+ }),
13
+ },
14
+ })
package/eslint.config.mjs CHANGED
@@ -1,7 +1,37 @@
1
1
  import antfu from '@antfu/eslint-config'
2
2
 
3
+ // Handle CJS interop for Nuxt plugin
4
+ const nuxtPluginModule = await import('eslint-plugin-nuxt')
5
+ const nuxtPlugin = nuxtPluginModule.default ?? nuxtPluginModule
6
+
3
7
  export default [
4
- ...(await antfu()),
8
+ // Antfu base config
9
+ ...await antfu(),
10
+
11
+ // Nuxt recommended rules
12
+ {
13
+ name: 'nuxt',
14
+ plugins: {
15
+ nuxt: nuxtPlugin,
16
+ },
17
+ rules: {
18
+ ...(nuxtPlugin.configs?.recommended?.rules ?? {}),
19
+ },
20
+ },
21
+
22
+ // Explicit globals (add any other auto-imported composables here)
23
+ {
24
+ name: 'globals',
25
+ languageOptions: {
26
+ globals: {
27
+ globalState: 'readonly',
28
+ $fetch: 'readonly',
29
+ queryCollection: 'readonly',
30
+ },
31
+ },
32
+ },
33
+
34
+ // Your custom rule overrides
5
35
  {
6
36
  rules: {
7
37
  'vue/no-deprecated-slot-attribute': 'off',
@@ -9,16 +39,6 @@ export default [
9
39
  'no-console': 'off',
10
40
  'antfu/top-level-function': 'off',
11
41
  'style/eol-last': 'off',
12
- // ✅ Enforce correct self-closing behavior in Vue templates
13
- 'vue/html-self-closing': ['error', {
14
- html: {
15
- void: 'always', // <img />, <br />, <input />, etc.
16
- normal: 'never', // <div></div>, <span></span>, etc.
17
- component: 'always', // <MyComponent />
18
- },
19
- svg: 'always',
20
- math: 'always',
21
- }],
22
42
  },
23
43
  },
24
- ]
44
+ ]
package/nuxt.config.ts CHANGED
@@ -2,6 +2,9 @@ import process from 'node:process'
2
2
  import { defineNuxtConfig } from 'nuxt/config'
3
3
 
4
4
  export default defineNuxtConfig({
5
+ future: {
6
+ compatibilityVersion: 4,
7
+ },
5
8
  ssr: true,
6
9
  nitro: {
7
10
  preset: 'cloudflare-pages',
@@ -29,7 +32,7 @@ export default defineNuxtConfig({
29
32
  css: [
30
33
  '~/assets/css/global.css', // ✅ Keep global styles only
31
34
  ],
32
- modules: ['@nuxtjs/tailwindcss', '@vee-validate/nuxt', 'nitro-cloudflare-dev'],
35
+ modules: ['@nuxtjs/tailwindcss', '@vee-validate/nuxt', 'nitro-cloudflare-dev', '@nuxt/content'],
33
36
  vite: {
34
37
  define: {
35
38
  'process.env.DEBUG': false,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@edgedev/create-edge-site",
3
- "version": "1.0.13",
3
+ "version": "1.0.15",
4
4
  "description": "Create Edge Starter Site",
5
5
  "bin": {
6
6
  "create-edge-site": "./bin/cli.js"
@@ -15,10 +15,12 @@
15
15
  },
16
16
  "dependencies": {
17
17
  "@fancyapps/ui": "^5.0.36",
18
+ "@nuxt/content": "^3.6.3",
18
19
  "@nuxtjs/tailwindcss": "6.13.2",
19
20
  "@vee-validate/nuxt": "^4.15.0",
20
21
  "@vee-validate/rules": "^4.15.0",
21
22
  "@vee-validate/zod": "^4.15.0",
23
+ "better-sqlite3": "^12.2.0",
22
24
  "nuxt": "^3.16.1",
23
25
  "scrollreveal": "^4.0.9",
24
26
  "swiper": "^11.2.6",
@@ -31,6 +33,7 @@
31
33
  "devDependencies": {
32
34
  "@antfu/eslint-config": "^4.11.0",
33
35
  "eslint": "^9",
36
+ "eslint-plugin-nuxt": "^4.0.0",
34
37
  "nitro-cloudflare-dev": "^0.2.2",
35
38
  "wrangler": "^4.14.4"
36
39
  }
@@ -1,7 +1,7 @@
1
1
  import fs from 'node:fs/promises'
2
2
  import path from 'node:path'
3
3
 
4
- const rootFolder = 'public/images'
4
+ const rootFolder = '../public/images'
5
5
  const output = {}
6
6
 
7
7
  async function scanFolder(dirPath) {
@@ -1,3 +1,5 @@
1
+ import { readFile } from 'fs/promises'
2
+ import { join } from 'path'
1
3
  export default defineEventHandler(async (event) => {
2
4
  const rawParam = event.context.params?.path;
3
5
  const pathSegments = Array.isArray(rawParam)
@@ -9,8 +11,9 @@ export default defineEventHandler(async (event) => {
9
11
  const requestedPath = pathSegments.join('/');
10
12
 
11
13
  try {
12
- const manifestModule = await import('~/public/images/image-manifest.json');
13
- const manifest = manifestModule.default;
14
+ const manifestPath = join(process.cwd(), 'public/images/image-manifest.json');
15
+ const raw = await readFile(manifestPath, 'utf-8');
16
+ const manifest = JSON.parse(raw);
14
17
 
15
18
  if (!manifest || typeof manifest !== 'object') {
16
19
  return sendError(event, createError({
@@ -1,7 +1,11 @@
1
+ import { readFile } from 'fs/promises'
2
+ import { join } from 'path'
3
+
1
4
  export default defineEventHandler(async (event) => {
2
5
  try {
3
- const manifestModule = await import('~/public/images/image-manifest.json');
4
- const manifest = manifestModule.default;
6
+ const manifestPath = join(process.cwd(), 'public/images/image-manifest.json');
7
+ const raw = await readFile(manifestPath, 'utf-8');
8
+ const manifest = JSON.parse(raw);
5
9
 
6
10
  return { images: manifest };
7
11
  } catch (err) {
@@ -1,4 +1,4 @@
1
- import { getKVValue } from '~/server/utils/getKV'
1
+ import { getKVValue } from '../../../server/utils/getKV'
2
2
 
3
3
  export default defineEventHandler(async (event) => {
4
4
  const { key } = getRouterParams(event)
@@ -0,0 +1,33 @@
1
+ export default defineEventHandler(async (event) => {
2
+ const host =
3
+ event.node?.req?.headers?.host ||
4
+ event.req?.headers?.['host'] ||
5
+ 'localhost'
6
+
7
+ const protocol = host.startsWith('localhost') ? 'http' : 'https'
8
+ const baseURL = `${protocol}://${host.replace(/^www\./, '')}`
9
+
10
+ // Your routes here
11
+ const routes = [
12
+ '', // homepage
13
+ 'stuff',
14
+ 'contact',
15
+ ]
16
+
17
+ const sitemap = `<?xml version="1.0" encoding="UTF-8"?>
18
+ <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
19
+ ${routes
20
+ .map(
21
+ (path) => `
22
+ <url>
23
+ <loc>${baseURL}/${path}</loc>
24
+ <changefreq>monthly</changefreq>
25
+ <priority>0.7</priority>
26
+ </url>`
27
+ )
28
+ .join('')}
29
+ </urlset>`
30
+
31
+ event.node.res.setHeader('Content-Type', 'application/xml')
32
+ return sitemap
33
+ })
@@ -1,27 +1,27 @@
1
1
  /** @type {import('tailwindcss').Config} */
2
2
  export default {
3
- content: [
4
- "./components/**/*.{vue,js,ts}",
5
- "./layouts/**/*.{vue,js,ts}",
6
- "./pages/**/*.{vue,js,ts}",
7
- "./app.vue",
8
- ],
9
- theme: {
10
- extend: {
11
- colors: {
12
- dblue: "#30464C", // Dark Blue
13
- mblue: "#46616F", // Medium Blue
14
- lgray: "#A2A8AE", // Light Gray
15
- lblue: "#87B4B7", // Light Blue
16
- burntorange: "#B65B33", // Burnt Orange
17
- tan: "#BDA86A", // Tan
18
- cream: "#D9D0C4", // Cream
19
- },
20
- fontFamily: {
21
- sans: ["Overpass", "sans-serif"],
22
- serif: ["Rokkitt", "serif"],
23
- },
3
+ content: [
4
+ './app/components/**/*.{vue,js,ts}',
5
+ './app/layouts/**/*.{vue,js,ts}',
6
+ './app/pages/**/*.{vue,js,ts}',
7
+ './app/app.vue',
8
+ ],
9
+ theme: {
10
+ extend: {
11
+ colors: {
12
+ dblue: '#30464C', // Dark Blue
13
+ mblue: '#46616F', // Medium Blue
14
+ lgray: '#A2A8AE', // Light Gray
15
+ lblue: '#87B4B7', // Light Blue
16
+ burntorange: '#B65B33', // Burnt Orange
17
+ tan: '#BDA86A', // Tan
18
+ cream: '#D9D0C4', // Cream
19
+ },
20
+ fontFamily: {
21
+ sans: ['Overpass', 'sans-serif'],
22
+ serif: ['Rokkitt', 'serif'],
24
23
  },
25
24
  },
26
- plugins: [],
27
- };
25
+ },
26
+ plugins: [],
27
+ }
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes