A robust, TypeScript-based REST API built with Express.js that securely handles contact form submissions and directly integrates with Notion databases. Designed with Clean Architecture principles, strict request validation, and professional-grade logging.
- TypeScript & Clean Architecture: Organized, scalable, and maintainable codebase.
- Notion SDK Integration: Automatically creates new rows in a Notion database upon valid form submission.
- Strict Validation: Uses Zod for precise and robust payload validation.
- Professional Logging: Configured with Winston (application logs) and Morgan (HTTP request logs) for comprehensive monitoring.
- Developer Experience (DX): Hot-reloading with
nodemon+ts-node, alongside strict ESLint and Prettier configurations. - Security & CORS: Fully configured for secure third-party frontend access.
src/
├── config/ # Environment and middleware configurations (CORS)
├── controllers/ # Route handlers and HTTP logic
├── routes/ # Dynamic Express routers
├── services/ # Core business logic (Notion API integration)
├── types/ # TypeScript interfaces and Zod schemas
├── utils/ # Helper utilities (Validation middleware, Logger)
├── app.ts # Express application setup
└── server.ts # Server entry point
- Node.js (v18+ recommended)
- A Notion Integration Token (Create one at Notion Developers)
- A Notion Database with
Name(title),Email(email), andMessage(rich_text) properties. Make sure to connect your integration to the database.
-
Clone the repository (or download the source):
git clone https://github.com/wafley/client-ping.git cd client-ping -
Install dependencies:
npm install
-
Configure Environment Variables: Copy
.env.exampleto.envand fill in your details:cp .env.example .env
Required variables:
PORT: (default: 3000)NOTION_TOKEN: Your internal Notion integration secret.NOTION_DATABASE_ID: The ID of your target Notion database.ALLOWED_ORIGINS: Comma-separated list of allowed frontend domains (default is*).
Start the development server with hot-reloading:
npm run devThe server will start at http://localhost:3000.
Accepts a JSON payload to submit a contact form.
Request Body:
{
"name": "John Doe",
"email": "john@example.com",
"message": "Hello! I am interested in your services."
}Success Response (200 OK):
{
"status": "success",
"message": "Contact form submitted successfully"
}Validation Error (400 Bad Request):
{
"status": "error",
"message": "Validation failed",
"errors": [
{
"path": "email",
"message": "Invalid email address"
}
]
}npm run dev: Starts the server in development mode usingnodemon.npm run build: Compiles the TypeScript code to JavaScript in thedist/folder.npm run start: Runs the compiled production code.npm run lint: Analyzes the code using ESLint.npm run format: Formats all source files using Prettier.
Contributions are what make the open-source community such an amazing place to learn, inspire, and create. Any contributions you make are greatly appreciated.
- Fork the Project
- Create your Feature Branch (
git checkout -b feature/AmazingFeature) - Commit your Changes (
git commit -m 'feat: add some AmazingFeature') - Push to the Branch (
git push origin feature/AmazingFeature) - Open a Pull Request
Please ensure your code passes the linting and formatting checks (npm run lint and npm run format) before opening a pull request.
Distributed under the MIT License. See LICENSE for more information.