DEV Community

Mohamed Aiman
Mohamed Aiman

Posted on Fully Autonomous

Building a server-rendered admin UI with Express, EJS, and SEN-JS

Admin screens usually need the same building blocks: navigation, tables, search, filters, and forms. In my public project SEN-JS, I organize those pieces as reusable EJS components, with Express handling the page rendering.

This walkthrough covers the project’s documented component model and how to explore it locally. The source is available at Darkguyaiman/SEN-JS.

1. Start with the page and its data

A server-rendered page can receive its title, navigation, and rows in one render operation. In SEN-JS, the renderPage helper connects the page template to the component registry. That keeps a route focused on preparing data while templates describe the interface.

The repository separates routes/, views/, and components/. Shared rendering behavior lives in lib/core/Component.js.

2. Keep each component in its own folder

A component has an EJS template and, when it needs browser behavior, an optional JavaScript file. For example:

components/
  sidebar/
    sidebar.ejs
    sidebar.js
  table/
  search-bar/
  filter/
  calendar/
  button/
Enter fullscreen mode Exit fullscreen mode

This makes the unit of reuse concrete: markup and related behavior live together. The project loads scripts for the components used on the page, so adding a button does not mean manually importing every component script.

3. Pass explicit props

Here is a small EJS example using the documented button interface:

<%- sen.component('button', {
  label: 'Save',
  variant: 'primary'
}) %>
Enter fullscreen mode Exit fullscreen mode

The button API includes props such as label, variant, size, href, and disabled. Tables receive columns and rows, while filters receive their options and selected value. Explicit inputs help keep page-specific content out of shared templates.

The table component also supports a cardTitle property for its mobile card presentation. That is useful when the same records need to be readable on both a wide admin screen and a phone.

4. Explore it locally

With Node.js and npm available, clone the repository and install its dependencies:

git clone https://github.com/Darkguyaiman/SEN-JS.git
cd SEN-JS
npm install
npm run build:css
npm run dev
Enter fullscreen mode Exit fullscreen mode

The README documents demo data when MySQL is unavailable. To use a database, copy .env.example to .env, configure MySQL, and follow the schema setup instructions in the repository. Keep real credentials out of Git.

The development script watches Tailwind and runs the Express server. For a new component, create components/my-widget/my-widget.ejs, add my-widget.js if needed, then use sen.component('my-widget', props) in a page. Rebuild the CSS after adding template classes.

What this approach trades off

I use this structure to keep ordinary admin workflows close to their server-rendered pages. It still needs appropriate authentication, input validation, and database handling for each application. A UI component framework does not provide all of those application rules automatically.

For a dashboard that mainly displays records and submits forms, reusable templates are a practical starting point. For complex browser state, I would evaluate the interaction requirements separately.

You can browse SEN-JS on GitHub or explore my other web development work at darkguyaiman.com.

This article was prepared with AI assistance and checked against the public project documentation.

Top comments (0)