From 1e4023d5887a9c847f3c3b76649498485c2fe86f Mon Sep 17 00:00:00 2001 From: Maxime Pauvert Date: Sun, 8 Feb 2026 18:26:00 +0100 Subject: [PATCH 1/4] fix: use template list form nuxt-starter --- app/components/StarterCard.vue | 6 +-- nuxt.config.ts | 3 +- server/routes/data/starters.json.ts | 72 ++++++++++------------------- shared/types/index.ts | 11 +++-- 4 files changed, 33 insertions(+), 59 deletions(-) diff --git a/app/components/StarterCard.vue b/app/components/StarterCard.vue index 51a73285..9d37ed41 100644 --- a/app/components/StarterCard.vue +++ b/app/components/StarterCard.vue @@ -7,11 +7,7 @@ const props = defineProps({ }) const template = computed(() => { - return props.starter.repo === 'nuxt/starter' - ? (props.starter.branch === 'v4') - ? '' - : `-- -t ${props.starter.branch}` - : `-- -t "${props.starter.repo}#${props.starter.branch}"` + return props.starter.default ? '' : `-- -t ${props.starter.slug}` }) const command = computed(() => { diff --git a/nuxt.config.ts b/nuxt.config.ts index 72d35faf..e7ffb763 100644 --- a/nuxt.config.ts +++ b/nuxt.config.ts @@ -16,11 +16,12 @@ export default defineNuxtConfig({ routeRules: { '/themes': { redirect: 'https://nuxt.com/templates' }, '/templates': { redirect: 'https://nuxt.com/templates' }, + '/data/starters.json': { isr: 3600 }, }, compatibilityDate: '2025-07-28', nitro: { prerender: { - routes: ['/', '/data/starters.json'], + routes: ['/'], }, }, vite: { diff --git a/server/routes/data/starters.json.ts b/server/routes/data/starters.json.ts index 93ba912c..13124a1d 100644 --- a/server/routes/data/starters.json.ts +++ b/server/routes/data/starters.json.ts @@ -1,48 +1,24 @@ -export default defineEventHandler((): Starter[] => [ - { - name: 'Nuxt 4', - slug: 'v4', - description: 'Minimal starter with a single app.vue.', - image: 'data:image/svg+xml,%3Csvg xmlns=\'http://www.w3.org/2000/svg\' width=\'34\' height=\'34\' viewBox=\'0 0 34 34\' fill=\'none\'%3E%3Cpath d=\'M19.0778 28.3333H31.6956C32.0993 28.3364 32.4968 28.2333 32.8482 28.0344C33.1996 27.8355 33.4926 27.5478 33.6978 27.2C33.8967 26.8554 34.0015 26.4645 34.0015 26.0667C34.0015 25.6688 33.8967 25.2779 33.6978 24.9333L25.1978 10.3511C24.9987 10.0063 24.7124 9.72003 24.3675 9.52108C24.0226 9.32213 23.6315 9.21751 23.2333 9.21777C22.8296 9.2147 22.4321 9.31778 22.0807 9.51669C21.7293 9.71559 21.4363 10.0033 21.2311 10.3511L19.0778 14.0911L14.8467 6.79999C14.6445 6.44959 14.3521 6.1597 14 5.96041C13.648 5.76112 13.249 5.65969 12.8445 5.66666C12.4471 5.67016 12.0574 5.77635 11.7132 5.97494C11.369 6.17352 11.0819 6.45774 10.88 6.79999L0.302233 24.9333C0.153235 25.1913 0.056538 25.476 0.0176701 25.7714C-0.0211977 26.0667 -0.00147386 26.3668 0.075714 26.6545C0.152902 26.9422 0.28604 27.2118 0.467516 27.4481C0.648992 27.6843 0.875247 27.8824 1.13334 28.0311C1.47334 28.22 1.8889 28.3333 2.30446 28.3333H10.2378C13.3733 28.3333 15.6778 26.9733 17.2645 24.2911L21.1556 17.6422L23.2333 14.0911L29.4667 24.7822H21.1556L19.0778 28.3333ZM10.0867 24.7822H4.57112L12.8445 10.54L17 17.6422L14.2045 22.4022C13.1467 24.14 11.9756 24.7822 10.0867 24.7822Z\' fill=\'%2300DC82\'/%3E%3C/svg%3E', - repo: 'nuxt/starter', - branch: 'v4', - docs: 'https://nuxt.com/docs/4.x/getting-started/installation', - }, - { - name: 'Nuxt 3', - deprecated: true, - slug: 'v3', - description: 'Minimal starter with a single app.vue.', - image: 'data:image/svg+xml,%3Csvg xmlns=\'http://www.w3.org/2000/svg\' width=\'34\' height=\'34\' viewBox=\'0 0 34 34\' fill=\'none\'%3E%3Cpath d=\'M19.0778 28.3333H31.6956C32.0993 28.3364 32.4968 28.2333 32.8482 28.0344C33.1996 27.8355 33.4926 27.5478 33.6978 27.2C33.8967 26.8554 34.0015 26.4645 34.0015 26.0667C34.0015 25.6688 33.8967 25.2779 33.6978 24.9333L25.1978 10.3511C24.9987 10.0063 24.7124 9.72003 24.3675 9.52108C24.0226 9.32213 23.6315 9.21751 23.2333 9.21777C22.8296 9.2147 22.4321 9.31778 22.0807 9.51669C21.7293 9.71559 21.4363 10.0033 21.2311 10.3511L19.0778 14.0911L14.8467 6.79999C14.6445 6.44959 14.3521 6.1597 14 5.96041C13.648 5.76112 13.249 5.65969 12.8445 5.66666C12.4471 5.67016 12.0574 5.77635 11.7132 5.97494C11.369 6.17352 11.0819 6.45774 10.88 6.79999L0.302233 24.9333C0.153235 25.1913 0.056538 25.476 0.0176701 25.7714C-0.0211977 26.0667 -0.00147386 26.3668 0.075714 26.6545C0.152902 26.9422 0.28604 27.2118 0.467516 27.4481C0.648992 27.6843 0.875247 27.8824 1.13334 28.0311C1.47334 28.22 1.8889 28.3333 2.30446 28.3333H10.2378C13.3733 28.3333 15.6778 26.9733 17.2645 24.2911L21.1556 17.6422L23.2333 14.0911L29.4667 24.7822H21.1556L19.0778 28.3333ZM10.0867 24.7822H4.57112L12.8445 10.54L17 17.6422L14.2045 22.4022C13.1467 24.14 11.9756 24.7822 10.0867 24.7822Z\' fill=\'%2300DC82\'/%3E%3C/svg%3E', - repo: 'nuxt/starter', - branch: 'v3', - docs: 'https://nuxt.com/docs/3.x/getting-started/installation', - }, - { - name: 'UI', - slug: 'ui', - description: 'Starter with Nuxt UI.', - image: 'data:image/svg+xml,%3Csvg xmlns=\'http://www.w3.org/2000/svg\' width=\'32\' height=\'32\' viewBox=\'0 0 20 20\'%3E%3Cpath fill=\'%2300DC82\' fill-rule=\'evenodd\' d=\'M10 2.5c-1.31 0-2.526.386-3.546 1.051a.75.75 0 0 1-.82-1.256A8 8 0 0 1 18 9a22.47 22.47 0 0 1-1.228 7.351a.75.75 0 1 1-1.417-.49A20.97 20.97 0 0 0 16.5 9A6.5 6.5 0 0 0 10 2.5ZM4.333 4.416a.75.75 0 0 1 .218 1.038A6.466 6.466 0 0 0 3.5 9a7.966 7.966 0 0 1-1.293 4.362a.75.75 0 0 1-1.257-.819A6.466 6.466 0 0 0 2 9c0-1.61.476-3.11 1.295-4.365a.75.75 0 0 1 1.038-.219ZM10 6.12a3 3 0 0 0-3.001 3.041a11.455 11.455 0 0 1-2.697 7.24a.75.75 0 0 1-1.148-.965A9.957 9.957 0 0 0 5.5 9c0-.028.002-.055.004-.082a4.5 4.5 0 0 1 8.996.084v.148l-.005.297a.75.75 0 1 1-1.5-.034c.003-.11.004-.219.005-.328a3 3 0 0 0-3-2.965Zm0 2.13a.75.75 0 0 1 .75.75c0 3.51-1.187 6.745-3.181 9.323a.75.75 0 1 1-1.186-.918A13.687 13.687 0 0 0 9.25 9a.75.75 0 0 1 .75-.75Zm3.529 3.698a.75.75 0 0 1 .584.885a18.883 18.883 0 0 1-2.257 5.84a.75.75 0 1 1-1.29-.764a17.386 17.386 0 0 0 2.078-5.377a.75.75 0 0 1 .885-.584Z\' clip-rule=\'evenodd\'/%3E%3C/svg%3E', - repo: 'nuxt/starter', - branch: 'ui', - docs: 'https://ui.nuxt.com', - }, - { - name: 'Content', - slug: 'content', - description: 'Starter for a content-driven website.', - image: 'data:image/svg+xml,%3Csvg width=\'34\' height=\'34\' fill=\'none\' xmlns=\'http://www.w3.org/2000/svg\'%3E%3Cpath d=\'M12 14h10a1.667 1.667 0 0 0 1.667-1.667v-10A1.667 1.667 0 0 0 22 .667H12a1.667 1.667 0 0 0-1.667 1.666v10A1.667 1.667 0 0 0 12 14Zm1.667-10h6.666v6.667h-6.666V4ZM32 10.667h-3.333a1.667 1.667 0 0 0 0 3.333H32a1.667 1.667 0 1 0 0-3.333Zm-3.333-3.334H32A1.667 1.667 0 1 0 32 4h-3.333a1.667 1.667 0 0 0 0 3.333ZM2 7.333h3.333a1.667 1.667 0 1 0 0-3.333H2a1.667 1.667 0 1 0 0 3.333ZM2 14h3.333a1.667 1.667 0 1 0 0-3.333H2A1.667 1.667 0 0 0 2 14Zm30 3.333H2a1.667 1.667 0 1 0 0 3.334h30a1.667 1.667 0 1 0 0-3.334ZM18.667 24H2a1.667 1.667 0 1 0 0 3.333h16.667a1.667 1.667 0 0 0 0-3.333Z\' fill=\'%2300BD6F\'/%3E%3C/svg%3E', - repo: 'nuxt/starter', - branch: 'content', - docs: 'https://content.nuxt.com', - }, - { - name: 'Module', - slug: 'module', - description: 'Starter to create your first Nuxt module.', - image: 'data:image/svg+xml,%3Csvg width=\'34\' height=\'34\' fill=\'none\' xmlns=\'http://www.w3.org/2000/svg\'%3E%3Cpath d=\'M29.117 9.283V9.15l-.1-.25a1.186 1.186 0 0 0-.117-.15 1.571 1.571 0 0 0-.15-.2l-.15-.117-.267-.133-12.5-7.717a1.667 1.667 0 0 0-1.766 0L1.667 8.3l-.15.133-.15.117c-.056.063-.106.13-.15.2a1.183 1.183 0 0 0-.117.15l-.1.25v.133c-.016.144-.016.29 0 .434v14.566a1.667 1.667 0 0 0 .783 1.417l12.5 7.717a.784.784 0 0 0 .25.1h.134c.282.09.584.09.866 0h.134a.784.784 0 0 0 .25-.1L28.333 25.7a1.667 1.667 0 0 0 .784-1.417V9.717c.016-.144.016-.29 0-.434ZM13.333 29.017 4.167 23.35V12.717l9.166 5.65v10.65ZM15 15.483 5.667 9.717 15 3.967l9.333 5.75L15 15.483Zm10.833 7.867-9.166 5.667v-10.65l9.166-5.65V23.35Z\' fill=\'%2300BD6F\'/%3E%3C/svg%3E', - repo: 'nuxt/starter', - branch: 'module', - docs: 'https://nuxt.com/docs/4.x/guide/going-further/modules', - }, -]) +export default defineEventHandler(async (event) => { + const templates: Starter[] = [] + + const files = await $fetch('https://api.github.com/repos/maximepvrt/nuxt-starter/contents/templates?ref=update-template') + + await Promise.all(files.map(async (file) => { + if (!file.download_url || file.type !== 'file' || !file.name.endsWith('.json')) { + return + } + const templateName = file.name.replace('.json', '') + const template = await $fetch(file.download_url, { + responseType: 'json', + }) as Starter + if (!template.deprecated) { + templates.push({ slug: templateName, ...template, tar: `https://codeload.github.com/${template.repo}/tar.gz/refs/heads/${template.branch}` }) + } + })) + + return templates.sort((a, b) => { + if (a.default && !b.default) return -1 + if (!a.default && b.default) return 1 + return 0 + }) +}) diff --git a/shared/types/index.ts b/shared/types/index.ts index ef80c059..b70d7e68 100644 --- a/shared/types/index.ts +++ b/shared/types/index.ts @@ -1,12 +1,13 @@ export interface Starter { name: string slug: string + default?: boolean description: string image?: string - repo: string - branch: string - dir?: string - demo?: string - docs?: string + tar: string + repo: string, + branch: string, + defaultDir?: string + url?: string deprecated?: boolean } From 9b2539bfa57a849dfc6784e8908aae97b876344a Mon Sep 17 00:00:00 2001 From: Maxime Pauvert Date: Sun, 8 Feb 2026 18:39:15 +0100 Subject: [PATCH 2/4] Update starters.json.ts --- server/routes/data/starters.json.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/routes/data/starters.json.ts b/server/routes/data/starters.json.ts index 13124a1d..cbff5e72 100644 --- a/server/routes/data/starters.json.ts +++ b/server/routes/data/starters.json.ts @@ -1,7 +1,7 @@ export default defineEventHandler(async (event) => { const templates: Starter[] = [] - const files = await $fetch('https://api.github.com/repos/maximepvrt/nuxt-starter/contents/templates?ref=update-template') + const files = await $fetch('https://api.github.com/repos/nuxt/nuxt-starter/contents/templates') await Promise.all(files.map(async (file) => { if (!file.download_url || file.type !== 'file' || !file.name.endsWith('.json')) { From bb5371d67bc776a21a617dfb8c155d8401bd212c Mon Sep 17 00:00:00 2001 From: Maxime Pauvert Date: Sun, 8 Feb 2026 19:07:19 +0100 Subject: [PATCH 3/4] up --- server/routes/data/starters.json.ts | 28 ++++++++++++++-------------- shared/types/index.ts | 4 ++-- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/server/routes/data/starters.json.ts b/server/routes/data/starters.json.ts index cbff5e72..8b858542 100644 --- a/server/routes/data/starters.json.ts +++ b/server/routes/data/starters.json.ts @@ -1,21 +1,21 @@ -export default defineEventHandler(async (event) => { +export default defineEventHandler(async () => { const templates: Starter[] = [] - const files = await $fetch('https://api.github.com/repos/nuxt/nuxt-starter/contents/templates') + const files = await $fetch('https://api.github.com/repos/maximepvrt/nuxt-starter/contents/templates?ref=update-template') await Promise.all(files.map(async (file) => { - if (!file.download_url || file.type !== 'file' || !file.name.endsWith('.json')) { - return - } - const templateName = file.name.replace('.json', '') - const template = await $fetch(file.download_url, { - responseType: 'json', - }) as Starter - if (!template.deprecated) { - templates.push({ slug: templateName, ...template, tar: `https://codeload.github.com/${template.repo}/tar.gz/refs/heads/${template.branch}` }) - } - })) - + if (!file.download_url || file.type !== 'file' || !file.name.endsWith('.json')) { + return + } + const templateName = file.name.replace('.json', '') + const template = await $fetch(file.download_url, { + responseType: 'json', + }) as Starter + if (!template.deprecated) { + templates.push({ slug: templateName, ...template, tar: `https://codeload.github.com/${template.repo}/tar.gz/refs/heads/${template.branch}` }) + } + })) + return templates.sort((a, b) => { if (a.default && !b.default) return -1 if (!a.default && b.default) return 1 diff --git a/shared/types/index.ts b/shared/types/index.ts index b70d7e68..798ecef1 100644 --- a/shared/types/index.ts +++ b/shared/types/index.ts @@ -5,8 +5,8 @@ export interface Starter { description: string image?: string tar: string - repo: string, - branch: string, + repo: string + branch: string defaultDir?: string url?: string deprecated?: boolean From 741085aede9a30e92cce35c056e80d448445876e Mon Sep 17 00:00:00 2001 From: Maxime Pauvert Date: Sun, 8 Feb 2026 19:20:01 +0100 Subject: [PATCH 4/4] up --- server/routes/c/[slug].get.ts | 2 +- server/routes/data/starters.json.ts | 4 ++-- server/routes/s/[slug].get.ts | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/server/routes/c/[slug].get.ts b/server/routes/c/[slug].get.ts index fa61e7ca..2f82eacc 100644 --- a/server/routes/c/[slug].get.ts +++ b/server/routes/c/[slug].get.ts @@ -7,5 +7,5 @@ export default defineEventHandler(async (event) => { body: 'Not found', } } - return sendRedirect(event, `https://codesandbox.io/s/github/${starter.repo}/tree/${starter.branch}/${starter.dir || ''}`, 302) + return sendRedirect(event, `https://codesandbox.io/s/github/${starter.repo}/tree/${starter.branch}`, 302) }) diff --git a/server/routes/data/starters.json.ts b/server/routes/data/starters.json.ts index 8b858542..06b82721 100644 --- a/server/routes/data/starters.json.ts +++ b/server/routes/data/starters.json.ts @@ -1,7 +1,7 @@ export default defineEventHandler(async () => { const templates: Starter[] = [] - const files = await $fetch('https://api.github.com/repos/maximepvrt/nuxt-starter/contents/templates?ref=update-template') + const files = await $fetch>('https://api.github.com/repos/maximepvrt/nuxt-starter/contents/templates?ref=update-template') await Promise.all(files.map(async (file) => { if (!file.download_url || file.type !== 'file' || !file.name.endsWith('.json')) { @@ -12,7 +12,7 @@ export default defineEventHandler(async () => { responseType: 'json', }) as Starter if (!template.deprecated) { - templates.push({ slug: templateName, ...template, tar: `https://codeload.github.com/${template.repo}/tar.gz/refs/heads/${template.branch}` }) + templates.push({ ...template, slug: templateName, tar: `https://codeload.github.com/${template.repo}/tar.gz/refs/heads/${template.branch}` }) } })) diff --git a/server/routes/s/[slug].get.ts b/server/routes/s/[slug].get.ts index 4fbed4ba..4393337d 100644 --- a/server/routes/s/[slug].get.ts +++ b/server/routes/s/[slug].get.ts @@ -7,5 +7,5 @@ export default defineEventHandler(async (event) => { body: 'Not found', } } - return sendRedirect(event, `https://stackblitz.com/github/${starter.repo}/tree/${starter.branch}/${starter.dir || ''}`, 302) + return sendRedirect(event, `https://stackblitz.com/github/${starter.repo}/tree/${starter.branch}`, 302) })