DEV Community

Cover image for Getting started with Drayman
Yan Ivan Evdokimov
Yan Ivan Evdokimov

Posted on • Updated on

Getting started with Drayman

Drayman is a server-side component framework that allows you to use any available HTML element, web component or custom Drayman third-party component together with server-side code in a single script.

With Drayman, the browser only renders what the user should see - all logic and calculations happen server-side and UI is written using JSX syntax.

The best way to show Drayman capabilities is to create something with it. So let's get started.

File viewer component

Let's build a component that allows the user to select a file from the file system and view it's contents.

First, you need to install Drayman. It can be done by running these commands:

npx @drayman/framework-init@latest my-app
cd my-app
npm start
Enter fullscreen mode Exit fullscreen mode

The website will be available at http://localhost:3033.

If you don't want install anything, you can always try Drayman inside CodeSandbox by visiting new.drayman.io.

Initial component template

Go to src/components/home.tsx and replace its contents with this code:

export const component: DraymanComponent = async () => {
  return async () => {
    return (
      <>
        <p>Select a file to view it directly from file system</p>
        <select></select>
        <br />
        <pre></pre>
      </>
    );
  };
};
Enter fullscreen mode Exit fullscreen mode

You will see an initial skeleton of our component. Further <select> will be used to show available files and <pre> will show contents of the selected file.

Filling select with options

Because Drayman runs a component server-side, we can use any Node.js library. In our case we will use the fs module.

Let's read file names from the project root directory and fill <select> options with them:

import { promises as fs } from "fs";

export const component: DraymanComponent = async () => {
  const files = (await fs.readdir("./")).filter((x) => x.includes("."));

  return async () => {
    return (
      <>
        <p>Select a file to view it directly from file system</p>
        <select>
          {files.map((fileName) => (
            <option>{fileName}</option>
          ))}
        </select>
        <br />
        <pre></pre>
      </>
    );
  };
};
Enter fullscreen mode Exit fullscreen mode

Right now our component is only showing some elements without any interactivity. Our next step will be to add it.

Reacting to user actions

We need to remember which file the user has selected to show its contents. It can be done by using the onchange event attribute and attaching a function that will be executed server-side. We also need to add the value attribute to each option so that select would know which option was selected.

Let's also add the fs.readFile function inside the <pre> tag so that Drayman would read file contents during re-render. We won't show the pre until a file is actually selected:

import { promises as fs } from "fs";

export const component: DraymanComponent = async () => {
  const files = (await fs.readdir("./")).filter((x) => x.includes("."));
  let selectedFile;

  return async () => {
    return (
      <>
        <p>Select a file to view it directly from file system</p>
        <select
          onchange={async ({ value }) => {
            selectedFile = value;
          }}
        >
          {files.map((fileName) => (
            <option value={fileName}>{fileName}</option>
          ))}
        </select>
        <br />
        {selectedFile && <pre>{await fs.readFile(selectedFile, "utf-8")}</pre>}
      </>
    );
  };
};
Enter fullscreen mode Exit fullscreen mode

If you make a selection from the dropdown, you will see that nothing happens on the page - file contents don't appear. That is because with Drayman you must strictly tell when a component needs to be re-rendered. It can be done by using a special helper function forceUpdate.

Import it and add to the onchange event after the selected file was saved:

import { promises as fs } from "fs";

export const component: DraymanComponent = async ({ forceUpdate, }) => {
  const files = (await fs.readdir("./")).filter((x) => x.includes("."));
  let selectedFile;

  return async () => {
    return (
      <>
        <p>Select a file to view it directly from file system</p>
        <select
          onchange={async ({ value }) => {
            selectedFile = value;
            await forceUpdate();
          }}
        >
          {files.map((fileName) => (
            <option value={fileName}>{fileName}</option>
          ))}
        </select>
        <br />
        {selectedFile && <pre>{await fs.readFile(selectedFile, "utf-8")}</pre>}
      </>
    );
  };
};
Enter fullscreen mode Exit fullscreen mode

Now our component is complete and file contents are shown on select:
blog-getting-started-final-result

Conclusion

We have built a component that combines server-side logic and client-side view in a single script.

If this felt interesting to you, visit the official docs to deep-dive into Drayman framework!

Discussion (0)