├── Procfile ├── src ├── views │ ├── error.hbs │ ├── index.hbs │ ├── template.hbs │ └── partials │ │ └── intro.hbs └── routes │ ├── api │ └── locales.js │ └── index.js ├── static ├── css │ ├── styles.scss │ ├── _mixins.scss │ └── _base.scss └── js │ ├── templates │ └── helpers.js │ └── app.js ├── .travis.yml ├── config.json ├── test └── specs │ └── sample.test.js ├── locales └── en-us.json ├── .gitignore ├── .prettierrc ├── app.json ├── Makefile ├── LICENSE ├── package.json ├── web.js └── README.md /Procfile: -------------------------------------------------------------------------------- 1 | web: node web.js 2 | -------------------------------------------------------------------------------- /src/views/error.hbs: -------------------------------------------------------------------------------- 1 |
{{__ description}}
4 | 5 | {{else}} 6 | 7 |Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna 8 | aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. 9 | Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur 10 | sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
11 | 12 | {{/if}} 13 | 14 | {{#ifCond true true}} 15 | 16 |Handlebars helpers successfully loaded.
17 | 18 | {{/ifCond}} 19 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | BIN=node_modules/.bin 2 | 3 | start: 4 | $(BIN)/concurrently --kill-others --timestamp-format "HH:mm:ss" --prefix "[{index}] {time}" "make serve" "make watch" 5 | 6 | serve: 7 | $(BIN)/nodemon web.js --ignore static/ --ignore test/ 8 | 9 | build: 10 | mkdir -p static/js/templates 11 | $(BIN)/handlebars src/views/ -f static/js/templates/views.min.js -e hbs -c handlebars 12 | $(BIN)/handlebars src/views/partials/ -f static/js/templates/partials.min.js -p -e hbs -c handlebars 13 | $(BIN)/spire-of-babel static/js/app.js --bundle --sourcemap > static/build.min.js 14 | $(BIN)/node-sass static/css/styles.scss static/css/styles.css 15 | 16 | watch: 17 | make build 18 | $(BIN)/onchange 'src/views/**/*.hbs' 'static/css/**/*.scss' 'static/js/**/*.js' -e 'static/**/*.min.*' -- make build 19 | -------------------------------------------------------------------------------- /static/js/app.js: -------------------------------------------------------------------------------- 1 | const Handlebars = require('handlebars'); 2 | 3 | require('./templates/helpers.js')(Handlebars); 4 | require('./templates/views.min.js'); 5 | require('./templates/partials.min.js'); 6 | 7 | let locales = {}; 8 | 9 | Handlebars.registerHelper('__', key => { 10 | if (locales[key]) { 11 | return locales[key]; 12 | } 13 | 14 | return key; 15 | }); 16 | 17 | const renderView = (view, data) => { 18 | document.querySelector('.contents').innerHTML = Handlebars.templates[view]( 19 | data 20 | ); 21 | }; 22 | 23 | fetch('/api/locales') 24 | .then(response => response.json()) 25 | .then(data => { 26 | locales = data; 27 | 28 | renderView('index', { 29 | description: 30 | 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.', 31 | title: 'Hello, world.' 32 | }); 33 | }); 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2020 Scott Doxey 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@neogeek/nodejs-starter-kit", 3 | "version": "0.0.1", 4 | "description": "This repo is a starter kit for working with Node.js, Handlebars, Sass, and Babel.", 5 | "engines": { 6 | "node": ">=12.0" 7 | }, 8 | "main": "web.js", 9 | "license": "MIT", 10 | "dependencies": { 11 | "body-parser": "1.19.0", 12 | "compression": "1.7.4", 13 | "cors": "2.8.5", 14 | "express": "4.17.1", 15 | "express-enrouten": "1.3.0", 16 | "express-hbs": "2.3.4", 17 | "express-session": "1.17.1", 18 | "handlebars": "4.7.6", 19 | "i18n": "0.13.2", 20 | "node-sass": "4.14.1", 21 | "spire-of-babel": "2.0.1" 22 | }, 23 | "devDependencies": { 24 | "codecov": "3.7.2", 25 | "concurrently": "5.3.0", 26 | "jest": "26.4.2", 27 | "nodemon": "2.0.4", 28 | "onchange": "7.0.2" 29 | }, 30 | "scripts": { 31 | "postinstall": "make build", 32 | "start": "node web.js", 33 | "coverage": "jest --coverage --verbose=true", 34 | "test": "jest --verbose=true" 35 | }, 36 | "keywords": [ 37 | "node", 38 | "babel", 39 | "express", 40 | "handlebars", 41 | "mocha", 42 | "sass" 43 | ], 44 | "repository": { 45 | "type": "git", 46 | "url": "git://github.com/neogeek/nodejs-starter-kit.git" 47 | }, 48 | "private": true 49 | } 50 | -------------------------------------------------------------------------------- /web.js: -------------------------------------------------------------------------------- 1 | const config = require('./config.json'); 2 | 3 | const express = require('express'); 4 | const app = express(); 5 | 6 | const cors = require('cors'); 7 | const session = require('express-session'); 8 | const bodyParser = require('body-parser'); 9 | const compression = require('compression'); 10 | 11 | const enrouten = require('express-enrouten'); 12 | 13 | const hbs = require('express-hbs'); 14 | 15 | require('./static/js/templates/helpers.js')(hbs); 16 | 17 | const i18n = require('i18n'); 18 | 19 | i18n.configure({ 20 | defaultLocale: 'en-us', 21 | directory: `${__dirname}/locales`, 22 | indent: ' ', 23 | locales: ['en-us'] 24 | }); 25 | 26 | app.use(i18n.init); 27 | 28 | app.disable('x-powered-by'); 29 | 30 | app.use(cors()); 31 | 32 | app.use( 33 | session({ 34 | resave: true, 35 | saveUninitialized: true, 36 | secret: process.env.SECRET || 'secret' 37 | }) 38 | ); 39 | 40 | app.use(bodyParser.urlencoded({ extended: true })); 41 | app.use(bodyParser.json()); 42 | 43 | app.use(compression()); 44 | 45 | app.use(express.static(`${__dirname}/static`)); 46 | 47 | app.use((req, res, next) => { 48 | res.locals.config = config; 49 | res.locals.layout = 'template'; 50 | res.locals.url = `${req.protocol}://${req.get('host')}${req.originalUrl}`; 51 | 52 | next(); 53 | }); 54 | 55 | app.use(enrouten({ directory: 'src/routes' })); 56 | 57 | app.use((err, req, res, next) => { 58 | res.status(err.status || '500'); 59 | res.render('error', { 60 | message: err.message, 61 | status: err.status || '500' 62 | }); 63 | }); 64 | 65 | app.use((req, res) => { 66 | res.status('404'); 67 | res.render('error', { 68 | message: 'Page Not Found', 69 | status: '404' 70 | }); 71 | }); 72 | 73 | app.engine( 74 | 'hbs', 75 | hbs.express4({ 76 | onCompile: (exhbs, source) => 77 | exhbs.handlebars.compile(source, { preventIndent: true }), 78 | partialsDir: `${__dirname}/src/views/partials` 79 | }) 80 | ); 81 | 82 | app.set('view engine', 'hbs'); 83 | app.set('views', `${__dirname}/src/views`); 84 | 85 | app.listen(process.env.PORT || '5000'); 86 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Node.js Starter Kit 2 | 3 | > This repo is a starter kit for working with [Node.js](http://nodejs.org), [Handlebars](http://handlebarsjs.com) (both server and client side), [Sass](http://sass-lang.com) (via [node-sass](https://github.com/sass/node-sass)), and [Babel](https://babeljs.io/) (via [spire-of-babel](https://github.com/neogeek/spire-of-babel)). 4 | 5 | [](https://travis-ci.org/neogeek/nodejs-starter-kit) 6 | 7 | ## Install to Heroku 8 | 9 | [](https://dashboard.heroku.com/new?template=https%3A%2F%2Fgithub.com%2Fneogeek%2Fnodejs-starter-kit) 10 | 11 | ## Getting Started 12 | 13 | Run the following command to download the repo and unpack it into `nodejs-starter-kit-master/`. 14 | 15 | ```bash 16 | $ curl -L https://github.com/neogeek/nodejs-starter-kit/archive/master.tar.gz | tar -xz 17 | ``` 18 | 19 | All client-side files are located in `/static`. 20 | 21 | Both client and server-side Handlebars templates are stored in `/src/views`. 22 | 23 | ## Building 24 | 25 | The following command will install all Node.js dependencies. Once all dependencies are installed it will run `make build` compiling Handlebars and Sass files. 26 | 27 | ```bash 28 | $ npm install 29 | ``` 30 | 31 | To manually compile Handlebars and Sass files run: 32 | 33 | ```bash 34 | $ make build 35 | ``` 36 | 37 | To watch for changes to any Handlebars or Sass files run: 38 | 39 | ```bash 40 | $ make watch 41 | ``` 42 | 43 | ## Testing 44 | 45 | Tests are powered by [mocha](http://mochajs.org/). To run all tests use this command: 46 | 47 | ```bash 48 | $ npm test 49 | ``` 50 | 51 | A `.travis.yml` configuration file is included to support automated testing through [Travis CI](https://travis-ci.org). 52 | 53 | ## Server 54 | 55 | If you have the [Heroku Toolbelt](https://toolbelt.heroku.com) installed you can start the sample applications with this command: 56 | 57 | ```bash 58 | $ foreman start 59 | ``` 60 | 61 | If not, then the application can also be run using this command: 62 | 63 | ```bash 64 | $ make serve 65 | ``` 66 | 67 | Once the application is running it can be accessed at