Skip to main content

Layout development

Once you have built one or more podlets, you will want to be able to test them in the more realistic context of a layout server, thereby allowing you to see the complete page and make sure all the pieces work together correctly.

The following examples show a somewhat contrived multi-podlet and layout setup in which our layout composes together a header, a navigation area, some content and a footer.

Sample podlets​

Example: header

Create a folder /podlets/header with a file index.js inside to hold the following podlet code.

import Podlet, { html } from "@podium/podlet";
import express from "express";

const app = express();

const podlet = new Podlet({
name: "header",
version: "1.0.0",
development: false,
});

app.use(podlet.middleware());

app.get("/manifest.json", (req, res) => {
res.json(podlet);
});

app.get("/", (req, res) => {
res.podiumSend(html`<header>The Best Podium page ever</header>`);
});

app.listen(7001);

Example: navigation bar

Create a folder /podlets/navigation with a file index.js inside to hold the following podlet code.

import Podlet, { html } from "@podium/podlet";
import express from "express";

const app = express();

const podlet = new Podlet({
name: "navigation",
version: "1.0.0",
development: false,
});

app.use(podlet.middleware());

app.get("/manifest.json", (req, res) => {
res.json(podlet);
});

app.get("/", (req, res) => {
res.podiumSend(html`<nav>
<ul>
<li><a href="/home">home</a></li>
<li><a href="/blog">blog</a></li>
<li><a href="/about">about</a></li>
<li><a href="/contact">contact</a></li>
</ul>
</nav>`);
});

app.listen(7002);

Example: main home page content

Create a folder /podlets/home with a file index.js inside to hold the following podlet code.

import Podlet, { html } from "@podium/podlet";
import express from "express";

const app = express();

const podlet = new Podlet({
name: "homeContent",
version: "1.0.0",
development: false,
});

app.use(podlet.middleware());

app.get("/manifest.json", (req, res) => {
res.json(podlet);
});

app.get("/", (req, res) => {
res.podiumSend(html`<section>Welcome to my Podium home page</section>`);
});

app.listen(7003);

Example: page footer

Create a folder /podlets/footer with a file index.js inside to hold the following podlet code.

import Podlet, { html } from "@podium/podlet";
import express from "express";

const app = express();

const podlet = new Podlet({
name: "footer",
version: "1.0.0",
development: false,
});

app.use(podlet.middleware());

app.get("/manifest.json", (req, res) => {
res.json(podlet);
});

app.get("/", (req, res) => {
res.podiumSend(html`<footer>&copy; 2018 - the Podium team</footer>`);
});

app.listen(7004);

Sample layout​

Example: the /home layout

Create a folder /layouts/home. Create a file index.js inside this folder to hold the following layout code.

import Layout, { html } from "@podium/layout";
import express from "express";

const app = express();

const layout = new Layout({
name: "homePage",
pathname: "/home",
});

const headerClient = layout.client.register({
name: "header",
uri: "http://localhost:7001/manifest.json",
});
const navigationClient = layout.client.register({
name: "navigation",
uri: "http://localhost:7002/manifest.json",
});
const contentClient = layout.client.register({
name: "content",
uri: "http://localhost:7003/manifest.json",
});
const footerClient = layout.client.register({
name: "footer",
uri: "http://localhost:7004/manifest.json",
});

app.use(layout.pathname(), layout.middleware());

app.get(layout.pathname(), async (req, res) => {
const incoming = res.locals.podium;

const [header, navigation, content, footer] = await Promise.all([
headerClient.fetch(incoming),
navigationClient.fetch(incoming),
contentClient.fetch(incoming),
footerClient.fetch(incoming),
]);

incoming.view.title = "Podium example - home";

res.podiumSend(html`
<section>${header}</section>
<section>${navigation}</section>
<section>${content}</section>
<section>${footer}</section>
`);
});

app.listen(7000);

Running podlets and layout together​

Because each podlet and the layout have been configured to run on different ports you can safely start them all up together.

node podlets/header
node podlets/navigation
node podlets/home
node podlets/footer

We can now start up our /home layout to consume and display our podlet content.

node layouts/home

Our layout has been configured to run on port 7000 so we should now be able to visit the url http://localhost:7000/home in a browser and see header, navigation, home page and footer content composed together.

Improving the development experience​

The setup described above is a manual process requiring a number of repetitive operations by the developer to start up, restart or shut down processes. What follows are several suggestions for improving on this.

using forever​

One fairly simple way to manage all your podlets and layouts at once is to use a tool called forever which is available on npm.

Example: install forever

npm i -g forever

Forever allows you to pass it some json configuration describing your setup and have it manage the processes

Example: forever json configuration file

[
{
"uid": "header",
"append": true,
"watch": true,
"script": "index.js",
"sourceDir": "/path/to/podlets/header"
},
{
"uid": "navigation",
"append": true,
"watch": true,
"script": "index.js",
"sourceDir": "/path/to/podlets/navigation"
},
{
"uid": "home",
"append": true,
"watch": true,
"script": "index.js",
"sourceDir": "/path/to/podlets/home"
},
{
"uid": "footer",
"append": true,
"watch": true,
"script": "index.js",
"sourceDir": "/path/to/podlets/footer"
},
{
"uid": "homePage",
"append": true,
"watch": true,
"script": "index.js",
"sourceDir": "/path/to/layouts/home"
}
]

You can then pass the configuration file to forever to start everything up at once.

Example: running forever

forever start /path/to/development.json

Notice that every service has been configured to run in watch mode meaning that they will be automatically restarted any time a file change is detected.

You can read more about forever here.

using pm2​

A great alternative to forever is pm2. Pm2 can also take a configuration file in json format, can aggregate logs, run services in watch mode, has great docs and more.