Building RC Web Solutions: From Simple Portfolio to Full-Featured Business Application
Tech StackWeb DevelopmentCase StudyNext.js

Building RC Web Solutions: From Simple Portfolio to Full-Featured Business Application

A deep dive into the technologies, architecture, and evolution of rcweb.dev - transforming a portfolio site into a comprehensive business web application with payment processing, email campaigns, and advanced features.

Randy Caballero
16 min read

Building RC Web Solutions: From Portfolio to Production-Ready Business Application

When I first started RC Web Solutions, like most developers, I began with a simple portfolio website. A few pages showcasing my work, a contact form, and some basic information about my services.

But as the business grew, so did the need for more sophisticated features. Today, rcweb.dev is not just a portfolio—it's a full-featured business web application that handles everything from client acquisition to payment processing, email marketing campaigns, and comprehensive analytics.

In this article, I'll take you behind the scenes to show you exactly how I built this application, the technologies I chose, and why.


What Type of Application is RC Web Solutions?

Let's clarify what type of application rcweb.dev is:

Business Web Application (Not SaaS)

RC Web Solutions is a Business Web Application (BWA) rather than a traditional SaaS platform. Here's the distinction:

SaaS (Software as a Service):

  • Multiple tenants/users with separate accounts
  • Subscription-based recurring revenue
  • User dashboards and role-based access
  • Examples: Shopify, Mailchimp, Salesforce

Business Web Application:

  • Single business entity
  • Custom features tailored to specific business needs
  • Client-facing features + internal tools
  • Examples: Company websites with advanced features, booking systems, custom CRMs

RC Web Solutions is a BWA with SaaS-like features:

  • ✅ Advanced backend functionality
  • ✅ Database-driven content
  • ✅ Payment processing
  • ✅ Email automation
  • ✅ Newsletter campaign system
  • ✅ Analytics and tracking
  • ✅ Cookie consent management
  • ✅ Blog/CMS functionality

It's designed to serve one business (RC Web Solutions LLC) with multiple complex features rather than serving multiple businesses with generic features.


The Evolution: From Portfolio to Application

Phase 1: Simple Portfolio (v1.0)

When I started, the site was straightforward:

  • Static pages (Home, About, Services, Contact)
  • Basic HTML/CSS/JavaScript
  • Contact form that sent emails
  • Hosted on shared hosting

Limitations:

  • ❌ Hard to update content
  • ❌ No analytics
  • ❌ No payment processing
  • ❌ Manual client management
  • ❌ No SEO optimization

Phase 2: Next.js Rebuild (v2.0)

I rebuilt the entire site using modern technologies:

  • Migrated to Next.js
  • Added PostgreSQL database
  • Implemented Prisma ORM
  • Created admin features
  • Added payment processing

Improvements:

  • ✅ Server-side rendering (better SEO)
  • ✅ Fast page loads
  • ✅ Database-driven content
  • ✅ Automated workflows

Phase 3: Full Business Application (v3.0 - Current)

The current version includes:

  • Newsletter campaign system with batch processing
  • Stripe payment integration
  • Cookie consent management (GDPR/CCPA)
  • Blog with Markdown CMS
  • Comprehensive analytics (GA4, Facebook Pixel)
  • SMS marketing integration (Twilio)
  • Advanced contact management
  • Special offer system with countdown timers

Result: A complete business ecosystem in one application.


Technology Stack: The Full Breakdown

Here's every technology powering rcweb.dev and why I chose each one:

Frontend

Next.js 14 (App Router)

// Framework: Next.js 14
Why I chose it:
✅ Server-side rendering (SSR) = better SEO
✅ Static site generation (SSG) = lightning-fast pages
✅ API routes = backend and frontend in one project
✅ Image optimization = automatic WebP conversion
✅ File-based routing = intuitive structure

Alternative considered: Vanilla React Why Next.js won: Built-in SEO, performance, and deployment optimizations

TypeScript

// Type safety across the entire application
interface ContactFormData {
  name: string;
  email: string;
  phone: string;
  message: string;
  marketingConsent: boolean;
}

Why TypeScript:

  • ✅ Catch bugs at compile time, not runtime
  • ✅ Better IDE autocomplete
  • ✅ Self-documenting code
  • ✅ Easier refactoring

Tailwind CSS

<button className="px-6 py-3 bg-gold text-black rounded-lg hover:bg-gold/90">
  Contact Us
</button>

Why Tailwind:

  • ✅ Utility-first = faster development
  • ✅ No CSS file bloat
  • ✅ Consistent design system
  • ✅ Responsive design made easy

Alternative considered: Styled Components, CSS Modules Why Tailwind won: Speed of development and bundle size

Framer Motion

<motion.div
  initial={{ opacity: 0, y: 20 }}
  animate={{ opacity: 1, y: 0 }}
  transition={{ duration: 0.5 }}
>
  Content here
</motion.div>

Why Framer Motion:

  • ✅ Smooth, professional animations
  • ✅ Great TypeScript support
  • ✅ Performant
  • ✅ Easy to use

Backend

PostgreSQL Database

-- Relational database for structured data
CREATE TABLE contacts (
  id SERIAL PRIMARY KEY,
  name VARCHAR(255),
  email VARCHAR(255) UNIQUE,
  phone VARCHAR(50),
  message TEXT,
  marketing_consent BOOLEAN,
  created_at TIMESTAMP DEFAULT NOW()
);

Why PostgreSQL:

  • ✅ Robust and reliable
  • ✅ ACID compliance (data integrity)
  • ✅ Excellent for relational data
  • ✅ JSON support (hybrid SQL/NoSQL)
  • ✅ Free and open-source

Alternative considered: MongoDB, MySQL Why PostgreSQL won: Best balance of features, reliability, and performance

Prisma ORM

// Type-safe database queries
const contacts = await prisma.contact.findMany({
  where: {
    marketingConsent: true,
  },
  orderBy: {
    createdAt: 'desc',
  },
});

Why Prisma:

  • ✅ Auto-generated TypeScript types
  • ✅ Intuitive query syntax
  • ✅ Database migrations made easy
  • ✅ Great developer experience

Next.js API Routes (Server Actions)

// app/actions/createContactAction.ts
'use server';

export async function createContactAction(data: FormData) {
  const contact = await prisma.contact.create({
    data: {
      name: data.name,
      email: data.email,
      // ...
    },
  });

  return { success: true, contact };
}

Why Server Actions:

  • ✅ No need for separate API endpoints
  • ✅ Automatic type safety
  • ✅ Progressive enhancement
  • ✅ Simplified error handling

Third-Party Integrations

Stripe (Payments)

// Secure payment processing
const checkout = await stripe.checkout.sessions.create({
  line_items: [{
    price_data: {
      currency: 'usd',
      product_data: { name: 'Web Development Services' },
      unit_amount: 149900, // $1,499.00
    },
    quantity: 1,
  }],
  mode: 'payment',
  success_url: `${domain}/success`,
  cancel_url: `${domain}/canceled`,
});

Why Stripe:

  • ✅ Industry standard for payments
  • ✅ Excellent developer experience
  • ✅ Built-in fraud protection
  • ✅ Comprehensive documentation

Resend (Email Service)

// Transactional emails + newsletter campaigns
await resend.emails.send({
  from: 'RC Web <no-reply@rcweb.dev>',
  to: ['customer@example.com'],
  subject: 'Thank you for contacting us!',
  html: emailTemplate,
});

Why Resend:

  • ✅ Modern API (better than SendGrid/Mailgun)
  • ✅ React Email support
  • ✅ Great deliverability rates
  • ✅ Free tier (100 emails/day)

Features built with Resend:

  • Contact form confirmations
  • Newsletter campaigns (batch processing)
  • Payment receipts
  • Welcome emails

Twilio (SMS Marketing)

// SMS campaigns for promotional offers
await twilio.messages.create({
  body: 'Special offer: 20% OFF web development!',
  from: '+1234567890',
  to: customer.phone,
});

Why Twilio:

  • ✅ Reliable SMS delivery
  • ✅ Compliance features (TCPA, opt-in/opt-out)
  • ✅ Campaign management

Google Analytics 4 + Facebook Pixel

// Track conversions and user behavior
gtag('event', 'conversion', {
  send_to: 'AW-XXXXXXX/XXXXXX',
  value: 1499.00,
  currency: 'USD',
});

Why both:

  • ✅ GA4: Deep insights into user behavior
  • ✅ Facebook Pixel: Retargeting and ad optimization
  • ✅ Conversion tracking across platforms

Development & Deployment

Vercel (Hosting & Deployment)

# Automatic deployments on every git push
git push origin main
# → Vercel automatically builds and deploys

Why Vercel:

  • ✅ Created by Next.js team (optimized for Next.js)
  • ✅ Edge network (fast globally)
  • ✅ Automatic preview deployments
  • ✅ Zero-config setup
  • ✅ Free tier for production use

Neon (PostgreSQL Hosting)

// Serverless PostgreSQL database
DATABASE_URL="postgresql://user:pass@ep-xxx.us-east-2.aws.neon.tech/rcweb"

Why Neon:

  • ✅ Serverless (scales to zero)
  • ✅ Generous free tier
  • ✅ Instant branching (dev/staging/prod)
  • ✅ Auto-scaling

Git & GitHub

# Version control and collaboration
git commit -m "Add newsletter campaign system"
git push origin main

Why Git/GitHub:

  • ✅ Complete version history
  • ✅ Easy rollbacks
  • ✅ Collaboration-ready
  • ✅ CI/CD integration

Key Features & How They're Built

1. Newsletter Campaign System

The Problem: Resend free tier limits: 100 emails/day

The Solution: Built a custom batch processing system

// Send 100 emails/day automatically
async function sendBatchCampaign(campaignId: string) {
  const campaign = await prisma.campaign.findUnique({
    where: { id: campaignId },
  });

  // Get next 100 contacts who haven't received the email
  const contacts = await prisma.contact.findMany({
    where: {
      marketingConsent: true,
      emails: {
        none: { campaignId },
      },
    },
    take: 100,
  });

  // Send emails
  for (const contact of contacts) {
    await resend.emails.send({
      from: 'RC Web <no-reply@rcweb.dev>',
      to: contact.email,
      subject: campaign.subject,
      html: campaign.content,
    });
  }

  // Update campaign status
  await prisma.campaign.update({
    where: { id: campaignId },
    data: {
      emailsSent: { increment: contacts.length },
      lastBatchSentAt: new Date(),
    },
  });
}

Features:

  • ✅ Send to 1000+ contacts over 10 days automatically
  • ✅ Track progress (emails sent, remaining, completion %)
  • ✅ Resume failed campaigns
  • ✅ Preview emails before sending
  • ✅ Multiple templates (Halloween, 20% OFF, etc.)

2. Payment Processing with Stripe

// Create checkout session
export async function createStripeCheckoutAction(
  packageId: string,
  amount: number,
  customerEmail: string
) {
  const session = await stripe.checkout.sessions.create({
    customer_email: customerEmail,
    line_items: [{
      price_data: {
        currency: 'usd',
        product_data: {
          name: `${packageId} Package`,
          description: 'Professional web development services',
        },
        unit_amount: amount * 100, // Convert to cents
      },
      quantity: 1,
    }],
    mode: 'payment',
    success_url: `${siteConfig.baseUrl}/success?session_id={CHECKOUT_SESSION_ID}`,
    cancel_url: `${siteConfig.baseUrl}/pricing`,
  });

  return { url: session.url };
}

Features:

  • ✅ Secure checkout
  • ✅ Multiple payment methods
  • ✅ Automatic receipts
  • ✅ Webhook handling for payment confirmation

3. Contact Management with Anti-Bot Protection

Multi-layer bot protection:

// Layer 1: Honeypot field (invisible to humans, visible to bots)
<input
  type="text"
  name="website"
  style={{ position: 'absolute', left: '-9999px' }}
/>

// Layer 2: Minimum time check (humans take >3 seconds)
const timeSpent = Date.now() - formMountTime;
if (timeSpent < 3000) {
  return { error: 'Form submitted too quickly' };
}

// Layer 3: reCAPTCHA v3 (invisible verification)
const token = await grecaptcha.execute(SITE_KEY, { action: 'submit' });
const score = await verifyRecaptchaToken(token);
if (score < 0.5) {
  return { error: 'Verification failed' };
}

Result: 99.9% spam reduction without annoying users

4. Cookie Consent (GDPR/CCPA Compliant)

// Track essential vs. optional cookies
const [consent, setConsent] = useState({
  essential: true,    // Required (can't be disabled)
  analytics: false,   // Optional (GA4)
  marketing: false,   // Optional (Facebook Pixel, ads)
});

// Only load scripts if user consents
{consent.analytics && <GoogleAnalytics />}
{consent.marketing && <FacebookPixel />}

Features:

  • ✅ Separate essential vs. optional cookies
  • ✅ Persistent consent (localStorage)
  • ✅ Easy to revoke
  • ✅ GDPR & CCPA compliant

5. Blog System with Markdown

// No database needed for blog posts!
// content/blog/my-post.md
---
title: "My Blog Post"
date: "2025-01-22"
---

# Content here in Markdown

Why Markdown:

  • ✅ Simple to write (no CMS needed)
  • ✅ Version controlled with Git
  • ✅ Fast (static generation)
  • ✅ SEO optimized automatically
  • ✅ Easy to migrate

6. Special Offers with Countdown Timer

// Real countdown that actually counts down
useEffect(() => {
  const endDate = new Date();
  endDate.setDate(endDate.getDate() + 7); // 7 days from now
  const endTime = endDate.getTime();

  const updateTimer = () => {
    const now = new Date().getTime();
    const distance = endTime - now;

    setTimeLeft({
      days: Math.floor(distance / (1000 * 60 * 60 * 24)),
      hours: Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)),
      minutes: Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60)),
      seconds: Math.floor((distance % (1000 * 60)) / 1000),
    });
  };

  const timer = setInterval(updateTimer, 1000);
  return () => clearInterval(timer);
}, []);

Architecture & Design Patterns

Component Architecture

src/
├── app/                    # Next.js app router
│   ├── (routes)/          # Page routes
│   ├── api/               # API routes
│   ├── components/        # Shared components
│   └── actions/           # Server actions
├── lib/                   # Utility functions
├── hooks/                 # Custom React hooks
├── config/                # Configuration files
└── types/                 # TypeScript types

Design Patterns Used

  1. Server Components (default) - Render on server for better performance
  2. Client Components ("use client") - Only when interactivity is needed
  3. Server Actions - Type-safe server mutations
  4. Optimistic Updates - Instant UI feedback
  5. Error Boundaries - Graceful error handling
  6. Loading States - Better UX with skeletons

Performance Optimizations

1. Image Optimization

// Automatic WebP conversion, lazy loading, responsive sizes
<Image
  src="/hero.jpg"
  width={1920}
  height={1080}
  alt="Hero"
  priority // Load immediately (above fold)
/>

2. Code Splitting

// Dynamic imports for heavy components
const HeavyComponent = dynamic(() => import('./HeavyComponent'), {
  loading: () => <Skeleton />,
  ssr: false, // Don't render on server
});

3. Font Optimization

// Preload critical fonts
import { Inter, Iceland } from 'next/font/google';

const inter = Inter({
  subsets: ['latin'],
  display: 'swap', // Prevent invisible text
});

4. Caching Strategy

// Static pages cached at CDN edge
export const revalidate = 3600; // Revalidate every hour

// Dynamic data cached in-memory
const cachedData = unstable_cache(
  async () => await fetchExpensiveData(),
  ['cache-key'],
  { revalidate: 60 }
);

Results:

  • Lighthouse Score: 95-100 (Performance)
  • First Contentful Paint: <1.5s
  • Time to Interactive: <3s
  • Total Bundle Size: <200KB (gzipped)

Security Measures

1. Input Validation

// Zod schema validation
const FormSchema = z.object({
  email: z.string().email('Invalid email'),
  phone: z.string().regex(/^\+?[1-9]\d{1,14}$/, 'Invalid phone'),
  message: z.string().min(10, 'Message too short').max(1000, 'Message too long'),
});

2. SQL Injection Prevention

// Prisma uses parameterized queries automatically
// ✅ SAFE:
await prisma.contact.findMany({ where: { email } });

// ❌ NEVER DO THIS:
await prisma.$executeRaw(`SELECT * FROM contacts WHERE email = '${email}'`);

3. Rate Limiting

// Prevent abuse of API endpoints
const rateLimit = new RateLimiter({
  interval: 60 * 1000, // 1 minute
  max: 10, // 10 requests per minute
});

4. Environment Variables

# Never commit secrets to Git
DATABASE_URL="postgresql://..."
STRIPE_SECRET_KEY="sk_live_..."
RESEND_API_KEY="re_..."

Challenges & Solutions

Challenge 1: Email Campaign Limits

Problem: Resend free tier = 100 emails/day, but I have 500+ contacts

Solution: Built batch processing system

  • Send 100/day automatically
  • Track progress in database
  • Resume after 24 hours
  • Campaign completion in 5 days for 500 contacts

Challenge 2: SMS Marketing Compliance

Problem: Twilio rejected campaign due to compliance issues

Solution:

  • Updated privacy policy (removed "without consent" clause)
  • Added "message frequency may vary" to opt-in
  • Changed use case from "mixed" to "marketing only"
  • Created detailed compliance documentation

Challenge 3: TypeScript Errors with Dynamic Routes

Problem: Type '/blog/${string}' is not assignable to Route

Solution: Used proper type assertion

import type { Route } from 'next';
<Link href={`/blog/${slug}` as Route}>

Challenge 4: Form Spam

Problem: Receiving 50+ spam submissions per day

Solution: Multi-layer protection

  • Honeypot fields
  • Minimum time check
  • reCAPTCHA v3
  • Email validation
  • Result: 99.9% spam reduction

Metrics & Results

Performance

  • ✅ Page Load Time: <2 seconds
  • ✅ Lighthouse Score: 95-100
  • ✅ SEO Score: 100
  • ✅ Accessibility: 95+

Business Impact

  • ✅ 40% increase in contact form submissions
  • ✅ 25% increase in average session duration
  • ✅ 60% reduction in bounce rate
  • ✅ 3x more newsletter signups

Technical

  • ✅ 0 critical bugs in production
  • ✅ 99.9% uptime
  • ✅ <200KB bundle size
  • ✅ Full TypeScript coverage

What's Next?

I'm constantly improving rcweb.dev. Here's what's on the roadmap:

Q1 2025

  • ✅ Blog system (completed!)
  • 🔄 Advanced analytics dashboard
  • 🔄 Invoice generation system
  • 🔄 Automated SEO reporting for clients

Q2 2025

  • Project management portal
  • Client dashboard (view project progress)
  • Live chat integration
  • A/B testing framework

Q3 2025

  • Mobile app (React Native)
  • API for third-party integrations
  • Advanced automation workflows

Lessons Learned

1. Start Simple, Scale Gradually

I didn't build all these features at once. I started with a basic site and added features as the business needed them. This approach:

  • ✅ Kept me focused on what matters
  • ✅ Prevented overwhelm
  • ✅ Allowed for iteration based on real feedback

2. TypeScript is Worth It

Yes, it's more setup initially. But it has saved me countless hours of debugging and prevented numerous production bugs.

3. Choose Boring Technology (Sometimes)

I used PostgreSQL instead of the "cool new NoSQL database" because:

  • It's proven and reliable
  • Great documentation
  • Large community
  • Battle-tested

Hot take: Sometimes boring is better.

4. Invest in Developer Experience

Tools like Prisma, TypeScript, and Tailwind CSS make development faster and more enjoyable. The upfront learning curve pays dividends.

5. Performance Matters

A fast website is a converting website. Every 100ms improvement in load time increases conversion rates.


Want to Build Something Similar?

This tech stack is perfect for:

  • ✅ Business websites with advanced features
  • ✅ SaaS applications
  • ✅ E-commerce platforms
  • ✅ Portfolio sites with CMS
  • ✅ Booking/reservation systems

If you're interested in building a custom application like this, let's talk! I can help you:

  • Choose the right tech stack for your needs
  • Design scalable architecture
  • Implement complex features
  • Deploy to production
  • Maintain and optimize

Open Source?

I'm considering open-sourcing parts of this project, particularly:

  • Newsletter campaign system
  • Multi-layer bot protection
  • Cookie consent management
  • Batch processing utilities

Interested? Let me know in the comments or send me a message!


Final Thoughts

Building rcweb.dev has been an incredible learning experience. What started as a simple portfolio has evolved into a comprehensive business application that handles everything from client acquisition to payment processing.

The key takeaways:

  1. Use modern tools - They make development faster and more reliable
  2. Optimize for performance - Your users (and Google) will thank you
  3. Iterate based on real needs - Don't over-engineer from day one
  4. Measure everything - Data-driven decisions beat assumptions
  5. Never stop learning - Technology evolves, and so should your skills

Tech Stack Summary

Frontend:

  • Next.js 14
  • TypeScript
  • Tailwind CSS
  • Framer Motion

Backend:

  • PostgreSQL
  • Prisma ORM
  • Next.js Server Actions

Integrations:

  • Stripe (Payments)
  • Resend (Email)
  • Twilio (SMS)
  • Google Analytics 4
  • Facebook Pixel

Hosting:

  • Vercel (Application)
  • Neon (Database)

Tools:

  • Git/GitHub
  • VS Code
  • Postman
  • Figma

Have questions about the tech stack or want to discuss your own project? Contact me - I'd love to chat!


This article is part of our ongoing series about web development, technology, and business growth. Subscribe to our newsletter to get notified when new articles are published.

RC Web Solutions LLC Building the future, one line of code at a time.

Ready to Start Your Project?

Let's bring your vision to life. Contact us today for a free consultation.

Get Started