{"id":51075351,"url":"https://github.com/codestorm-official/playwright-with-nodejs","last_synced_at":"2026-06-23T13:41:16.984Z","repository":{"id":356213092,"uuid":"1231508807","full_name":"codestorm-official/playwright-with-nodejs","owner":"codestorm-official","description":"Production-oriented API for scraping demo pages with Playwright, Express, TypeScript, and Swagger/OpenAPI documentation.","archived":false,"fork":false,"pushed_at":"2026-05-07T04:10:37.000Z","size":57,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-07T05:37:42.927Z","etag":null,"topics":["playwirght-automation","playwright","playwright-nodejs","playwright-typescript"],"latest_commit_sha":null,"homepage":"https://railway.com/deploy/playwright-with-nodejs","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/codestorm-official.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-07T03:02:07.000Z","updated_at":"2026-05-07T04:11:55.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/codestorm-official/playwright-with-nodejs","commit_stats":null,"previous_names":["codestorm-official/playwright-with-nodejs"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/codestorm-official/playwright-with-nodejs","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codestorm-official%2Fplaywright-with-nodejs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codestorm-official%2Fplaywright-with-nodejs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codestorm-official%2Fplaywright-with-nodejs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codestorm-official%2Fplaywright-with-nodejs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/codestorm-official","download_url":"https://codeload.github.com/codestorm-official/playwright-with-nodejs/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codestorm-official%2Fplaywright-with-nodejs/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34692768,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-23T02:00:07.161Z","response_time":65,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["playwirght-automation","playwright","playwright-nodejs","playwright-typescript"],"created_at":"2026-06-23T13:41:16.267Z","updated_at":"2026-06-23T13:41:16.974Z","avatar_url":"https://github.com/codestorm-official.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"![Railway](https://img.shields.io/badge/Railway-Supported-blue?logo=railway)\n![Docker](https://img.shields.io/badge/Docker-Supported-blue?logo=docker)\n![Node.js](https://img.shields.io/badge/Node.js-Supported-green?logo=node.js)\n![TypeScript](https://img.shields.io/badge/TypeScript-Supported-blue?logo=typescript)\n![Express](https://img.shields.io/badge/Express-Supported-yellow?logo=express)\n\n# Playwright with Node.js\n\nProduction-oriented API for scraping demo pages with Playwright, Express, TypeScript, and Swagger/OpenAPI documentation.\n\n[![Deploy on Railway](https://railway.com/button.svg)](https://railway.com/deploy/playwright-with-nodejs?referralCode=asepsp\u0026utm_medium=integration\u0026utm_source=template\u0026utm_campaign=generic)\n\n![](./img/docs.png)\n\n## Features\n\n- Express API with route, controller, service, middleware, and utility layers\n- Playwright Chromium scraping through a shared browser service\n- Swagger UI at `/docs` and OpenAPI JSON at `/openapi.json`\n- Zod request validation, Helmet, CORS, compression, and rate limiting\n- Winston structured logging\n- Jest unit tests and Playwright API/e2e tests\n- Docker image with Playwright browser dependency installation\n\n## Requirements\n\n- Node.js 20+\n- npm\n- Docker, optional for container deployment\n\n## Quick Start\n\n```bash\nnpm install\ncp .env.example .env\nnpm run dev\n```\n\nThe API runs on `http://localhost:3000` by default.\n\nUseful URLs:\n\n- Root: `http://localhost:3000/` redirects to `/docs`\n- Health: `http://localhost:3000/health`\n- Swagger UI: `http://localhost:3000/docs`\n- OpenAPI JSON: `http://localhost:3000/openapi.json`\n\n## Scripts\n\n```bash\nnpm run dev            # Start TypeScript dev server\nnpm run build          # Compile src/ to dist/\nnpm start              # Run compiled app\nnpm run typecheck      # TypeScript check without emit\nnpm run lint           # ESLint\nnpm run format:check   # Prettier check\nnpm test               # Jest tests\nnpm run test:e2e       # Playwright API/e2e tests\nnpm run docker:build   # Build Docker image\nnpm run docker:compose # Start with Docker Compose\nnpm run zip            # Build and create distribution zip\n```\n\n## API Endpoints\n\n### Root\n\n```http\nGET /\n```\n\nRedirects to `/docs`.\n\n### Health\n\n```http\nGET /health\n```\n\nReturns service health, uptime, environment, and timestamp.\n\n### Scrape Test Sites\n\n```http\nGET /api/scrape/sites\n```\n\nScrapes available test site links from `SCRAPER_BASE_URL`.\n\n### Scrape E-commerce Products\n\n```http\nGET /api/scrape/ecommerce/products?limit=10\n```\n\nQuery parameters:\n\n- `limit`: integer from 1 to 50, default `10`\n\n### Run Scrape Task\n\n```http\nPOST /api/scrape/run\nContent-Type: application/json\n\n{\n  \"target\": \"ecommerce\",\n  \"limit\": 10\n}\n```\n\nSupported targets:\n\n- `test-sites`\n- `ecommerce`\n\n### Run Smoke Test\n\n```http\nPOST /api/tests/smoke\nContent-Type: application/json\n\n{\n  \"target\": \"test-sites\"\n}\n```\n\n## Response Format\n\nSuccess responses:\n\n```json\n{\n  \"success\": true,\n  \"data\": {},\n  \"meta\": {\n    \"durationMs\": 123,\n    \"timestamp\": \"2026-05-07T00:00:00.000Z\"\n  }\n}\n```\n\nError responses:\n\n```json\n{\n  \"success\": false,\n  \"error\": \"Error message\",\n  \"meta\": {\n    \"durationMs\": 12,\n    \"timestamp\": \"2026-05-07T00:00:00.000Z\"\n  }\n}\n```\n\n## Project Structure\n\n```text\nplaywright-with-nodejs/\n|-- src/\n|   |-- app.ts\n|   |-- index.ts\n|   |-- server.ts\n|   |-- scraper.ts\n|   |-- scraper.test.ts\n|   |-- config/\n|   |-- controllers/\n|   |-- middlewares/\n|   |-- routes/\n|   |-- schemas/\n|   |-- services/\n|   |-- types/\n|   `-- utils/\n|-- tests/\n|   `-- e2e/\n|-- docker/\n|   `-- entrypoint.sh\n|-- Dockerfile\n|-- docker-compose.yml\n|-- jest.config.js\n|-- playwright.config.ts\n|-- package.json\n|-- tsconfig.json\n`-- README.md\n```\n\n`dist/`, `coverage/`, `test-results/`, and `playwright-report/` are generated outputs.\n\n## Environment Variables\n\n| Variable                | Default                                                | Description                                                 |\n| ----------------------- | ------------------------------------------------------ | ----------------------------------------------------------- |\n| `NODE_ENV`              | `development`                                          | Runtime environment: `development`, `production`, or `test` |\n| `PORT`                  | `3000`                                                 | HTTP port                                                   |\n| `HOST`                  | `0.0.0.0`                                              | Bind host                                                   |\n| `LOG_LEVEL`             | `info`                                                 | Winston log level                                           |\n| `CORS_ORIGIN`           | `*`                                                    | Allowed CORS origin, comma-separated for multiple origins   |\n| `SCRAPER_BASE_URL`      | `https://webscraper.io/test-sites`                     | Test site source URL                                        |\n| `SCRAPER_ECOMMERCE_URL` | `https://webscraper.io/test-sites/e-commerce/allinone` | E-commerce source URL                                       |\n| `PLAYWRIGHT_HEADLESS`   | `true`                                                 | Browser headless mode                                       |\n| `PLAYWRIGHT_TIMEOUT_MS` | `30000`                                                | Playwright page/navigation timeout                          |\n| `SCRAPER_MAX_LIMIT`     | `50`                                                   | Maximum scrape limit used by configuration                  |\n| `RATE_LIMIT_WINDOW_MS`  | `60000`                                                | Rate limit window                                           |\n| `RATE_LIMIT_MAX`        | `60`                                                   | Max requests per rate limit window                          |\n\n## Docker\n\nBuild and run:\n\n```bash\nnpm run docker:build\ndocker run -p 3000:3000 --env-file .env playwright-api:latest\n```\n\nOr use Compose:\n\n```bash\nnpm run docker:compose\n```\n\nThe Dockerfile uses Debian slim instead of Alpine so Playwright can install Chromium and OS dependencies more reliably. If `package-lock.json` exists, Docker uses `npm ci`; otherwise it falls back to `npm install`. For repeatable production builds, generate and commit `package-lock.json`.\n\n## Production Checklist\n\n- Set `NODE_ENV=production`\n- Configure `CORS_ORIGIN` instead of using `*`\n- Use `LOG_LEVEL=warn` or `error`\n- Commit `package-lock.json` for deterministic installs\n- Send logs to external storage in production\n- Put the service behind HTTPS/reverse proxy\n- Set CPU and memory limits for the container\n- Monitor `/health`\n- Validate target sites are reachable from the deployment environment\n\n## Notes\n\n- Scraping and e2e tests depend on external network access to `webscraper.io`.\n- Swagger uses a relative OpenAPI server URL (`/`) so the \"Try it out\" button calls the same origin used to open `/docs`.\n- Endpoint-level `headless` values are accepted by current schemas for compatibility, but browser mode is controlled by `PLAYWRIGHT_HEADLESS`.\n- `src/scraper.ts` is a legacy standalone scraper used by Jest tests; the main API uses the service/controller stack under `src/services` and `src/controllers`.\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcodestorm-official%2Fplaywright-with-nodejs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcodestorm-official%2Fplaywright-with-nodejs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcodestorm-official%2Fplaywright-with-nodejs/lists"}