Day 6: Building a Careers Page with Markdown and Lightsail PostgreSQL

n-tien
May 04, 2025
3 mins read
Day 6: Building a Careers Page with Markdown and Lightsail PostgreSQL

Building a Careers Page with Markdown and Lightsail PostgreSQL

📢 If you haven't read the previous parts, check out Day 1, Day 2, Day 3, Day 4, and Day 5!

📚 You can also explore all posts from the 7 Days Website Revamp series!


Why We Created a Custom Careers Page

As our Vietnam office prepares for the 2025 Internship Program, we needed a platform that:

  • Simplifies publishing internship opportunities
  • Collects applications securely and efficiently
  • Gives us full control over design, user flow, and data

Rather than relying on third-party job boards, we built our own Careers Page using Markdown and a PostgreSQL database hosted on AWS Lightsail.

👉 Check out our current internship listing here: Full-stack Software Engineer Intern 2025


Managing Job Listings with Markdown

Each job posting is created as a Markdown file inside:

/src/content/careers/

With frontmatter like:

---
title: "Full-stack Software Engineer Intern 2025"
location: "Ho Chi Minh City, Vietnam"
employment_type: "Internship"
department: "Engineering"
published: true
date: "2025-05-01"
---

The body includes the role description, expectations, and perks.

✅ This setup makes it simple to publish or update job listings — no CMS required.


The Application Form

Here’s what our actual internship application form includes:

  • First Name & Last Name
  • Email Address & Phone Number
  • Resume upload (PDF, max 3.5MB)
  • Transcript upload (PDF, max 3.5MB)
  • “How did you hear about us?” radio options
  • Optional message input
  • Submit button (or “Job Expired” if the deadline is past)

Saving Applications to PostgreSQL

We provisioned a PostgreSQL database on AWS Lightsail using Terraform:

resource "aws_lightsail_database" "atware_home" {
  relational_database_name = "atware-asia-home-db"
  availability_zone        = "ap-southeast-1a"
  master_database_name     = "atware_home"
  master_username          = "atware"
  master_password          = var.db_password
  blueprint_id             = "postgres_16"
  bundle_id                = "micro_2_0"
  publicly_accessible      = true
}

✅ This lightweight DB is perfect for our application data — cost-effective, scalable, and secure.


File Upload and Size Limits

Both Resume and Transcript files are uploaded directly into the database.

  • Accepted format: PDF only
  • Size limit: 3.5MB
  • Files are stored as base64-encoded binary blobs

We validate the file size and type on both client-side and server-side to ensure stability and avoid abuse.


Spam Protection and Rate Limiting

To keep our API stable, we implemented rate limiting middleware.

📌 For simplicity, we’ve omitted those technical details from this blog post — but it’s active in production.


Final Thoughts

Combining Markdown for job listings and Lightsail PostgreSQL for application storage gave us a lightweight, developer-friendly recruiting platform.

This approach allows our team to manage job openings independently, control the user experience, and securely store candidate information without relying on external job boards.

In the final post of this series, we'll focus on SEO optimization, Google Search Console setup, and how we used ChatGPT to enhance our website content strategy!


You can now continue with Day 7: SEO Optimization, Google Search Console, and Content Enhancement with ChatGPT!

📚 You can also explore all posts from the 7 Days Website Revamp series!