cd..blog

Full-Stack Fusion: Express, Netlify, CI/CD & State Management

const published = "Nov 8, 2025, 10:22 PM";const readTime = 5 min;
typescriptexpressjsnetlifyci/cdstate management
Master full-stack development by integrating TypeScript Express APIs, Netlify's serverless functions, robust CI/CD, and modern state management with Zustand.

Modern web development thrives on seamless integration and efficient workflows. This post demonstrates how to combine an Express.js API, Netlify's powerful hosting and serverless functions, robust CI/CD practices, and a modern state management solution using TypeScript.

Architecture at a Glance

Our architecture features a frontend (e.g., React/Vite) hosted on Netlify, consuming data from a TypeScript Express API. This Express API is deployed as Netlify Functions, leveraging Netlify's built-in CI/CD for automated deployments. Client-side state is managed efficiently using Zustand.

Express API with TypeScript

Express.js provides a robust and flexible foundation for building APIs. We'll create a simple Express application that can then be deployed as a Netlify Function. Express.js is a minimal and flexible Node.js web application framework that provides a robust set of features for web and mobile applications.

First, set up your Express project:

// api/server.ts
import express from 'express';
import cors from 'cors';

const app = express();
app.use(cors()); // Enable CORS for frontend access
app.use(express.json());

// A simple API endpoint
app.get('/api/greeting', (req, res) => {
  res.json({ message: 'Hello from Express API!', timestamp: new Date() });
});

// Export the app for serverless deployment
export default app;

Frontend State Management with Zustand

For the frontend, we'll use React (or any framework) and Zustand for state management. Zustand is a small, fast, and scalable bear-necessities state-management solution using simplified flux principles, making it ideal for modern React applications.

Define a simple store to hold our API data:

// src/store/useGreetingStore.ts
import { create } from 'zustand';

interface GreetingState {
  message: string;
  timestamp: string | null;
  fetchGreeting: () => Promise<void>;
}

export const useGreetingStore = create<GreetingState>((set) => ({
  message: 'Loading...', 
  timestamp: null,
  fetchGreeting: async () => {
    try {
      const response = await fetch('/.netlify/functions/api/greeting'); // Relative path to Netlify Function
      const data = await response.json();
      set({ message: data.message, timestamp: data.timestamp });
    } catch (error) {
      console.error('Failed to fetch greeting:', error);
      set({ message: 'Error fetching greeting.', timestamp: null });
    }
  },
}));

Consume this store in a React component:

// src/components/GreetingDisplay.tsx
import React, { useEffect } from 'react';
import { useGreetingStore } from '../store/useGreetingStore';

const GreetingDisplay: React.FC = () => {
  const { message, timestamp, fetchGreeting } = useGreetingStore();

  useEffect(() => {
    fetchGreeting();
  }, [fetchGreeting]);

  return (
    <div>
      <h2>API Greeting:</h2>
      <p>{message}</p>
      {timestamp && <p>Timestamp: {new Date(timestamp).toLocaleString()}</p>}
    </div>
  );
};

export default GreetingDisplay;

Netlify Integration: Hosting & Serverless Functions

Netlify provides an excellent platform for hosting single-page applications and deploying serverless functions. We'll deploy our frontend and wrap our Express API into a Netlify Function. Netlify Functions allow you to run backend code without managing servers, integrating seamlessly with your frontend deployment.

First, configure your netlify.toml:

# netlify.toml
[build]
  command = "npm run build" # Your frontend build command
  publish = "dist"         # Your frontend build output directory

[functions]
  directory = "netlify/functions" # Where your Netlify Functions reside

[[redirects]]
  from = "/api/*"
  to = "/.netlify/functions/api/:splat"
  status = 200

Next, create the Netlify Function handler for your Express app:

// netlify/functions/api.ts
import serverless from 'serverless-http';
import app from '../../api/server'; // Adjust path to your Express app

// This wraps your Express app to make it compatible with Netlify Functions
export const handler = serverless(app);

Ensure you install serverless-http (npm install serverless-http). This package allows existing Node.js HTTP servers (like Express) to run in a serverless environment.

CI/CD & DevOps with Netlify

Netlify offers powerful, built-in CI/CD capabilities that streamline your deployment process. By connecting your GitHub, GitLab, or Bitbucket repository, every push to your main branch automatically triggers a build and deployment. Netlify CI/CD automates the entire deployment pipeline, from code commit to global CDN delivery.

  1. Connect Repository: Link your project's Git repository to Netlify.
  2. Build Settings: Netlify automatically detects netlify.toml for build commands and publish directories.
  3. Environment Variables: Manage sensitive API keys and configuration via Netlify's UI for secure CI/CD.

Any commit to your configured branch will initiate a build, deploy your frontend, and publish your serverless functions, providing a robust DevOps pipeline with minimal configuration.

Conclusion

Integrating Express, Netlify, CI/CD, and modern state management like Zustand with TypeScript creates a powerful, scalable, and maintainable full-stack application. This approach simplifies deployment, enhances developer experience, and leverages serverless architecture for cost-effectiveness and performance. By understanding how these pieces fit together, you can build sophisticated web applications with confidence and agility.