diff --git a/README.md b/README.md index 4d102acd2..9d8b03f15 100644 --- a/README.md +++ b/README.md @@ -89,6 +89,7 @@ For proper integration with the starter-dev CLI and website there are also some - `description` - This field is used as a short description highlighting the technologies of each particular starter kit. It is shown as a selection in the starter-dev CLI. Example: `NextJS, React Query, and TailwindCSS` - `keywords` - This field is an array of strings used to map to the technology list on the starter.dev website. Example: `["next", "react-query", "tailwind"]` - `hasShowcase` - This field is a boolean and is required when displaying the "View Showcase" link for kits that have showcases. If your kit has a showcase, set the value to `true`. If your kit does not have a showcase, set the value to `false`. +- `showcase` - This field is an array and is required when displaying the showcase list on individual kit pages. If your kit has a showcase, add an object containing `kit`, `name`, `repo`, and `app` to the array. Please check existing package.jsons like the one found here starters/svelte-kit-scss/package.json for what the values should be. ### Adding starter kit to the website diff --git a/packages/website/.gitignore b/packages/website/.gitignore index 3c2f2dcc6..e5ea84a75 100644 --- a/packages/website/.gitignore +++ b/packages/website/.gitignore @@ -20,3 +20,4 @@ yarn-error.log* # ignore generated kit pages src/pages/kits/*.md src/pages/kits/*.mdx +src/showcases/*.json diff --git a/packages/website/package.json b/packages/website/package.json index a8457189d..d1faae4b1 100644 --- a/packages/website/package.json +++ b/packages/website/package.json @@ -10,8 +10,9 @@ "format": "yarn prettier -w .", "lint": "eslint ./src", "kitgen": "node ./scripts/generate-kit-pages.js", - "predev": "yarn kitgen", - "prebuild": "yarn kitgen" + "showcasegen": "node ./scripts/generate-showcases.js", + "predev": "yarn kitgen && yarn showcasegen", + "prebuild": "yarn kitgen && yarn showcasegen" }, "devDependencies": { "@astrojs/mdx": "^0.13.0", @@ -33,6 +34,7 @@ "@heroicons/react": "^1.0.5", "autoprefixer": "^10.4.2", "clsx": "^1.1.1", + "json-loader": "^0.5.7", "just-pick": "^4.2.0", "react": "^18.2.0", "react-dom": "^18.2.0", diff --git a/packages/website/scripts/generate-kit-pages.js b/packages/website/scripts/generate-kit-pages.js index 509870381..01ebeefac 100755 --- a/packages/website/scripts/generate-kit-pages.js +++ b/packages/website/scripts/generate-kit-pages.js @@ -1,98 +1,9 @@ -const path = require('path'); -const fs = require('fs/promises'); -const pick = require('just-pick'); -const rimraf = require('rimraf'); -const { getRepoRootPath, getKitDirs } = require('../../../scripts/kits-utils'); - -const KIT_PAGE_RELATIVE_LAYOUT_PATH = '../../layouts/KitLayout.astro'; - -function convertToFrontmatter(obj) { - return Object.entries(obj) - .map(([key, value]) => `${key}: ${obj[key]}`) - .join('\n'); -} - -function formatMarkdownFile(markdown, frontmatter) { - return `--- -# generated by scripts/kitgen at ${new Date().toISOString()} -# edit KIT_PAGE_RELATIVE_LAYOUT_PATH in scripts/kitgen to change layout -layout: ${KIT_PAGE_RELATIVE_LAYOUT_PATH} -${frontmatter} ---- - -${markdown}`; -} +const { generate } = require('./generate'); /////////////////////////////////////////////////////////////////////////////// // SCRIPT MAIN //////////////////////////////////////////////////////////////////////////////// (async () => { - const repoPath = getRepoRootPath(); - const kitPagesPath = path.join(repoPath, 'packages/website/src/pages/kits'); - - try { - const handle = await fs.opendir(kitPagesPath); - console.info('kitgen: deleting existing kit pages'); - rimraf(`${kitPagesPath}/*.md,${kitPagesPath}/*.mdx`, async (err) => { - if (err) { - console.error(err); - } - await handle.close(); - }); - } catch (err) { - if (err && err.code === 'ENOENT') { - console.info('kitgen: creating kit pages directory'); - await fs.mkdir(kitPagesPath); - } - } - - const kitDirs = await getKitDirs(); - - console.info('kitgen: generating kit pages'); - for (const dir of kitDirs) { - const kitPath = path.join(repoPath, 'starters', dir); - - let infoFile = 'package.json'; - if (dir.startsWith('deno-')) { - // For Deno, we don't have package.json - infoFile = 'deno.json'; - } - - try { - const readme = await fs.readFile( - path.join(kitPath, 'README.md'), - 'utf-8' - ); - const json = await fs.readFile(path.join(kitPath, infoFile), 'utf-8'); - const data = JSON.parse(json); - - const kitData = { - ...pick(data, [ - 'name', - 'version', - 'description', - 'keywords', - 'hasShowcase', - ]), - readmePath: path.join(kitPath, 'README.md'), - starterPath: `/starters/${dir}`, - }; - - const frontmatter = convertToFrontmatter(kitData); - const formattedMarkdown = formatMarkdownFile(readme, frontmatter); - - const kitPagePath = path.join( - repoPath, - 'packages/website/src/pages/kits', - `${data.name}.mdx` - ); - - await fs.writeFile(kitPagePath, formattedMarkdown, 'utf-8'); - } catch (err) { - console.error( - `KITGEN: failed to write kit page for ${dir}: ${err.message}` - ); - } - } + await generate(true, 'packages/website/src/pages/kits'); })(); diff --git a/packages/website/scripts/generate-showcases.js b/packages/website/scripts/generate-showcases.js new file mode 100644 index 000000000..193ad4303 --- /dev/null +++ b/packages/website/scripts/generate-showcases.js @@ -0,0 +1,8 @@ +const { generate } = require('./generate'); +/////////////////////////////////////////////////////////////////////////////// +// SCRIPT MAIN +//////////////////////////////////////////////////////////////////////////////// + +(async () => { + await generate(false, 'packages/website/src/showcases'); +})(); diff --git a/packages/website/scripts/generate.js b/packages/website/scripts/generate.js new file mode 100644 index 000000000..06a83473b --- /dev/null +++ b/packages/website/scripts/generate.js @@ -0,0 +1,137 @@ +const path = require('path'); +const fs = require('fs/promises'); +const pick = require('just-pick'); +const rimraf = require('rimraf'); +const { getRepoRootPath, getKitDirs } = require('../../../scripts/kits-utils'); + +const KIT_PAGE_RELATIVE_LAYOUT_PATH = '../../layouts/KitLayout.astro'; + +function convertToFrontmatter(obj) { + return Object.entries(obj) + .map(([key, value]) => `${key}: ${obj[key]}`) + .join('\n'); +} + +function formatMarkdownFile(markdown, frontmatter) { + return `--- +# generated by scripts/kitgen at ${new Date().toISOString()} +# edit KIT_PAGE_RELATIVE_LAYOUT_PATH in scripts/kitgen to change layout +layout: ${KIT_PAGE_RELATIVE_LAYOUT_PATH} +${frontmatter} +--- + +${markdown}`; +} + +async function createDeleteFiles(isKit, PagesPath) { + try { + const handle = await fs.opendir(PagesPath); + console.info( + isKit + ? 'kitgen: deleting existing kit pages' + : 'showcasegen: deleting existing showcase file' + ); + rimraf( + isKit ? `${PagesPath}/*.md,${PagesPath}/*.mdx` : `${PagesPath}/*`, + async (err) => { + if (err) { + console.error(err); + } + await handle.close(); + } + ); + } catch (err) { + if (err && err.code === 'ENOENT') { + console.info( + isKit + ? 'kitgen: creating kit pages directory' + : 'showcasegen: creating showcase file' + ); + await fs.mkdir(PagesPath); + } + } +} + +async function generate(isKit, genPath) { + const repoPath = getRepoRootPath(); + const PagesPath = path.join(repoPath, genPath); + await createDeleteFiles(isKit, PagesPath); + + const kitDirs = await getKitDirs(); + const showcases = []; + let pickData; + let formattedMarkdown; + let PagePath; + + console.info( + isKit ? 'kitgen: generating kit pages' : 'showcasegen: generating showcases' + ); + for (const dir of kitDirs) { + const kitPath = path.join(repoPath, 'starters', dir); + + let infoFile = 'package.json'; + if (dir.startsWith('deno-')) { + // For Deno, we don't have package.json + infoFile = 'deno.json'; + } + + try { + const readme = await fs.readFile( + path.join(kitPath, 'README.md'), + 'utf-8' + ); + const json = await fs.readFile(path.join(kitPath, infoFile), 'utf-8'); + const data = JSON.parse(json); + + if (isKit) { + pickData = { + ...pick(data, [ + 'name', + 'version', + 'description', + 'keywords', + 'hasShowcase', + ]), + readmePath: path.join(kitPath, 'README.md'), + starterPath: `/starters/${dir}`, + }; + const frontmatter = convertToFrontmatter(pickData); + formattedMarkdown = formatMarkdownFile(readme, frontmatter); + PagePath = path.join( + repoPath, + 'packages/website/src/pages/kits', + `${data.name}.mdx` + ); + } else { + pickData = { + ...pick(data, ['showcases']), + }; + Object.entries(pickData).map(([key, value]) => { + value.map((item) => { + showcases.push(item); + }); + }); + PagePath = path.join( + repoPath, + 'packages/website/src/showcases/showcases.json' + ); + } + + await fs.writeFile( + PagePath, + isKit ? formattedMarkdown : JSON.stringify(showcases), + 'utf-8' + ); + } catch (err) { + console.error( + isKit + ? `KITGEN: failed to write kit page for ${dir}: ${err.message}` + : `SHOWCASEGEN: failed to write showcase page: ${err.message}` + ); + } + } +} + +module.exports = { + generate, +}; diff --git a/packages/website/src/components/KitActionLinks.astro b/packages/website/src/components/KitActionLinks.astro index 48b7d181d..252752b3c 100644 --- a/packages/website/src/components/KitActionLinks.astro +++ b/packages/website/src/components/KitActionLinks.astro @@ -8,7 +8,7 @@ const { name, hasShowcase, inline } = Astro.props; ---
-