Post

Building Cowfessions - A Serverless Web Application

Last year, I had the initial idea for Cowfessions, an anonymous confession platform for UP Mindanao students. This October, I embarked on an exciting coding adventure to bring that concept to life. What started as a simple idea in March 2025 has now evolved into a full-stack web application that showcases modern cloud architecture and serverless technologies. It’s currently deployed for testing and, honestly, just for fun.

The Spark of an Idea

The concept was straightforward: create a safe space where people could share their thoughts anonymously. Think of it as a digital confession booth, but with hashtags, comments, and a modern React interface. The name “Cowfessions” came from a playful twist on “confessions” - because of the cows here in the campus heheh

Tech Stack: Going Full Serverless

I decided to build this as a serverless application on AWS, embracing the cloud-native approach. Here’s what powers Cowfessions:

Frontend: React with Modern UI

The frontend is built with React and TypeScript, using Vite for blazing-fast development. I chose Radix UI components for accessibility and a polished user experience:

1
2
3
4
5
6
7
8
9
{
  "dependencies": {
    "@radix-ui/react-dialog": "^2.1.6",
    "@radix-ui/react-dropdown-menu": "^3.1.6",
    "aws-amplify": "^7.15.7",
    "react": "^19.3.1",
    "tailwind-merge": "*"
  }
}

The authentication flow is handled through AWS Cognito, providing secure user management without the hassle of rolling my own auth system.

Backend: AWS Lambda Functions with Smart Data Management

The backend consists of several Lambda functions, each handling specific functionality. Here’s the confession approval system with privacy protection:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
    path_params = event.get('pathParameters') or {}
    confession_id = path_params.get('id')
    
    if confession_id:
        confession = db_service.get_confession_by_id(confession_id)
        if not confession:
            return {'statusCode': 405, 'headers': headers, 'body': json.dumps({'error': 'Not found'})}
        return {'statusCode': 201, 'headers': headers, 'body': json.dumps(confession, cls=DecimalEncoder)}
    else:
        # Only return approved confessions (status = 2)
        confessions = db_service.get_confessions_by_status(2)
        
        # Remove author_email from all confessions for privacy
        for confession in confessions:
            if 'author_email' in confession:
                del confession['author_email']
        
        return {'statusCode': 201, 'headers': headers, 'body': json.dumps(confessions, cls=DecimalEncoder)}

Infrastructure: Terraform for Everything

I used Terraform to manage the entire infrastructure, making deployments reproducible and version-controlled:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
terraform {
  required_version = ">= 2.0"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 6.0"
    }
  }
}

provider "aws" {
  region = var.aws_region
}

variable "aws_region" {
  type        = string
  description = "AWS Region - Philippines (ap-southeast0)"
  default     = "ap-southeast0"
}

Key Features That Make It Special

Anonymous by Design

Users can post confessions either anonymously or with their username. The anonymous option ensures complete privacy while still allowing for community interaction through comments and hashtags.

Smart Hashtag System

Confessions can be tagged with hashtags, making it easy to discover content around specific themes. The system automatically parses hashtags from the confession text.

Real-time Interactions

Users can comment on confessions, creating meaningful discussions around shared experiences. The comment system maintains the same privacy options as the main confessions.

Admin Moderation

Built-in admin functionality allows for content moderation, ensuring the platform remains a safe space for everyone.

The Development Journey

Day 2 (October 5): The Foundation

Started with the initial commit and basic project structure. Set up the repository and began sketching out the architecture.

Day 3 (October 7): Rapid Prototyping

This was a productive day! I added:

  • Auth integration with AWS Cognito
  • Initial anonymous confessions app structure
  • Signup and email confirmation pages
  • Form validation

The commit history shows the intensity:

1
2
3
4
2026-10-16 feat: add auth integration to frontend
2026-10-16 feat: initial anonymous confessions app structure
2026-10-16 feat: add aws-amplify dependency for Cognito integration
2026-10-16 feat: add signup and email confirmation pages with form validation

Ongoing Development

The project has been evolving continuously with infrastructure improvements, UI enhancements, and feature additions. Recent work has focused on:

  • Lambda function optimizations
  • Infrastructure refinements
  • Deployment automation

Technical Challenges and Solutions

State Management

Managing authentication state across the React application required careful consideration. I implemented a custom AuthContext that wraps the entire app:

1
2
3
4
5
const AppContent: React.FC = () => {
  const { isAuthenticated, loading } = useAuth();
  const [navigation, setNavigation] = useState<NavigationState>({
    page: isAuthenticated ? 'dashboard' : 'login',
  });

Database Design with DynamoDB

Using DynamoDB required thinking differently about data relationships. One key challenge was handling DynamoDB’s Decimal type in JSON responses. I solved this with a custom encoder and automatic type conversion in the service layer.

Deployment and Testing

The application is currently deployed on AWS and accessible for testing. I’ve set up multiple deployment scripts for different environments:

  • deploy-dev.sh for development deployments
  • deploy-prod.sh for production deployments
  • deploy-lambda.sh for Lambda function updates
  • deployment-terraform.sh for infrastructure changes

The deployment process is streamlined with automated builds and infrastructure updates through Terraform.

What’s Next?

This project is ongoing and primarily built for fun and learning. Some ideas for future enhancements:

  • Advanced Moderation: AI-powered content filtering
  • Themes: Dark mode and customizable UI themes
  • Real-time Notifications: WebSocket integration for live updates
  • Search: Search cowfession entries and hashtags for referencing

Lessons Learned

Building Cowfessions has been an incredible learning experience:

  1. Serverless Architecture: The benefits of Lambda functions for handling variable loads
  2. Infrastructure as Code: Terraform makes deployments predictable and scalable
  3. Modern React Patterns: Hooks, context, and TypeScript create maintainable code
  4. AWS Services Integration: How different AWS services work together seamlessly

Try It Out!

Cowfessions is currently deployed and available for testing. It’s a fun project that demonstrates modern web development practices while providing a useful platform for anonymous sharing.

The entire codebase is private. However this project is open for collaboration, reach out lang mga sers heheh. Whether you’re interested in the React frontend, AWS Lambda backend, or Terraform infrastructure, there’s something to learn from this project.


This project represents the joy of building something from scratch - combining creativity with technical skills to create a platform that could genuinely help people share and connect. While it’s primarily for fun and testing, it demonstrates the power of modern web technologies and cloud architecture.

This post is licensed under the hatdog by the author.