DEV Community

Cover image for Setup Simple Web UI for Node.js App in Seconds
vilicvane
vilicvane

Posted on

Setup Simple Web UI for Node.js App in Seconds

I have plenty of small projects written in Node.js, and most of the time, I would like to but won't setup web UI for those projects because that would introduce new frontend & backend code which would look bloated comparing to the core code of the projects themselves.

There is a good solution for some of those cases - ink. With ink, I can implement text-based UI with knowledge of React, which is neat but there are still some caveats for my usages:

  • It's not daemon friendly. E.g., ink app within pm2 would not look pretty. If I want to daemonize the app, I basically lose the UI capability other than log streams.
  • It's not mobile friendly. To access the app from a mobile device, I have to SSH connect the server and wish the UI won't mess up with my screen size.

BackPage

Web UI would still be my first choice if it got a lower price tag. And here comes the BackPage.

import {BackPage} from 'backpage';
import React from 'react';

const page = new BackPage();

page.render(<div>Hello BackPage!</div>);

page.guide(); // Prints URL.
Enter fullscreen mode Exit fullscreen mode

And you immediately get this:

BackPage rendering a Hello message

BackPage renders the React element and streams live changes to browser using WebSocket. But the drawback is obvious: it does not support common user interactions.

Form-based Interactions

However, it supports simple form-based action which should be more than enough for its use cases as a complementary to log streams.

import React, {useState} from 'react';

import {ActionButton, BackPage} from 'backpage';

const page = new BackPage();

const App = () => {
  const [started, setStarted] = useState(false);

  return (
    <>
      <div>{started ? 'Started' : 'Stopped'}</div>
      <ActionButton action={() => setStarted(true)}>Start</ActionButton>
      <ActionButton action={() => setStarted(false)}>Stop</ActionButton>
    </>
  );
};

page.render(<App />);

page.guide();
Enter fullscreen mode Exit fullscreen mode

And this is what you get:

BackPage rendering Start and Stop action buttons

To receive inputs from the browser, you can use Form element:

page.render(
  <Form action={data => console.info(data)}>
    <input name="foo" />
    <button type="submit">submit</button>
    <button type="reset">reset</button>
  </Form>,
);
Enter fullscreen mode Exit fullscreen mode

ActionButton is actually a button wrapped within a Form.

Browser Notifications

You can also send notifications to the browser and optionally fallback to something like a webhook, if the notification not getting clicked within the timeout:

const page = new BackPage({
  notify: {
    fallback() {
      return 'https://webhook/...',
    },
  },
});

page.notify({
  title: 'Hello BackPage!',
  body: 'Click me or your webhook will get fired!',
});
Enter fullscreen mode Exit fullscreen mode

The result (don't forget to allow notification for the relevant origin in browser):

BackPage notification popping out

Public URL

For cases that accessing BackPage via the internet is needed, the simplest way is to use the minimal BackPage "Cloud" which doesn't even have a public UI (and yes, its private "dashboard" is served by BackPage itself). And the only thing you need to add is a random UUID as token:

import {BackPage, getPersistentToken} from 'backpage';

const page = new BackPage({
  token: getPersistentToken(),
});
Enter fullscreen mode Exit fullscreen mode

You can also use the randomUUID() function provided by Node.js core crypto module if you want a new URL every time.

Conclusion

BackPage makes simple web UI for Node.js app with limited needs for interaction easy. You may use BackPage to quickly setup web UI for small Node.js app, or even dashboard for Node.js backend.

As BackPage is still in its early stage, please consider starring the project if you found it potentially useful. ❤

If you have any problem or question against BackPage, please file an issue or leave a comment. I am always a quick responder when I am awake.

And yes, it's named after FrontPage. Even the logo is copied from FrontPage.

Top comments (0)