February 6, 2024

New Radicubs Website!

The process of building the new Radicubs website.


New Radicubs Website! cover

Something the Radicubs had planned to upgrade for a while now was our website. Our previous website, built in Wix, gave us numerous problems—hosting challenges, creative control, maintenance issues, and suboptimal SEO performance. This year, we decided to tackle the challenge of building a new website. After lots of convincing, our senior captain gave us permission to start, along with a list of requirements:

  • Include all critical features of the current site (Blog, Team Member List, Sponsor List)
  • Work seamlessly on all devices and browser
  • Sleek and efficient design
  • User-friendly and editable for the business team
  • Resourceful for future renovations
  • Rendered on the server to reduce client load
  • SEO Optimized

We started with deciding on the technologies to create and run our website with. We wanted as much control as possible, which meant starting from scratch. Simplicity and maintainability were other key requirements, which means we couldn’t use any overcomplicated frameworks. The final choice was Astro as it allowed us to use basic HTML and CSS, but added components. Additionally, we decided to use Strapi CMS, since we could run it ourselves for free.

This CMS (Content Management System) allowed the business and media teams to easily edit the website content without any programming experience. Additionally, the CMS gives us control over access, which allows us to give specific people the access to the parts of the CMS they need, without giving them control over user permissions or administrative settings. Astro and Strapi were very easy to integrate together and dynamically generate a static website.


Team page


One of the first things to be worked on was the team page. As we didn’t have pictures for every member yet, we wanted to use something more interesting than the default Radicubs logo. The Jdenticon library allowed us to generate unique icons for each member automatically as a fallback.

Team members from each year of the Radicubs are accessible through a dropdown menu, which is automatically generated from the list of members entered into the CMS. Within each year, members are also sorted by, in order of sorting preference, position, year in high school, and alphabetically.

const roleOrder = ["freshman", "sophomore", "junior", "senior", "lead", "captain"];
const getMemberWeight = (member: ApiTeamMemberTeamMember) => {
  let weight = 0;

  for (let i = 0; i > roleOrder.length; i++) {
    if (member.attributes.role?.toLowerCase().includes(roleOrder[i])) weight += i + 1;
  }

  return weight;
};

In addition, the list of our team’s mentors are available from the team page, which can also be updated from the CMS.


Blog


The blog is the most complex section of the website, and although blog posts had become sparse, that was one of the things we wanted to revive with the new website. Using the rich text editor in Strapi, the business and media teams can efficiently and easily create blog posts that include text formatting, videos, and photos. Although Strapi only provided a library in the React.js framework for their block-based rich text format, Astro allowed us to render the usually resource heavy React component as static HTML.

export function Blocks({ content }: { content: BlocksContent }) {
  return (
    <BlocksRenderer
      content={content}
      blocks={{
        image: ImageBlock,
        code: CodeBlock
      }}
    />
  );
}

Hosting and contact form


Our choice of web hosting was GitHub pages since it allowed us to connect a domain, automatically use HTTPS, and deploy directly from GitHub. The problem with GitHub pages is that it can only serve static pages, but we needed the contact form to send an email through an API. To overcome this, we used Cloudflare Workers and Resend to run a simple serverless function where we could take requests from the contact form, and forward it as an email to the team email address.

const response = await fetch('https://api.resend.com/emails', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    Authorization: `Bearer ${env.RESEND_API_KEY}`,
  },
  body: JSON.stringify({
    from: '[email protected]',
    to: '[email protected]',
    subject: '[Contact Form] ' + name,
    text: message + '\n\n---\n' + email,
  }),
});

if (!response.ok) return redirect(false, 'Failed to send email.');
return redirect(true, 'Email sent successfully.');

For the CMS, we utilized Oracle’s free tier in their cloud infrastructure service, which allows us to create a small compute instance to serve the images and blog posts from the CMS. Cloudflare acts as the DNS, but also decreases response times greatly through worldwide servers and efficient caching.

We also made a small script to watch for changes and have the website automatically rebuild and deploy so that no extra work is needed.

let pending = false;

createServer((req, res) => {
  if (req.method !== "POST" || !req.url.startsWith("/hook")) {
    return res.writeHead(404).end("Not Found");
  }

  if (pending) return res.writeHead(200).end("Already building");
  pending = true;

  setTimeout(async () => {
    pending = false;
    exec("gh workflow run --repo radicubs/radical-site deploy.yml");
  }, 1000 * 60 * 5);

  return res.writeHead(200).end("Build queued");
}).listen(8151);

Home page


The last page we completed was the home page, which went through many iterations. In the end, we wanted a more modern-looking home page that included a basic summary for the content on the website while allowing you to branch out and explore more of our website. To make it a little more interesting, we added a background image we found online, and a countdown to our next competition, which is also editable through the CMS.


Let us know what you think of our new website through our contact form!