Dev Journal #5: A UI to list links

The next step is to create the first UI page to display the list of existing links. Even though I followed SST’s docs for creating a NextJS project, linking NextJS, SST, and MUI together was fraught.

Bring NextJS and MUI Online

To get it all in sync, I ended up cloning the SST NextJS quickstart example and copying over files until I was able to see Next’s Hello World UI:

NextJS hello world screen

Then, I did the same with MUI’s NextJS (Typescript) example until I could that Hello World UI:

MUI hello world screen

You can view these changes in the Next UI works in dev and Add MUI PRs.

I’m eternally grateful to the devs that have written countless examples for the MUI and SST projects; without those examples, I don’t think I would’ve been able to move forward on this project with these tools.

Finally, let’s connect the UI to the API data! First, we’ll expose the api construct in stacks/API.ts so that we can bind it to the UI:

  // ...
  stack.addOutputs({
    ApiEndpoint: api.url,
  });

  return { api };
}

Then bind the api to the site under stacks/Site.ts:

export function Site({ stack }: StackContext) {
  const { api } = use(API);

  const site = new NextjsSite(stack, "site", {
    bind: [api],
  });

On the index page (src/pages/index.tsx), we can create a Link type and use getServerSideProps to fetch data from the API:

type Link = {
  shortPath: string;
  url: string;
  uid: string;
};

export const getServerSideProps: GetServerSideProps<{
  links: Link[];
}> = async (context) => {
  const endpoint = `${Api.api.url}/links`;
  const res = await fetch(endpoint);
  const data = await res.json();

  return { props: data.body };
};

There’s a possible breakdown between the UI and API here if the Link type skews from what the API returns, so I created an issue to revisit this in the future. In that same file, we’ll add some basic p tags for each link we receive:

export default function Home({ links }: { links: Link[] }) {
  return (
    <Container maxWidth="lg">
      {/* ... */}
        {links &&
          links.map((link) => (
            <Typography
              variant="body1"
              component="p"
              gutterBottom
              key={link.uid}
            >
              {link.shortPath} - {link.url}
            </Typography>
          ))}

One last thing: NextJS requires an experimental flag in next.config.js to make this work. I think it’s to allow async calls inside getServerProps:

const nextConfig = {
  reactStrictMode: true,
  webpack(config) {
    config.experiments = { ...config.experiments, topLevelAwait: true };
    return config;
  },
};

And there we go, links! You can view this code on the Index shows list of links PR.

NextJS hello world screen