Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
root = true

[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.md]
trim_trailing_whitespace = false
2 changes: 2 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
NODE_ENV=development
PORT=3000
20 changes: 20 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
name: CI

on:
pull_request:
push:
branches: [main]

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version-file: .nvmrc
cache: npm
- run: npm ci
- run: npm run lint
- run: npm run format:check
- run: npm test
10 changes: 10 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
node_modules/
coverage/
.env
.env.local
.env.*.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.DS_Store
*.log
1 change: 1 addition & 0 deletions .husky/commit-msg
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
npx --no-install commitlint --edit "$1"
1 change: 1 addition & 0 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
npx lint-staged
1 change: 1 addition & 0 deletions .nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
20
4 changes: 4 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
node_modules
coverage
package-lock.json
.husky
8 changes: 8 additions & 0 deletions .prettierrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"singleQuote": true,
"trailingComma": "all",
"semi": true,
"printWidth": 100,
"arrowParens": "always",
"endOfLine": "lf"
}
91 changes: 90 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,92 @@
# api00

Node.js + Express starter API (JavaScript, no DB, no auth).
Node.js + Express starter API in plain JavaScript. No database, no auth — just a clean
foundation to grow a real API on top of.

## Stack

- Node.js 20+ (ESM)
- [Express](https://expressjs.com/) 4
- [Vitest](https://vitest.dev/) + [supertest](https://github.com/ladjs/supertest) for tests
- ESLint (flat config) + Prettier + EditorConfig
- Husky + lint-staged + commitlint (Conventional Commits)
- GitHub Actions CI (lint + format check + tests)

## Requirements

- Node.js 20 or later (see `.nvmrc`)
- npm 10+

## Getting started

```bash
# install dependencies (also installs git hooks via the prepare script)
npm install

# copy the example env file
cp .env.example .env

# run the dev server with auto-reload
npm run dev
```

The API listens on `http://localhost:3000` by default.

## Endpoints

| Method | Path | Description |
| ------ | --------- | ----------------------------------- |
| GET | `/` | API metadata (name, version, links) |
| GET | `/health` | Liveness probe with uptime |

Unknown routes return `404` with a JSON body `{ "error": "Not Found", "path": "..." }`.

## Scripts

| Script | What it does |
| ---------------------- | -------------------------------------- |
| `npm run dev` | Start the server with `node --watch` |
| `npm start` | Start the server without watch |
| `npm run lint` | Run ESLint |
| `npm run lint:fix` | Run ESLint with `--fix` |
| `npm run format` | Write Prettier formatting |
| `npm run format:check` | Check Prettier formatting (used in CI) |
| `npm test` | Run Vitest once |
| `npm run test:watch` | Run Vitest in watch mode |

## Project layout

```
src/
app.js # Express app factory (testable, no listen)
server.js # Entrypoint: creates app and listens on PORT
config/
env.js # Typed env loader (dotenv)
routes/
index.js # GET /
health.js # GET /health
middleware/
notFound.js # 404 JSON handler
errorHandler.js # Centralized error handler
tests/
root.test.js
health.test.js
```

## Environment variables

| Name | Default | Description |
| ---------- | ------------- | ------------------------------- |
| `NODE_ENV` | `development` | Runtime environment |
| `PORT` | `3000` | Port the HTTP server listens on |

## Git hooks

`husky` installs two hooks via `npm install`:

- **pre-commit**: runs `lint-staged` (ESLint + Prettier on staged files).
- **commit-msg**: validates commit messages with `commitlint` (Conventional Commits).

## License

Unlicensed — add one when the project grows beyond a personal sandbox.
3 changes: 3 additions & 0 deletions commitlint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default {
extends: ['@commitlint/config-conventional'],
};
21 changes: 21 additions & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import js from '@eslint/js';
import globals from 'globals';
import prettier from 'eslint-config-prettier';

export default [
{
ignores: ['node_modules/', 'coverage/'],
},
js.configs.recommended,
{
languageOptions: {
ecmaVersion: 2023,
sourceType: 'module',
globals: { ...globals.node },
},
rules: {
'no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
},
},
prettier,
];
Loading
Loading