diff --git a/.eleventy.js b/.eleventy.js index b1241bb9..91a7bf39 100644 --- a/.eleventy.js +++ b/.eleventy.js @@ -20,112 +20,116 @@ const javascript = require("./src/config/processors/javascript"); // πŸ› οΈ Utilities const filterPostDate = require("./src/config/filters/postDate"); const filterIsoDate = require("./src/config/filters/isoDate"); +const filterTitleCase = require("./src/config/filters/titleCase"); const isProduction = process.env.ELEVENTY_ENV === "PROD"; module.exports = function (eleventyConfig) { - // ═════════════════════════════════════════════════════════════════════════ - // LANGUAGES - // Using Eleventy's build events to process non-template languages - // Learn more: https://www.11ty.dev/docs/events/ - // ═════════════════════════════════════════════════════════════════════════ - - /* - * JavaScript & CSS Processing - * These processors handle bundling, transpiling, and minification - * - JavaScript: Compiled with esbuild for modern bundling - * - CSS/LESS: Processed and minified for production, including a PostCSS pipeline - */ - eleventyConfig.on("eleventy.after", javascript); - eleventyConfig.on("eleventy.after", less); - - // ═════════════════════════════════════════════════════════════════════════ - // PLUGINS - // Extend Eleventy with additional functionality - // Learn more: https://www.11ty.dev/docs/plugins/ - // ═════════════════════════════════════════════════════════════════════════ - - /* - * πŸ–ΌοΈ Image Optimization - * Resize and optimize images for better performance using {% getUrl %} - * Documentation: https://github.com/CodeStitchOfficial/eleventy-plugin-sharp-images - */ - eleventyConfig.addPlugin(pluginImages, configImages); - - /* - * πŸ—ΊοΈ Sitemap Generation - * Creates sitemap.xml automatically using domain from _data/client.json - * Documentation: https://github.com/quasibit/eleventy-plugin-sitemap - */ - eleventyConfig.addPlugin(pluginSitemap, configSitemap); - - /* - * πŸ“¦ Production Minification - * Minifies HTML, CSS, JSON, XML, XSL, and webmanifest files - * Only runs during production builds (npm run build) - * Documentation: https://github.com/CodeStitchOfficial/eleventy-plugin-minify - */ - if (isProduction) { - eleventyConfig.addPlugin(pluginMinifier); - } - - // ═════════════════════════════════════════════════════════════════════════ - // PASSTHROUGH COPIES - // Copy files directly to output without processing - // Learn more: https://www.11ty.dev/docs/copy/ - // ═════════════════════════════════════════════════════════════════════════ - - eleventyConfig.addPassthroughCopy("./src/assets"); // Static assets - eleventyConfig.addPassthroughCopy("./src/admin"); // CMS admin files - eleventyConfig.addPassthroughCopy("./src/_redirects"); // Redirect rules - - // ═════════════════════════════════════════════════════════════════════════ - // FILTERS - // Transform data in templates at build time - // Learn more: https://www.11ty.dev/docs/filters/ - // ═════════════════════════════════════════════════════════════════════════ - - /* - * πŸ“… Human-Readable Date Formatting Filter - * Converts JavaScript dates to human-readable format - * Usage: {{ "2023-12-02" | postDate }} - * Powered by Luxon: https://moment.github.io/luxon/api-docs/ - */ - eleventyConfig.addFilter("postDate", filterPostDate); - - /* - * πŸ“… ISO Date Formatting Filter - * Converts JavaScript dates to ISO 8601 format - * Usage: {{ "2023-12-02" | isoDate }} - * Powered by Luxon: https://moment.github.io/luxon/api-docs/ - */ - eleventyConfig.addFilter("isoDate", filterIsoDate); - - // ═════════════════════════════════════════════════════════════════════════ - // SHORTCODES - // Generate dynamic content with JavaScript - // Learn more: https://www.11ty.dev/docs/shortcodes/ - // ═════════════════════════════════════════════════════════════════════════ - - /* - * πŸ“† Current Year Shortcode - * Outputs the current year (useful for copyright notices) - * Usage: {% year %} - * Updates automatically with each build - */ - eleventyConfig.addShortcode("year", () => `${new Date().getFullYear()}`); - - // ═════════════════════════════════════════════════════════════════════════ - // BUILD CONFIGURATION - // Define input/output directories and template engine - // ═════════════════════════════════════════════════════════════════════════ - - return { - dir: { - input: "src", // Source files directory - output: "public", // Build output directory - includes: "_includes", // Partial templates directory - data: "_data", // Global data files directory - }, - htmlTemplateEngine: "njk", // Nunjucks for HTML templates - }; + // ═════════════════════════════════════════════════════════════════════════ + // LANGUAGES + // Using Eleventy's build events to process non-template languages + // Learn more: https://www.11ty.dev/docs/events/ + // ═════════════════════════════════════════════════════════════════════════ + + /* + * JavaScript & CSS Processing + * These processors handle bundling, transpiling, and minification + * - JavaScript: Compiled with esbuild for modern bundling + * - CSS/LESS: Processed and minified for production, including a PostCSS pipeline + */ + eleventyConfig.on("eleventy.after", javascript); + eleventyConfig.on("eleventy.after", less); + + // ═════════════════════════════════════════════════════════════════════════ + // PLUGINS + // Extend Eleventy with additional functionality + // Learn more: https://www.11ty.dev/docs/plugins/ + // ═════════════════════════════════════════════════════════════════════════ + + /* + * πŸ–ΌοΈ Image Optimization + * Resize and optimize images for better performance using {% getUrl %} + * Documentation: https://github.com/CodeStitchOfficial/eleventy-plugin-sharp-images + */ + eleventyConfig.addPlugin(pluginImages, configImages); + + /* + * πŸ—ΊοΈ Sitemap Generation + * Creates sitemap.xml automatically using domain from _data/client.json + * Documentation: https://github.com/quasibit/eleventy-plugin-sitemap + */ + eleventyConfig.addPlugin(pluginSitemap, configSitemap); + + /* + * πŸ“¦ Production Minification + * Minifies HTML, CSS, JSON, XML, XSL, and webmanifest files + * Only runs during production builds (npm run build) + * Documentation: https://github.com/CodeStitchOfficial/eleventy-plugin-minify + */ + if (isProduction) { + eleventyConfig.addPlugin(pluginMinifier); + } + + // ═════════════════════════════════════════════════════════════════════════ + // PASSTHROUGH COPIES + // Copy files directly to output without processing + // Learn more: https://www.11ty.dev/docs/copy/ + // ═════════════════════════════════════════════════════════════════════════ + + eleventyConfig.addPassthroughCopy("./src/assets"); // Static assets + eleventyConfig.addPassthroughCopy("./src/admin"); // CMS admin files + eleventyConfig.addPassthroughCopy("./src/_redirects"); // Redirect rules + + // ═════════════════════════════════════════════════════════════════════════ + // FILTERS + // Transform data in templates at build time + // Learn more: https://www.11ty.dev/docs/filters/ + // ═════════════════════════════════════════════════════════════════════════ + + // Custom filter to convert file slug to title case (e.g., about-us -> About Us) + eleventyConfig.addFilter("titleCase", filterTitleCase); + + /* + * πŸ“… Human-Readable Date Formatting Filter + * Converts JavaScript dates to human-readable format + * Usage: {{ "2023-12-02" | postDate }} + * Powered by Luxon: https://moment.github.io/luxon/api-docs/ + */ + eleventyConfig.addFilter("postDate", filterPostDate); + + /* + * πŸ“… ISO Date Formatting Filter + * Converts JavaScript dates to ISO 8601 format + * Usage: {{ "2023-12-02" | isoDate }} + * Powered by Luxon: https://moment.github.io/luxon/api-docs/ + */ + eleventyConfig.addFilter("isoDate", filterIsoDate); + + // ═════════════════════════════════════════════════════════════════════════ + // SHORTCODES + // Generate dynamic content with JavaScript + // Learn more: https://www.11ty.dev/docs/shortcodes/ + // ═════════════════════════════════════════════════════════════════════════ + + /* + * πŸ“† Current Year Shortcode + * Outputs the current year (useful for copyright notices) + * Usage: {% year %} + * Updates automatically with each build + */ + eleventyConfig.addShortcode("year", () => `${new Date().getFullYear()}`); + + // ═════════════════════════════════════════════════════════════════════════ + // BUILD CONFIGURATION + // Define input/output directories and template engine + // ═════════════════════════════════════════════════════════════════════════ + + return { + dir: { + input: "src", // Source files directory + output: "public", // Build output directory + includes: "_includes", // Partial templates directory + data: "_data", // Global data files directory + }, + htmlTemplateEngine: "njk", // Nunjucks for HTML templates + }; }; diff --git a/package.json b/package.json index aa214e5b..f7997322 100644 --- a/package.json +++ b/package.json @@ -1,45 +1,46 @@ { - "name": "intermediate-website-kit-less", - "version": "2.0.1", - "description": "The official CodeStitch Intermediate kit, featuring 11ty, Decap CMS and LESS - all set up for you! Perfect for websites of all sizes.", - "main": "index.js", - "scripts": { - "watch:cms": "npx decap-server", - "watch:eleventy": "cross-env ELEVENTY_ENV=DEV eleventy --serve", - "build:eleventy": "cross-env ELEVENTY_ENV=PROD eleventy", - "start": "run-p watch:*", - "build": "run-s build:*", - "preview": "cross-env ELEVENTY_ENV=PROD eleventy --serve", - "remove-dark-mode": "node scripts/remove-dark-mode.js", - "remove-decap": "node scripts/remove-decap.js", - "remove-demo": "node scripts/remove-demo.js" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/CodeStitchOfficial/Intermediate-Website-Kit-LESS.git" - }, - "keywords": [], - "author": "", - "license": "ISC", - "bugs": { - "url": "https://github.com/CodeStitchOfficial/Intermediate-Website-Kit-LESS/issues" - }, - "homepage": "https://github.com/CodeStitchOfficial/Intermediate-Website-Kit-LESS#readme", - "dependencies": { - "@11ty/eleventy": "^3.1.2", - "@codestitchofficial/eleventy-plugin-minify": "^1.1.3", - "@codestitchofficial/eleventy-plugin-sharp-images": "^2.2.0", - "@quasibit/eleventy-plugin-sitemap": "^2.2.0", - "autoprefixer": "^10.4.27", - "codestitch-sharp-image-automation": "^0.4.0", - "cross-env": "^10.1.0", - "cssnano": "^7.1.2", - "decap-server": "^3.5.2", - "esbuild": "^0.27.3", - "glob": "^13.0.6", - "less": "^4.5.1", - "netlify-plugin-cache": "^1.0.3", - "npm-run-all2": "^5.0.2", - "postcss": "^8.5.6" - } + "name": "intermediate-website-kit-less", + "version": "2.0.1", + "description": "The official CodeStitch Intermediate kit, featuring 11ty, Decap CMS and LESS - all set up for you! Perfect for websites of all sizes.", + "main": "index.js", + "scripts": { + "watch:cms": "npx decap-server", + "watch:eleventy": "cross-env ELEVENTY_ENV=DEV eleventy --serve", + "build:eleventy": "cross-env ELEVENTY_ENV=PROD eleventy", + "start": "run-p watch:*", + "build": "run-s build:*", + "preview": "cross-env ELEVENTY_ENV=PROD eleventy --serve", + "remove-dark-mode": "node scripts/remove-dark-mode.js", + "remove-decap": "node scripts/remove-decap.js", + "remove-demo": "node scripts/remove-demo.js", + "create-page": "node scripts/create-page.js" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/CodeStitchOfficial/Intermediate-Website-Kit-LESS.git" + }, + "keywords": [], + "author": "", + "license": "ISC", + "bugs": { + "url": "https://github.com/CodeStitchOfficial/Intermediate-Website-Kit-LESS/issues" + }, + "homepage": "https://github.com/CodeStitchOfficial/Intermediate-Website-Kit-LESS#readme", + "dependencies": { + "@11ty/eleventy": "^3.1.2", + "@codestitchofficial/eleventy-plugin-minify": "^1.1.3", + "@codestitchofficial/eleventy-plugin-sharp-images": "^2.2.0", + "@quasibit/eleventy-plugin-sitemap": "^2.2.0", + "autoprefixer": "^10.4.27", + "codestitch-sharp-image-automation": "^0.4.0", + "cross-env": "^10.1.0", + "cssnano": "^7.1.2", + "decap-server": "^3.5.2", + "esbuild": "^0.27.3", + "glob": "^13.0.6", + "less": "^4.5.1", + "netlify-plugin-cache": "^1.0.3", + "npm-run-all2": "^5.0.2", + "postcss": "^8.5.6" + } } diff --git a/scripts/create-page.js b/scripts/create-page.js new file mode 100644 index 00000000..e51c9050 --- /dev/null +++ b/scripts/create-page.js @@ -0,0 +1,35 @@ +const fs = require("fs"); +const path = require("path"); + +const input = process.argv[2]; + +if (!input) { + console.log('Please provide page names. Example: npm run create-page -- "Contact, About, Services"'); + process.exit(1); +} + +const pages = input.split(",").map((p) => p.trim()); + +const templatePath = path.join("src/content/pages", "_template.txt"); +let template = fs.readFileSync(templatePath, "utf8"); + +pages.forEach((page) => { + const slug = page + .toLowerCase() + .replace(/[^a-z0-9\s-]/g, "") + .replace(/\s+/g, "-") + .replace(/-+/g, "-") + .replace(/^-+|-+$/g, ""); + + if (!slug) return; + + const htmlPath = path.join("src/content/pages", `${slug}.html`); + const lessPath = path.join("src/assets/less", `${slug}.less`); + + // const pageTemplate = template.replaceAll("{{PAGE}}", slug); + + fs.writeFileSync(htmlPath, template); + fs.writeFileSync(lessPath, ""); + + console.log(`Created ${htmlPath} and ${lessPath}`); +}); diff --git a/src/config/filters/titleCase.js b/src/config/filters/titleCase.js new file mode 100644 index 00000000..d3bb11ee --- /dev/null +++ b/src/config/filters/titleCase.js @@ -0,0 +1,8 @@ +function filterTitleCase(value) { + return value + .split("-") + .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()) + .join(" "); +} + +module.exports = filterTitleCase; diff --git a/src/content/pages/_template.txt b/src/content/pages/_template.txt index eadf15f3..2f41fd4c 100644 --- a/src/content/pages/_template.txt +++ b/src/content/pages/_template.txt @@ -1,16 +1,33 @@ --- -title: "Page title for and OG tags" -description: "Description for <meta> description and OG tags" -permalink: "/page-path/" +description: "Meta description for the page" image: "OPTIONAL - If an image path is specified here, it will be used for that page's OG image. Useful for blog posts (implemented as standard with this kit)" +eleventyComputed: + title: "{{ page.fileSlug | titleCase }} | {{ client.name }} | {{ client.address.city }}, {{ client.address.state }}" + permalink: "/{{ page.fileSlug | slugify }}/" --- + {% extends "layouts/base.html" %} {% block head %} - <!-- Any page-specific tags that belong in the <head>, such as a page-specific stylesheet --> + + <link rel="stylesheet" href="/assets/css/{{ page.fileSlug }}.css"> + + <!-- Any page-specific tags that belong in the <head> --> + + {% endblock %} {% block body %} + <!-- Page HTML goes here, without a <main> wrapper. The <main> tag is already presented in layouts/base.html --> -{% endblock %} \ No newline at end of file + + <!-- If you want the page to have a "CTA", uncomment the line below --> + + <!-- {% include 'sections/cta.html' %} --> + +{% endblock %} + + + + diff --git a/src/content/pages/about.html b/src/content/pages/about.html index f13e113e..4388d18a 100644 --- a/src/content/pages/about.html +++ b/src/content/pages/about.html @@ -1,9 +1,10 @@ --- -title: "About | Code Stitch Web Designs" +title: "About Us| Code Stitch Web Designs" description: "Meta description for the page" permalink: "/about/" --- + {% extends "layouts/base.html" %} {% block head %}