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!