How we built Lokalimde.Works

and How Deno + Sanity Go Well Together

November 8, 2022

Why we used a monorepo

We were pretty sure that it will be a one-page landing page once we started thinking on what we could do. Then at some point, when we get more listeners and attention on social media, we dived into thinking of expanding the knowledge across where we can reach out to. As one of the instruments of achieving it, alongside the podcast publishing, we thought we might need a blog section, too. But that's not a good reason to have a monorepo in place as a separate app for just a couple of articles within.

Then another dimension included into our vision as "how to manage the content", primarily the RSS feed to be generated for the podcast platforms as they're only accepting one standard way of letting you go through and reach out your audience on web. So we began lean, moved slow but iteratively. First, added the first page served through Deno's sift server which is also a nice fit for on-demand request handling in the server-side with a very simple routing included.

serve({
  "/": homePage,
  "/feed": feed,
  "/assets/:path": assets,
  404: () => new Response("Not found."), 
  // it really responds with the same message right now :)
});

// ...

async function homePage() {
  return new Response(`
    <html lang="en">
       ...
    </html>
  `)
}

and every each of the path you hit, it gives you back a function returning a web-native Response object back.

That's the beauty of what you could do with just simple JS/TS stuff for serving immediate text/html-encoded content. But that's still not enough to have a monorepo at all. When it comes to the content management and the RSS generation, we expected to have it also extendable at some point with new sessions we have on Twitter Spaces in a moderated fashion. So we decided to go with Sanity which is also an amazing tool which I cannot suggest you more when it comes to content moderation. As Sanity comes built-in with its moderation tool called Sanity Studio, we found the correct timing to set the repo into two projects. That was the moment we went with a monorepo within to separated directories under /apps: site & cms.

For the monorepo structure, we basically went with Yarn Workspaces and separated each environment (Node.js & Deno) via a package.json within the root itself with each command pointing to its original internal command provided by each runtime like the following:

"scripts": {
  "site": "cd ./apps/site/ && deno run --allow-net --allow-read --allow-write --allow-env mod.tsx",
  "cms": "yarn --cwd apps/cms start",
  "cms.build": "yarn --cwd apps/cms build",
  "cms.deploy": "yarn --cwd apps/cms deploy"
}

Why we used Sanity (the CMS)

Sanity CMS is an eye-catching tool with a nice / flexible & developer-friendly content / data management & moderation suite. You build your content as you code, within a set of schema extentions you introduce. For example, you need a blog post, you can write your own blogPost schema type and include the file within the schema.js file within the root of the Sanity Studio, that's it. Here is the example:

export default {
  name: 'blogPost',
  type: 'document',
	title: 'Blog Post',
  fields: [
    {
      name: 'title',
      type: 'string',
      title: 'Title',
    },
    {
      name: 'subTitle',
      type: 'string',
      title: 'Sub Title',
    },
    {
      name: 'slug',
      type: 'slug',
      title: 'Slug',
      options: {
        slugify: input => input
                         .toLowerCase()
                         .replace(/\s+/g, '-')
                         .slice(0, 200)
      }
    },
    {
      name: 'pubDate',
      type: 'datetime',
      title: 'Publish Date',
    },
    {
      name: 'content',
      type: 'markdown',
      title: 'Content'
    },
    {
      title: 'Tags',
      name: 'tags',
      type: 'array',
      of: [{type: 'string'}]
    }
  ]
}

Then what you will need next, just to include it within the schemas.js:

export default createSchema({
  types: schemaTypes.concat([
    session
    blogPost
  ]),
})

Then what happens is that the Studio gets build auto-magically, and restarts the dashboard where you curate your content within:

image

Clean and neat, no need for more headaches. So we can totally recommend you to dive in when it comes to content management for your projects. Sanity is easy-to-go tool and exciting.

Why we used Deno 🦕 & Deno Deploy 🦖

Actually, we were not sure about which platform / runtime to be used while publishing the website at the beginning. The criteria for us were basically:

  • Something on-demand (which we do not wanna care about the load & we were sure that the load will be low at first).
  • Something easy-to-start with some workers running on the edge for the performance reasons that it may help the pages to be rendered & served back to the users as quick as possible.
  • Something supporting the modern web with capabilities as native as possible.
  • Something which is also supporting what we plan to use, so for experimentation purposes, we decided to see how much Deno deserves an attention and a chance to be tried-out.

image

Then, we decided to move forward with Deno Deploy as it is also a promising platform where we can quickly ramp-up the needs what we would need at the first step: Providing a RSS feed, links to the podcast sessions on different platforms and some foundation for publishing blog posts like how you are able to read this article. We also preferred their suggested solution for serving static assets (like css, etc.) and that easily solved our problem, too.

image

We would also like to tell the other benefits like really smooth Github integration which literally takes no time for us to go live from Deno Deploy's edge servers once there is a new content.

image

Once some code has been merged in our repo, it takes around ~20s to get it live. I would also like to mention regarding the build times which are no-brainer for anyone using the platform and really surprising for such a young tool. If you feel you need more details, please go hit their page for the official documentation and platform-internal things.

image

From performance-wise, the platform is amazingly satisfactory. We were expecting such a huge gain at the first step, for sure, as we're only serving static content all around the site but having a page rendered on standard network connections like Wi-Fi & mobile with an enormous pace, that also made us smiling in front of our screens :)!

image