2025-06-21 23:09:28 -05:00
2025-06-21 23:09:28 -05:00
2025-06-21 23:09:28 -05:00
2025-06-21 23:09:28 -05:00
2025-06-21 23:09:28 -05:00
2025-06-21 23:09:28 -05:00
2025-06-21 23:09:28 -05:00
2025-06-21 23:09:28 -05:00
2025-06-21 23:09:28 -05:00
2025-06-21 23:09:28 -05:00
2025-06-21 23:09:28 -05:00
2025-06-21 23:09:28 -05:00
2025-06-21 23:09:28 -05:00
2025-06-21 23:09:28 -05:00
2025-06-21 23:09:28 -05:00
2025-06-21 23:09:28 -05:00
2025-06-21 23:09:28 -05:00
2025-06-21 23:09:28 -05:00
2025-06-21 23:09:28 -05:00

Minimal Express.js Scaffolding

This project offers a streamlined and minimalistic scaffolding for Express.js applications. Unlike many generators that require extensive cleanup before you can begin, this boilerplate strikes a balance between simplicity and completeness. It provides just the essentials, allowing you to pull the repository, customize the project name, and start building your API immediately.

Support the Project

If you find this project useful, consider supporting its development:

Donate using Liberapay

Installation

To install the project dependencies, run the following command:

pnpm install

Running the App

To run the application in development mode with live reloading, use:

pnpm dev

To build and run the application for production, use:

pnpm start

Customization

To rename the project, modify the "name" field in the package.json file.

{
  "name": "your-project-name"
}

Technologies Used

  • Express: Fast, unopinionated, minimalist web framework for Node.js.
  • TypeScript: Typed superset of JavaScript that compiles to plain JavaScript.
  • Jest: A delightful JavaScript Testing Framework with a focus on simplicity.
  • Knip: A tool to find unused files, dependencies, and exports in your JavaScript and TypeScript projects.
  • ESLint: A pluggable and configurable linter tool for identifying and reporting on patterns in JavaScript.
  • Docker: A platform for developing, shipping, and running applications in containers.
  • tsx: A CLI to seamlessly execute TypeScript and ESM.
  • tsdown: A tool for building TypeScript projects.

Scripts

  • pnpm start: Starts the production server after building the project.
  • pnpm dev: Runs the application in development mode with live reloading.
  • pnpm build: Builds the TypeScript project into JavaScript.
  • pnpm test: Runs the test suite using Jest and generates a coverage report.
  • pnpm test:watch: Runs the tests in watch mode, re-running them on file changes.
  • pnpm knip: Finds unused files, dependencies, and exports.
  • pnpm lint: Lints the codebase using ESLint and automatically fixes issues.

Building This Scaffold From Scratch

Here is a detailed, step-by-step guide to creating this scaffold from the ground up.

Requirements

Step-by-Step Guide

  1. Initialize the project:

    pnpm init
    
  2. Install Express:

    pnpm install express
    
  3. Set up TypeScript:

    pnpm install --save-dev typescript @types/node @types/express
    npx tsc --init
    
  4. Create the main application file: Create a file at src/index.ts.

  5. Install tsx for development and tsdown for building:

    pnpm install --save-dev tsx tsdown
    
  6. Configure tsdown: Create a tsdown.config.ts file:

    import { defineConfig } from 'tsdown';
    
    export default defineConfig({
      entry: 'src/index.ts',
      format: ["esm"],
      target: "ESNext",
      platform: "node"
    });
    
  7. Configure tsconfig.json: Modify your tsconfig.json to look like this:

    {
      "compilerOptions": {
        "target": "ESNext",
        "module": "ESNext", 
        "moduleResolution": "Bundler",
        "baseUrl": "src",
        "paths": {              
          "@*": ["*"]
        },
        "esModuleInterop": true,
        "forceConsistentCasingInFileNames": true,
        "strict": true,
        "skipLibCheck": true
      }
    }
    
    
  8. Set up Jest for testing:

    pnpm install --save-dev jest ts-jest @types/jest @types/supertest supertest
    npx ts-jest config:init
    

    This will create a jest.config.js file.

  9. Refactor the application for testability:

    • Move all your Express app definition logic from src/index.ts into a new src/server.ts file.
    • The src/index.ts file should only contain the server.listen() part, which starts the server.
    • Create a tests folder and mirror the structure of your src folder for your test files.
  10. Install Knip to keep the project clean:

    pnpm add -D knip
    
  11. Set up ESLint for code linting:

    pnpm add --save-dev eslint jiti @eslint/js typescript-eslint @stylistic/eslint-plugin eslint-plugin-n
    

    Create an eslint.config.ts file with the following settings (modify as needed):

        import eslint from '@eslint/js';
    import tseslint from 'typescript-eslint';
    import stylistic from '@stylistic/eslint-plugin';
    import nodePlugin from 'eslint-plugin-n';
    
    export default tseslint.config(
    eslint.configs.recommended,
    nodePlugin.configs['flat/recommended-script'],
    ...tseslint.configs.strictTypeChecked,
    ...tseslint.configs.stylisticTypeChecked,
    { 
        ignores: [
        '**/node_modules/*',
        '**/*.mjs',
        '**/*.js',
        ],
    },
    {
        languageOptions: {
        parserOptions: {
            project: './tsconfig.json',
            warnOnUnsupportedTypeScriptVersion: false,
        },
        },
    },
    {
        plugins: {
        '@stylistic/js': stylistic,
        '@stylistic/ts': stylistic,
        },
    },
    {
        files: ['**/*.ts'],
    },
    {
        rules: {
        '@typescript-eslint/explicit-member-accessibility': 'warn',
        '@typescript-eslint/no-misused-promises': 0,
        '@typescript-eslint/no-floating-promises': 0,
        '@typescript-eslint/no-confusing-void-expression': 0,
        '@typescript-eslint/no-unnecessary-condition': 0,
        '@typescript-eslint/restrict-template-expressions': [
            'error', { allowNumber: true },
        ],
        '@typescript-eslint/restrict-plus-operands': [
            'warn', { allowNumberAndString: true },
        ],
        '@typescript-eslint/no-unused-vars': 'warn',
        '@typescript-eslint/no-unsafe-enum-comparison': 0,
        '@typescript-eslint/no-unnecessary-type-parameters': 0,
        '@stylistic/js/no-extra-semi': 'warn',
        'max-len': [
            'warn',
            {
            'code': 80,
            },
        ],
        '@stylistic/ts/semi': ['warn', 'always'],
        '@stylistic/ts/member-delimiter-style': ['warn', {
            'multiline': {
            'delimiter': 'comma',
            'requireLast': true,
            },
            'singleline': {
            'delimiter': 'comma',
            'requireLast': false,
            },
            'overrides': {
            'interface': {
                'singleline': {
                'delimiter': 'semi',
                'requireLast': false,
                },
                'multiline': {
                'delimiter': 'semi',
                'requireLast': true,
                },
            },
            },
        }],
        '@typescript-eslint/no-non-null-assertion': 0,
        '@typescript-eslint/no-unused-expressions': 'warn',
        'comma-dangle': ['warn', 'always-multiline'],
        'no-console': 1,
        'no-extra-boolean-cast': 0,
        'indent': ['warn', 2],
        'quotes': ['warn', 'single'],
        'n/no-process-env': 1,
        'n/no-missing-import': 0,
        'n/no-unpublished-import': 0,
        'prefer-const': 'warn',
        },
    },
    );
    
  12. Set up Docker: Create a Dockerfile file:

        # Use the official Node.js image.
        FROM node:22-slim
    
        # Create and change to the app directory.
        WORKDIR /usr/src/app
    
        # Copy package.json and pnpm-lock.yaml
        COPY package.json pnpm-lock.yaml ./
    
        # Install pnpm
        RUN npm install -g pnpm
    
        # Install dependencies
        RUN pnpm install
    
        # Copy the rest of the application's source code.
        COPY . .
    
        # Build the project
        RUN pnpm run build
    
        # Expose the port the app runs on
        EXPOSE 3000
    
        # Serve the app
        CMD [ "pnpm", "start" ]
    

    Create a docker-compose.yml file:

    services:
      exp-min:
        build: .
        container_name: "exp-min"
        ports:
          - "3000:3000"
    
Description
Streamlined and minimalistic scaffolding for Express.js applications
Readme 221 KiB
Languages
TypeScript 77.7%
JavaScript 15.6%
Dockerfile 6.7%