# HBS (Motor de plantilla)
- Alternativa a EJS
- https://handlebarsjs.com/
# HBS y Express
https://www.npmjs.com/package/hbs
npm i hbs
// Configuración inicial
const express = require("express");
const app = express();
const port = process.env.PORT || 3001;
// Motor de plantilla
const hbs = require('hbs');
hbs.registerPartials(__dirname + '/views/partials', function (err) {});
app.set('view engine', 'hbs');
app.set("views", __dirname + "/views");
app.use(express.static(__dirname + "/public"));
// Aquí detallar rutas
// Iniciar servidor
app.listen(port, () => {
  console.log(`Example app listening at http://localhost:${port}`);
});
Crear carpeta views y un index.hbs
# Extensión VSC
https://marketplace.visualstudio.com/items?itemName=RuhanRK.hbs-snippets
# Nodemon hbs
Por defecto nodemon no detectará los cambios de los archivos con extensión .hbs
Crear nodemon.json en la carpeta raíz
{
    "ext": "js,json,hbs"
}
Ahora si ejecutar:
nodemon app
# Rutas render
Para que Express renderice este arhivo y lo combierta en HTML utilizamos:
app.get("/", (req, res) => {
  res.render('index', {titulo: '<h1>Inicio con HBS</h1>'})
});
app.get("/equipo", (req, res) => {
    res.render('equipo', {
        equipo: [
            {
                id: 1,
                nombre: 'Juanito',
                habilidad: ['Javascript', 'Node.js']
            },
            {
                id: 2,
                nombre: 'Pedrito',
                habilidad: ['Php', 'Laravel']
            }
        ]
    })
});
app.get('/servicio', (req, res) => {
    res.render('servicio', {
        servicio: {
            estado: false,
            nombre: 'Servicio de programación'
        }
    })
})
app.use((req, res, next) => {
    res.status(404).render("404", {
        titulo: "404",
        descripcion: "Página no encontrada"
    })
})
index.hbs
<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Título dinámico próximamente...</title>
</head>
<body>
    <p>
        {{titulo}}
    </p>
</body>
</html>
# partials
https://handlebarsjs.com/guide/partials.html
WARNING
Todo esto funciona si tenemos configurado:
hbs.registerPartials(__dirname + '/views/partials', function (err) {});
Estamos repitiendo código HTML por ende podemos optimizarlo:
partials/header.hbs
<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{{title}}</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous">
</head>
<body class="container">
    <h1 class="mt-5">HBS</h1>
    <hr>
partials/footer.hbs
    <div>Footer: {{year}}</div>
</body>
</html>
index.hbs
# CSS, JS, img, etc
Como ya tenemos configurada nuestra carpeta public, es ahí donde añadimos los archivos en cuestión.
Ejemplo para css bootstrap: public/css/archivo.css
<link rel="stylesheet" href="/css/bootstrap.min.css">
Ejemplo para JS bootstrap: public/js/archivo.js
<script src="/js/bootstrap.min.js"></script>
# If
https://handlebarsjs.com/guide/builtin-helpers.html#if
# Each
https://handlebarsjs.com/guide/builtin-helpers.html#each
# 404
// al final de todas nuestras rutas
app.use((req, res, next) => {
    res.status(404).render("404", {
        titulo: "404",
        descripcion: "Página no encontrada"
    })
})
# Extra Material Kit
Llevar a la carpeta public los assets descargados, tanto de js y css:
- public\css\material-kit.css
- public\js\core\bootstrap-material-design.min.js
- public\js\core\jquery.min.js
- public\js\core\popper.min.js
- public\js\plugins\bootstrap-datetimepicker.js
- public\js\plugins\moment.min.js
- public\js\plugins\nouislider.min.js
- public\js\material-kit.js
Fonts and Icons
<!-- Fonts and icons -->
<link rel="stylesheet" type="text/css" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700|Roboto+Slab:400,700|Material+Icons" />
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/latest/css/font-awesome.min.css">
header.hbs
<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{{title}}</title>
    {{!-- <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous"> --}}
    <!-- Fonts and icons -->
    <link rel="stylesheet" type="text/css" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700|Roboto+Slab:400,700|Material+Icons" />
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/latest/css/font-awesome.min.css">
    {{!-- Materialkit --}}
    <link rel="stylesheet" href="/css/material-kit.min.css">
</head>
<body class="container">
    {{> navbar}}
    <h1 class="mt-5">HBS</h1>
    <hr>
footer.hbs
    <div>Footer: {{year}}</div>
<!--   Core JS Files   -->
<script src="/js/core/jquery.min.js" type="text/javascript"></script>
<script src="/js/core/popper.min.js" type="text/javascript"></script>
<script src="/js/core/bootstrap-material-design.min.js" type="text/javascript"></script>
<script src="/js/plugins/moment.min.js"></script>
<!--	Plugin for the Datepicker, full documentation here: https://github.com/Eonasdan/bootstrap-datetimepicker -->
<script src="/js/plugins/bootstrap-datetimepicker.js" type="text/javascript"></script>
<!--  Plugin for the Sliders, full documentation here: http://refreshless.com/nouislider/ -->
<script src="/js/plugins/nouislider.min.js" type="text/javascript"></script>
<!-- Control Center for Material Kit: parallax effects, scripts for the example pages etc -->
<script src="/js/material-kit.js" type="text/javascript"></script></body>
</body>
</html>
navbar.hbs
<nav class="navbar bg-primary navbar-expand-lg">
  <div class="container">
      <div class="navbar-translate">
        <a class="navbar-brand" href="https://demos.creative-tim.com/material-kit/index.html">
          Material Kit </a>
        <button class="navbar-toggler" type="button" data-toggle="collapse" aria-expanded="false" aria-label="Toggle navigation">
            <span class="sr-only">Toggle navigation</span>
            <span class="navbar-toggler-icon"></span>
            <span class="navbar-toggler-icon"></span>
            <span class="navbar-toggler-icon"></span>
        </button>
      </div>
      <div class="collapse navbar-collapse">
          <ul class="navbar-nav ml-auto">
            <li class="nav-item">
                <a href="/" class="nav-link">
                    <i class="material-icons">apps</i> Inicio
                </a>
            </li>
            <li class="nav-item">
                <a href="/equipo" class="nav-link">
                    <i class="material-icons">apps</i> Equipo
                </a>
            </li>
            <li class="nav-item">
                <a href="/servicio" class="nav-link">
                    <i class="material-icons">apps</i> Servicio
                </a>
            </li>
          </ul>
      </div>
  </div>
</nav>
login.hbs (Próximamente...)
# Despliegue Heroku
Vamos a subir nuestra aplicación a un hosting real, para ello utilizaremos Heroku: https://www.heroku.com/pricing
# Crear cuenta gratis
# Cambiar puerto
https://help.heroku.com/P1AVPANS/why-is-my-node-js-app-crashing-with-an-r10-error
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
    console.log(`Our app is running on port ${ PORT }`);
});
# Agregar Script package.json
"scripts": {
    "start": "node app"
  },
# .gitignore
Crear archivo .gitignore
node_modules
# Heroku cli
https://devcenter.heroku.com/articles/heroku-cli
# Heroku GIT
heroku login
git init
heroku git:remote -a nombre-de-su-proyecto
git add .
git commit -am "make it better"
git push heroku master
# Bailar y compartir tu web en los comentarios de Youtube
