Wendy LogoWendy

Simple Web Server

Build a long-running HTTP server on WendyOS using TypeScript

Building a Web Server with Express

Source Code: The complete source code for this example is available at github.com/wendylabsinc/samples/node-typescript/simple-server

Often times you'll want a long-running server where you can make HTTP or WebSocket calls to your WendyOS device. This allows your device to accept incoming requests and respond to them, making it easy to build interactive applications or APIs that can be accessed from other devices on your network.

This guide shows you how to build a web server using Node.js with Express, the most popular and battle-tested framework for Node.js.

Prerequisites

  • Wendy CLI installed on your development machine
  • Node.js 22 or later installed
  • Docker installed (see Docker Installation)
  • A WendyOS device plugged in over USB or connectable over Wi-Fi

Setting Up Your Project

Create a New Directory

First, create a directory for your project:

mkdir simple-server
cd simple-server

Initialize the Project

Initialize a new Node.js project with TypeScript and Express:

npm init -y
npm install express
npm install --save-dev typescript @types/node @types/express tsx
npx tsc --init

Configure Package.json

Update your package.json:

{
  "name": "simple-server",
  "version": "0.1.0",
  "type": "module",
  "scripts": {
    "build": "tsc",
    "start": "node dist/index.js",
    "dev": "tsx watch src/index.ts"
  },
  "dependencies": {
    "express": "^4"
  },
  "devDependencies": {
    "@types/express": "^5",
    "@types/node": "^22",
    "typescript": "^5.7",
    "tsx": "^4"
  },
  "engines": {
    "node": ">=22"
  }
}

Update tsconfig.json

Update your tsconfig.json:

{
  "compilerOptions": {
    "target": "ES2022",
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "outDir": "./dist",
    "rootDir": "./src",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "declaration": true
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "dist"]
}

Create the Web Server

Create src/index.ts:

import express, { Request, Response } from "express";

const app = express();
const port = 3000;

app.use(express.json());

app.get("/", (_req: Request, res: Response) => {
  res.send("Hello, World!");
});

app.get("/hello/:name", (req: Request, res: Response) => {
  res.send(`Hello, ${req.params.name}!`);
});

interface CreateUserBody {
  username: string;
}

interface User {
  id: number;
  username: string;
}

app.post("/users", (req: Request<{}, User, CreateUserBody>, res: Response) => {
  const user: User = {
    id: 1,
    username: req.body.username,
  };
  res.status(201).json(user);
});

app.listen(port, () => {
  console.log(`Server running on http://localhost:${port}`);
});

Multiple Routes: This example includes three routes:

  • GET / - Returns "Hello, World!"
  • GET /hello/:name - Returns a personalized greeting
  • POST /users - Creates a new user from JSON body

Create a Dockerfile

Create a Dockerfile in the project root:

# Build stage
FROM node:22-slim AS builder

WORKDIR /app
COPY package*.json ./
RUN npm install

COPY tsconfig.json ./
COPY src ./src
RUN npm run build

# Runtime stage
FROM node:22-slim

WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules

EXPOSE 3000

CMD ["node", "dist/index.js"]

Deploy to WendyOS Device

Deploy your containerized web server to your WendyOS device:

wendy run

Test Your Server on WendyOS

After deploying your server to your WendyOS device, you can test it from your development machine.

You can configure wendy.json with a readiness probe and postStart hook to automatically open your browser when the server is ready:

{
  "readiness": {
    "tcpSocket": { "port": 3000 },
    "timeoutSeconds": 30
  },
  "hooks": {
    "postStart": {
      "cli": "open http://${WENDY_HOSTNAME}:3000"
    }
  }
}

Linux users: Replace open with xdg-open in the postStart hook.

Or open your browser manually and navigate to:

http://wendyos-true-probe.local:3000

Replace the hostname: Each WendyOS device has a unique hostname. Replace wendyos-true-probe with your device's actual hostname shown in the CLI output. In addition, don't forget to add the port to the hostname.

You should see the following output:

Hello, World!

This confirms your web server is successfully running on your WendyOS device and accepting requests from your network.

Verifying Deployment

You can verify the server container is running by listing the applications on your device:

wendy device apps list

You should see your containerized web server listed among the running applications.

Learn More

Express is the most popular Node.js web framework. Learn more at https://expressjs.com/

Alternative Frameworks

While this guide covers Express, many other excellent TypeScript web frameworks will work similarly on WendyOS:

  • Fastify: Fast and low overhead web framework
  • Koa: Expressive middleware framework by the Express team
  • Hono: Works on Node.js, Bun, Deno, and edge runtimes
  • NestJS: Progressive framework for building scalable server-side applications

All of these frameworks can be containerized and deployed to WendyOS following the same Docker-based approach outlined in this guide.

Next Steps

Now that you have a basic web server running:

  • Add more routes to handle different endpoints
  • Implement PUT and DELETE routes for a full REST API
  • Add middleware for logging, authentication, and error handling
  • Parse query parameters
  • Implement WebSocket support for real-time communication
  • Connect to databases and external APIs