Super Sale Limited Time 50% OFF for All-Access Plans
Save 50% Now

Webpack has been initialized using a configuration object that does not match the API schema.

Getting the following error trying to follow the instructions at https://preview.keenthemes.com/html/craft/docs/getting-started/build/webpack. I'm following the instructions but at the "npm run build" step I get :

[webpack-cli] Invalid configuration object. Webpack has been initialized using a configuration object that does not match the API schema.

  • configuration[0].entry.js~1widgets.bundle should be a non-empty array. -> All modules are loaded upon startup. The last one is exported.

Here's my Webpack.config, package.json and results from "webpack -v" i

webpack.config.js

const webpack = require("webpack");
const path = require("path");
const fs = require("fs");
const glob = require("glob");
const CopyWebpackPlugin = require("copy-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const TerserJSPlugin = require("terser-webpack-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
const WebpackMessages = require("webpack-messages");
const ExcludeAssetsPlugin = require("webpack-exclude-assets-plugin");
const MergeIntoSingle = require("webpack-merge-and-include-globally/index");
const RtlCssPlugin = require("rtlcss-webpack-plugin");

const dev = false;

// paths
let rootPath = path.resolve(__dirname, "..");
const corePath = rootPath;
const coreSrcPath = corePath + "/src";

// arguments/params from the line command
const args = getParameters();

// get theme name
let theme = getTheme(args);

if (args.indexOf("docs_html") !== -1 || args.indexOf("docs_new_html") !== -1) {
 theme = "docs";
}

if (dev) {
 let f = "";
 if (args.indexOf("docs_new_html") !== -1) {
 f = "new-";
 }
 rootPath = path.resolve(__dirname, "../../../themes/" + theme + "/" + f + "html");
}

// get selected demo
let demo = getDemo();

// under demo paths
const demoPath = rootPath + "/theme";
const distPath = demoPath;
const assetDistPath = distPath + "/assets";
const srcPath = demoPath + "/src";

if (dev) {
 console.log(`Source: ${srcPath.replace(/\\/g, "/")}`);
 console.log(`Output: ${assetDistPath.replace(/\\/g, "/")}`);
}

const extraPlugins = [];
const exclude = [];

const js = args.indexOf("js") !== -1;
const css = args.indexOf("css") !== -1 || args.indexOf("scss") !== -1;

additionalSettings();

importExtraPlugins();

function additionalSettings() {
 if (args.indexOf("rtl") !== -1) {
 // enable rtl for css
 extraPlugins.push(new RtlCssPlugin({
 filename: "[name].rtl.css",
 }));
 }

 if (!js && css) {
 // exclude js files
 exclude.push("\.js$");
 }

 if (js && !css) {
 // exclude css files
 exclude.push("\.s?css$");
 }

 if (exclude.length) {
 // add plugin for exclude assets (js/css)
 extraPlugins.push(new ExcludeAssetsPlugin({
 path: exclude,
 }));
 }
}

function getEntryFiles() {

 const entries = {
 // 3rd party plugins css/js
 "plugins/global/plugins.bundle": ["./webpack/plugins/plugins.js", "./webpack/plugins/plugins.scss"],
 // Theme css/js
 "css/style.bundle": ["./" + path.relative("./", srcPath) + "/sass/style.scss", "./" + path.relative("./", srcPath) + "/sass/plugins.scss"],
 "js/scripts.bundle": "./webpack/scripts" + (demo ? "." + demo : "") + ".js",
 };

 // Custom 3rd party plugins
 (glob.sync("./webpack/{plugins,js}/custom/**/*.+(js)") || []).forEach(file => {
 let loc = file.replace("webpack/", "").replace("./", "");
 loc = loc.replace(".js", ".bundle");
 entries[loc] = "./" + file;
 });

 // Custom JS files from src folder
 (glob.sync(path.relative("./", srcPath) + "/js/custom/**/!(_)*.js") || [])
 .filter(f => {
 // exclude folder with bundle
 return /\/bundle\/.*?\.js/.test(f) === false;
 })
 .forEach(file => {
 entries[file.replace(/.*js\/(.*?)\.js$/ig, "js/$1")] = "./" + file;
 });

 entries["js/widgets.bundle"] = (glob.sync(path.relative("./", srcPath).replaceAll(/\\/g, "/") + "/js/widgets/**/!(_)*.js") || []).map(file => {
 return file.replaceAll(/\\/g, "/");
 });

 if (dev) {
 entries["js/scripts.bundle"] = "./" + path.relative("./", rootPath) + "/tools/webpack/scripts" + (demo ? "." + demo : "") + ".js";

 // Custom 3rd party plugins from theme folder
 (glob.sync("./" + path.relative("./", rootPath) + "/tools/webpack/{plugins,js}/custom/**/*.+(js)") || []).forEach(file => {
 let loc = file.replace(/^.*?webpack/g, "").replace("./", "");
 loc = loc.replace(".js", ".bundle");
 entries[loc] = "./" + file;
 });

 // Custom JS files from core src folder
 (glob.sync(path.relative("./", coreSrcPath) + "/js/custom/**/!(_)*.js") || []).forEach(file => {
 entries[file.replace(/.*js\/(.*?)\.js$/ig, "js/$1")] = "./" + file;
 });

 // Widgets js
 entries["js/widgets.bundle"] = (glob.sync(path.relative("./", coreSrcPath) + "/js/widgets/**/!(_)*.js") || []);
 }

 if (args.indexOf("docs_html") !== -1 || args.indexOf("docs_new_html") !== -1) {
 entries["js/scripts.bundle"] = "./" + path.relative("./", rootPath) + "/src/js/scripts.js";
 }

 return entries;
}

function mainConfig() {
 return {
 // enabled/disable optimizations
 mode: args.indexOf("production") !== -1 ? "production" : "development",
 // console logs output, 
 stats: "errors-warnings",
 /*ignoreWarnings: [{
 module: /esri-leaflet/,
 message: /version/,
 }],*/
 performance: {
 // disable warnings hint
 hints: false,
 },
 optimization: {
 minimize: args.indexOf("production") !== -1,
 // js and css minimizer
 minimizer: [new TerserJSPlugin(), new CssMinimizerPlugin()],
 },
 entry: getEntryFiles(),
 output: {
 // main output path in assets folder
 path: assetDistPath,
 // output path based on the entries" filename
 filename: "[name].js",
 },
 resolve: {
 alias: {
 jquery: path.join(__dirname, "node_modules/jquery/src/jquery"),
 $: path.join(__dirname, "node_modules/jquery/src/jquery"),
 "@": [demoPath, corePath],
 "handlebars": "handlebars/dist/handlebars.js",
 "@form-validation": (dev ? coreSrcPath : srcPath) + "/plugins/@form-validation/cjs",
 },
 extensions: [".js", ".scss"],
 fallback: {
 util: false,
 },
 },
 // devtool: "source-map",
 plugins: [
 new WebpackMessages({
 name: theme,
 logger: str => console.log(`>> ${str}`),
 }),
 // create css file
 new MiniCssExtractPlugin({
 filename: "[name].css",
 }),
 new CopyWebpackPlugin({
 patterns: copyFolders(),
 }),
 ].concat(extraPlugins),
 module: {
 rules: [
 {
 test: /\.css$/,
 use: [
 MiniCssExtractPlugin.loader,
 "css-loader",
 ],
 },
 {
 test: /\.scss$/,
 use: [
 MiniCssExtractPlugin.loader,
 {
 loader: "css-loader",
 },
 {
 loader: "sass-loader",
 options: {
 // Prefer `dart-sass`
 implementation: require("sass"),
 sourceMap: false,
 sassOptions: {
 includePaths: [
 demoPath,
 path.resolve(__dirname, "node_modules"),
 ],
 },
 },
 },
 ],
 },
 {
 test: /\.(ttf|otf|eot|svg|woff(2)?)(\?[a-z0-9]+)?$/,
 type: "asset/resource",
 generator: {
 filename: "./plugins/global/fonts/[name][ext]"
 }
 },
 {
 test: /\.(gif|png|jpe?g)$/,
 type: "asset/resource",
 generator: {
 filename: "./plugins/custom/images/[name][ext]"
 },
 },
 // {
 // // for demo8 image in scss
 // test: /\.(gif|png|jpe?g)$/,
 // use: [
 // {
 // loader: "url-loader",
 // options: {
 // emitFile: false,
 // name: "[path][name].[ext]",
 // publicPath: (url, resourcePath, context) => {
 // return "../";
 // },
 // },
 // },
 // ],
 // },
 ],
 },
 // webpack dev server config
 devServer: {
 static: {
 directory: distPath,
 },
 compress: true,
 port: 8080,
 },
 };
}

function copyFolders() {
 let options = [
 {
 // copy media
 from: srcPath + "/media",
 to: assetDistPath + "/media",
 },
 {
 // copy tinymce skins
 from: path.resolve(__dirname, "node_modules") + "/tinymce/skins",
 to: assetDistPath + "/plugins/custom/tinymce/skins",
 },
 {
 // copy tinymce plugins
 from: path.resolve(__dirname, "node_modules") + "/tinymce/plugins",
 to: assetDistPath + "/plugins/custom/tinymce/plugins",
 }
 ];

 if (fs.existsSync(coreSrcPath + "/media/plugins/jstree")) {
 options.push({
 // copy jstree image
 from: coreSrcPath + "/media/plugins/jstree",
 to: assetDistPath + "/plugins/custom/jstree",
 force: true
 });
 }

 if (dev) {
 options.push({
 // copy media from core
 from: coreSrcPath + "/media",
 to: assetDistPath + "/media",
 });
 }

 return options;
}

function getParameters() {
 var args = [];
 Object.keys(process.env).forEach(function (key) {
 if (key.startsWith("npm_config_")) {
 var arg = key.substring("npm_config_".length);
 args.push(arg);
 }
 });

 if ("production" === process.env["NODE_ENV"]) {
 args.push("production");
 }

 return args;
}

function importExtraPlugins() {
 // Optional: Import datatables.net
 extraPlugins.push(new MergeIntoSingle({
 files: {
 "plugins/custom/datatables/datatables.bundle.js": [
 "node_modules/datatables.net/js/dataTables.js",
 "node_modules/datatables.net-bs5/js/dataTables.bootstrap5.js",
 "../src/js/vendors/plugins/datatables.init.js",
 "node_modules/jszip/dist/jszip.min.js",
 "node_modules/pdfmake/build/pdfmake.min.js",
 "node_modules/pdfmake/build/vfs_fonts.js",
 "node_modules/datatables.net-buttons/js/dataTables.buttons.min.js",
 "node_modules/datatables.net-buttons-bs5/js/buttons.bootstrap5.min.js",
 "node_modules/datatables.net-buttons/js/buttons.colVis.js",
 "node_modules/datatables.net-buttons/js/buttons.flash.js",
 "node_modules/datatables.net-buttons/js/buttons.html5.js",
 "node_modules/datatables.net-buttons/js/buttons.print.js",
 "node_modules/datatables.net-colreorder/js/dataTables.colReorder.min.js",
 "node_modules/datatables.net-colreorder-bs5/js/colReorder.bootstrap5.js",
 "node_modules/datatables.net-fixedcolumns/js/dataTables.fixedColumns.min.js",
 "node_modules/datatables.net-fixedcolumns-bs5/js/fixedColumns.bootstrap5.js",
 "node_modules/datatables.net-fixedheader/js/dataTables.fixedHeader.min.js",
 "node_modules/datatables.net-fixedheader-bs5/js/fixedHeader.bootstrap5.js",
 "node_modules/datatables.net-responsive/js/dataTables.responsive.min.js",
 "node_modules/datatables.net-responsive-bs5/js/responsive.bootstrap5.min.js",
 "node_modules/datatables.net-rowgroup/js/dataTables.rowGroup.min.js",
 "node_modules/datatables.net-rowgroup-bs5/js/rowGroup.bootstrap5.js",
 "node_modules/datatables.net-rowreorder/js/dataTables.rowReorder.min.js",
 "node_modules/datatables.net-rowreorder-bs5/js/rowReorder.bootstrap5.js",
 "node_modules/datatables.net-scroller/js/dataTables.scroller.min.js",
 "node_modules/datatables.net-scroller-bs5/js/dataTables.bootstrap5.js",
 "node_modules/datatables.net-select/js/dataTables.select.min.js",
 "node_modules/datatables.net-select-bs5/js/dataTables.bootstrap5.js",
 "node_modules/datatables.net-datetime/dist/dataTables.dateTime.min.js",
 ],
 "plugins/custom/datatables/pdfmake.min.js.map": [
 "node_modules/pdfmake/build/pdfmake.min.js.map",
 ],
 "plugins/custom/datatables/datatables.bundle.css": [
 "node_modules/datatables.net-bs5/css/dataTables.bootstrap5.css",
 "node_modules/datatables.net-buttons-bs5/css/buttons.bootstrap5.min.css",
 "node_modules/datatables.net-colreorder-bs5/css/colReorder.bootstrap5.min.css",
 "node_modules/datatables.net-fixedcolumns-bs5/css/fixedColumns.bootstrap5.min.css",
 "node_modules/datatables.net-fixedheader-bs5/css/fixedHeader.bootstrap5.min.css",
 "node_modules/datatables.net-responsive-bs5/css/responsive.bootstrap5.min.css",
 "node_modules/datatables.net-rowreorder-bs5/css/rowReorder.bootstrap5.min.css",
 "node_modules/datatables.net-scroller-bs5/css/scroller.bootstrap5.min.css",
 "node_modules/datatables.net-select-bs5/css/select.bootstrap5.min.css",
 "node_modules/datatables.net-datetime/dist/dataTables.dateTime.min.css",
 ],

 // fullcalendar
 "plugins/custom/fullcalendar/fullcalendar.bundle.js": [
 "node_modules/fullcalendar/main.js",
 "node_modules/fullcalendar/locales-all.min.js",
 ],
 "plugins/custom/fullcalendar/fullcalendar.bundle.css": [
 "node_modules/fullcalendar/main.min.css",
 ],
 },
 }));
}

function getTheme() {

 const excludedKeys = [
 "npm_config_cache",
 "npm_config_globalconfig",
 "npm_config_global_prefix",
 "npm_config_init_module",
 "npm_config_local_prefix",
 "npm_config_metrics_registry",
 "npm_config_node_gyp",
 "npm_config_noproxy",
 "npm_config_prefix",
 "npm_config_userconfig",
 "npm_config_user_agent",
 "npm_config_npm_version",
 ];

 const key = Object.keys(process.env)
 .filter(element => !element.match(/npm_config_(demo\d+)$/))
 .filter(key => !excludedKeys.includes(key))
 .find(element => element.match(/npm_config_.*?/));

 if (key) {
 return key.replace("npm_config_", "");
 }

 return null;
}

function getDemo() {
 const key = Object.keys(process.env).find(element => element.match(/npm_config_(demo\d+)$/));

 let demo = null;

 if (key) {
 demo = key.replace("npm_config_", "");
 }

 return demo;
}

module.exports = () => {
 return [mainConfig()];
};

package.json

{
 "name": "keenthemes",
 "version": "1.1.6",
 "author": "Keenthemes",
 "homepage": "https://keenthemes.com/",
 "description": "Packages used by yarn, npm, gulp and webpack",
 "main": "gulpfile.js",
 "dependencies": {
 "@ckeditor/ckeditor5-alignment": "42.0.2",
 "@ckeditor/ckeditor5-build-balloon": "42.0.2",
 "@ckeditor/ckeditor5-build-balloon-block": "42.0.2",
 "@ckeditor/ckeditor5-build-classic": "42.0.2",
 "@ckeditor/ckeditor5-build-decoupled-document": "42.0.2",
 "@ckeditor/ckeditor5-build-inline": "42.0.2",
 "@eonasdan/tempus-dominus": "^6.9.9",
 "@fortawesome/fontawesome-free": "^6.6.0",
 "@popperjs/core": "2.11.8",
 "@shopify/draggable": "^1.1.3",
 "@yaireo/tagify": "^4.27.0",
 "acorn": "^8.12.1",
 "apexcharts": "3.51.0",
 "autosize": "^6.0.1",
 "axios": "^1.7.2",
 "bootstrap": "5.3.3",
 "bootstrap-cookie-alert": "^1.2.2",
 "bootstrap-daterangepicker": "^3.1.0",
 "bootstrap-icons": "^1.11.3",
 "bootstrap-maxlength": "^1.10.1",
 "bootstrap-multiselectsplitter": "^1.0.4",
 "chalk": "^5.3.0",
 "chart.js": "^4.4.3",
 "clipboard": "^2.0.11",
 "countup.js": "^2.8.0",
 "cropperjs": "^1.6.2",
 "datatables.net": "^2.1.2",
 "datatables.net-bs5": "^2.1.2",
 "datatables.net-buttons": "^3.1.0",
 "datatables.net-buttons-bs5": "^3.1.0",
 "datatables.net-colreorder": "^2.0.3",
 "datatables.net-colreorder-bs5": "^2.0.3",
 "datatables.net-datetime": "^1.5.3",
 "datatables.net-fixedcolumns": "^5.0.0",
 "datatables.net-fixedcolumns-bs5": "^5.0.0",
 "datatables.net-fixedheader": "^4.0.1",
 "datatables.net-fixedheader-bs5": "^4.0.1",
 "datatables.net-plugins": "^2.0.8",
 "datatables.net-responsive": "^3.0.2",
 "datatables.net-responsive-bs5": "^3.0.2",
 "datatables.net-rowgroup": "^1.5.0",
 "datatables.net-rowgroup-bs5": "^1.5.0",
 "datatables.net-rowreorder": "^1.5.0",
 "datatables.net-rowreorder-bs5": "^1.5.0",
 "datatables.net-scroller": "^2.4.3",
 "datatables.net-scroller-bs5": "^2.4.3",
 "datatables.net-select": "^2.0.3",
 "datatables.net-select-bs5": "^2.0.3",
 "dropzone": "^5.9.3",
 "es6-promise": "^4.2.8",
 "es6-promise-polyfill": "^1.2.0",
 "es6-shim": "^0.35.8",
 "esri-leaflet": "^3.0.12",
 "esri-leaflet-geocoder": "^3.1.4",
 "flatpickr": "^4.6.13",
 "flot": "^4.2.6",
 "fslightbox": "^3.4.1",
 "fullcalendar": "^5.8.0",
 "handlebars": "^4.7.8",
 "inputmask": "^5.0.9",
 "jkanban": "^1.3.1",
 "jquery": "3.7.1",
 "jquery.repeater": "^1.2.1",
 "jstree": "^3.3.16",
 "jszip": "^3.10.1",
 "leaflet": "^1.9.4",
 "line-awesome": "^1.3.0",
 "lozad": "^1.16.0",
 "moment": "^2.30.1",
 "nouislider": "^15.8.1",
 "npm": "^10.8.2",
 "pdfmake": "^0.2.10",
 "prism-themes": "^1.9.0",
 "prismjs": "^1.29.0",
 "quill": "^2.0.2",
 "select2": "^4.1.0-rc.0",
 "smooth-scroll": "^16.1.3",
 "sweetalert2": "11.4.8",
 "tiny-slider": "^2.9.4",
 "tinymce": "7.2.1",
 "toastr": "^2.1.4",
 "typed.js": "2.1.0",
 "vis-timeline": "^7.7.3",
 "wnumb": "^1.2.0"
 },
 "devDependencies": {
 "@babel/core": "^7.24.7",
 "@babel/runtime": "^7.24.7",
 "copy-webpack-plugin": "^12.0.2",
 "css-loader": "^7.1.2",
 "css-minimizer-webpack-plugin": "^7.0.0",
 "del": "^7.1.0",
 "extract-loader": "^5.1.0",
 "file-loader": "^6.2.0",
 "fs-extra": "^11.2.0",
 "glob": "^10.4.2",
 "gulp": "4.0.2",
 "gulp-clean-css": "^4.3.0",
 "gulp-concat": "^2.6.1",
 "gulp-connect": "^5.7.0",
 "gulp-dart-sass": "^1.1.0",
 "gulp-if": "^3.0.0",
 "gulp-rename": "^2.0.0",
 "gulp-rewrite-css": "^1.1.2",
 "gulp-rtlcss": "^2.0.0",
 "gulp-sourcemaps": "^3.0.0",
 "gulp-terser": "^2.1.0",
 "imports-loader": "^5.0.0",
 "lazypipe": "^1.0.2",
 "mini-css-extract-plugin": "^2.9.0",
 "postcss-loader": "^8.1.1",
 "replace-in-file-webpack-plugin": "^1.0.6",
 "rtlcss-webpack-plugin": "^4.0.7",
 "sass-loader": "^14.2.1",
 "terser-webpack-plugin": "^5.3.10",
 "url-loader": "^4.1.1",
 "webpack-cli": "^5.1.4",
 "webpack-dev-server": "^5.0.4",
 "webpack-exclude-assets-plugin": "^0.1.1",
 "webpack-log": "^3.0.2",
 "webpack-merge-and-include-globally": "^2.3.4",
 "webpack-messages": "^2.0.4",
 "yargs": "^17.7.2"
 },
 "scripts": {
 "test": "echo \"Error: no test specified\" && exit 1",
 "build": "webpack",
 "watch": "webpack --watch",
 "localhost": "webpack serve",
 "sync": "node sync.js"
 },
 "overrides": {
 "gulp-dart-sass": {
 "sass": "1.70.0"
 }
 },
 "resolutions": {
 "gulp-dart-sass/sass": "1.70.0"
 }
}

Output from "webpack -v" System: OS: Windows 11 10.0.26100 CPU: (14) x64 Intel(R) Core(TM) Ultra 7 155U Memory: 19.63 GB / 31.48 GB Binaries: Node: 22.14.0 - C:\Program Files\nodejs\node.EXE Yarn: 1.22.22 - ~\AppData\Roaming\npm\yarn.CMD npm: 10.9.2 - C:\Program Files\nodejs\npm.CMD Browsers: Edge: Chromium (132.0.2957.140) Packages: copy-webpack-plugin: ^12.0.2 => 12.0.2 css-loader: ^7.1.2 => 7.1.2 css-minimizer-webpack-plugin: ^7.0.0 => 7.0.0 extract-loader: ^5.1.0 => 5.1.0 file-loader: ^6.2.0 => 6.2.0 imports-loader: ^5.0.0 => 5.0.0 postcss-loader: ^8.1.1 => 8.1.1 replace-in-file-webpack-plugin: ^1.0.6 => 1.0.6 rtlcss-webpack-plugin: ^4.0.7 => 4.0.7 sass-loader: ^14.2.1 => 14.2.1 terser-webpack-plugin: ^5.3.10 => 5.3.14 url-loader: ^4.1.1 => 4.1.1 webpack-cli: ^5.1.4 => 5.1.4 webpack-dev-server: ^5.0.4 => 5.0.4 webpack-exclude-assets-plugin: ^0.1.1 => 0.1.1 webpack-log: ^3.0.2 => 3.0.2 webpack-merge-and-include-globally: ^2.3.4 => 2.3.4 webpack-messages: ^2.0.4 => 2.0.4

I already tried getting support here https://devs.keenthemes.com/question/webpack-errors-with-craft-theme , but for some reason the thread died. I'm really hoping you give the support you market. Also, your contact us form is broken.

Text formatting options
Submit
Click any option to insert into your comment. Select text first to wrap it.
  • **text** to make things bold
  • *text* to emphasize
  • ### Heading to make headings
  • [link text](url) for links
  • ![alt text](image-url) to paste in an image
  • - item to make a list
  • 1. item to make an ordered list
  • > quote to quote somebody
  • `code` for single line of code
  • ```js ... ``` for JS code block
  • ```html ... ``` for HTML code block
  • ```scss ... ``` for SCSS code block
  • ```php ... ``` for PHP code block
  • --- for a horizontal rule
  • happy  :)
  • shocked  :|
  • sad  :(

Replies (1)


Hi

Sorry for the delay in getting back to you. Could you check our latest reply and the issue mentioned there? Let us know if you're still facing any problems.

Link

Thanks


Text formatting options
Submit
Click any option to insert into your comment. Select text first to wrap it.
  • **text** to make things bold
  • *text* to emphasize
  • ### Heading to make headings
  • [link text](url) for links
  • ![alt text](image-url) to paste in an image
  • - item to make a list
  • 1. item to make an ordered list
  • > quote to quote somebody
  • `code` for single line of code
  • ```js ... ``` for JS code block
  • ```html ... ``` for HTML code block
  • ```scss ... ``` for SCSS code block
  • ```php ... ``` for PHP code block
  • --- for a horizontal rule
  • happy  :)
  • shocked  :|
  • sad  :(
Text formatting options
Submit
Click any option to insert into your comment. Select text first to wrap it.
  • **text** to make things bold
  • *text* to emphasize
  • ### Heading to make headings
  • [link text](url) for links
  • ![alt text](image-url) to paste in an image
  • - item to make a list
  • 1. item to make an ordered list
  • > quote to quote somebody
  • `code` for single line of code
  • ```js ... ``` for JS code block
  • ```html ... ``` for HTML code block
  • ```scss ... ``` for SCSS code block
  • ```php ... ``` for PHP code block
  • --- for a horizontal rule
  • happy  :)
  • shocked  :|
  • sad  :(