{"id":25676964,"url":"https://github.com/jamro/nodepad","last_synced_at":"2026-06-11T22:31:20.822Z","repository":{"id":57120179,"uuid":"369280361","full_name":"jamro/nodepad","owner":"jamro","description":"NodePad is a simple tool to manage your NodeJs apps through REST API or UI","archived":false,"fork":false,"pushed_at":"2022-04-26T08:42:44.000Z","size":6854,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-08-20T02:56:33.819Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jamro.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-05-20T16:59:57.000Z","updated_at":"2021-10-27T17:33:02.000Z","dependencies_parsed_at":"2022-08-23T15:30:58.545Z","dependency_job_id":null,"html_url":"https://github.com/jamro/nodepad","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/jamro/nodepad","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jamro%2Fnodepad","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jamro%2Fnodepad/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jamro%2Fnodepad/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jamro%2Fnodepad/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jamro","download_url":"https://codeload.github.com/jamro/nodepad/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jamro%2Fnodepad/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34221150,"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-11T02:00:06.485Z","response_time":57,"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":[],"created_at":"2025-02-24T14:50:46.847Z","updated_at":"2026-06-11T22:31:20.800Z","avatar_url":"https://github.com/jamro.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![npm version](https://badge.fury.io/js/%40jamropl%2Fnodepad.svg)](https://badge.fury.io/js/%40jamropl%2Fnodepad)\n\n# NodePad\nNodePad is a simple tool to manage life cycle of your NodeJs apps. It allow to easily deploy, start/stop and monitor multiple apps via web interface or REST API.\n\n![Logo](./assets/logo/nodepad_logo_transparent.png)\n\nMain Features:\n- [Application Bundle Upload](#application-upload)\n- [Install NPM dependencies](#npm-application)\n- [Static files hosting](#static-application)\n- [Manage application life cycle](#web-user-interface)\n- [Routing](#routing)\n- [Preview logs](#web-user-interface)\n- [Authorization to NodePad API/UI](#authorization)\n- [Basic app monitoring](#web-user-interface)\n- [REST API](#rest-api)\n- [Web User Interface](#web-user-interface)\n- [Command Line Interface](#command-line-interface)\n\nUnder the hood, **NodePad** runs [PM2](https://www.npmjs.com/package/pm2) as a process manager.\n\n# Installation\n\n## Github\n\nClone Git Repository\n```bash\ngit clone https://github.com/jamro/nodepad.git\ncd nodepad\n```\n\nInstall all node packages\n```bash\nnpm install\n```\n\nLaunch **NodePad**\n```bash\nnpm start\n```\n\nOpen **NodePad** in your Browser:\n- User Interface: http://localhost:3333/\n- REST API: http://localhost:3333/api\n\n# Getting Started\n\n## Create the app\n\n- Open **NodePad** in your Browser (e.g. http://localhost:3333/). The port is configured in `config.js` under `dashboardPort`.\n- Click **Create New Application** and provide necessary details:\n-- App ID: **helloworld**\n-- App Port: **3335**\n-- Click **Create** to add your new app\n- **helloworld** app should be listed on the screen with status **off-line**\n- Launch the app by clicking **Play** button. The status should change to **on-line**\n- Go to your app URL: http://helloworld.localhost:3000/. The subdomain is the App ID provided before. The port is configured in `config.js` under `proxyPort`. It should return a default hello message from your app.\n\n## Deploy the app\n\n- Create app `index.js` source file anywhere on your disk:\n  ```javascript\n    #!/usr/bin/env node\n    const http = require('http');\n\n    const port = process?.env?.port;\n\n    console.log('Starting application helloworld (port: ' + port + ')...');\n\n    http.createServer(function (request, response) {\n      console.log(`Request ${request.method} ${request.url}`);\n      const content = '\u003ch1\u003eHello World\u003c/h1\u003e' + \n        '\u003cp\u003eThis is a message from your new app. Congrats! It seems to work :)\u003c/p\u003e';\n      response.end(content, 'utf-8');\n    }).listen(port);\n  ```\n- Compress `index.js` into `app.zip` file\n- Open **NodePad** in your Browser (e.g. http://localhost:3333/).\n- Click **Upload** next to **helloworld** app\n- Choose `app.zip` and upload it.\n- Go to your app URL: http://helloworld.localhost:3000/. It should return the new content\n\n# Main Features\n\n## REST API\nAll features are available through REST API. See http://localhost:3333/api for more details\n\n## Web User Interface\nThe UI is available at http://localhost:3333/ and it could be an alternative to the [REST API](#rest-api)\n\n![Applicatoin list user interface](./docs/nodepad_ui.png)\n\n## Application Upload\nYou can upload application bundles via [REST API](#rest-api) or [User Interface](#web-user-interface). The bundle is a ZIP file containing all application files. After upload, NodePad will extract all files from the bundle, and will launch the application. Several application bundles are supported:\n\n### Simple NodeJs Application\nThe bundle must contain `/index.js` file that will act as a runner. After upload, NodePad will launch execute it.\n\n### NPM Application\nThe bundle must contain `/index.js` and `package.json` file that will act as a runner. After upload, all dependencies will be installed by calling `npm install`. NodePad will launch the app by executing `/index.js`\n\n### Static Application\nThe bundle must contain `/index.html`. All files from the bindle will be served as static content by the server.\n\n\n## Routing\n**NodePad** acts as a reverse proxy and route traffic to applications basing on domain names. It follows a pattern of `[appId].[rootDomain]`. For example, **NodePad** will redirect all requests to `webapp.example.com` to an application with ID `webapp`. Routing work for both: HTTP requests and WebSockets.\n\n### Testing locally\nTo test routing locally, add proper entries to your `/etc/hosts`. For example\n```\n127.0.0.1 webapp.localhost\n```\n\nAfter that configuration, `webapp` application will be available at http://webapp.localhost:3000 (assuming that you run **NodePad** Proxy on default port 3000).\n\n**NodePad** offers app aliases, allowing accessing the same app via multiple domains (appIds). Let's assume that an app with ID `webapp` exists and it runs at port `8888`. Creating an alias with ID `webapp-v2` and assigned to port `8888` will result in having the app accessible at two URLs: http://webapp.localhost:3000 and http://webapp-v2.localhost:3000 (assuming that you run **NodePad** Proxy on default port 3000).\n\n### Running NodePad behind a proxy\nYou can run **NodePad** behind a proxy. To make routing work, add `X-Forwarded-For` headers to requests on the proxy level. \n\n#### Sample Nginx configuration\n\n```\nevents {\n  worker_connections  1024;\n}\n\nhttp {\n  server { \n    listen 81;\n    server_name ndoepad_dashboard;\n    \n    location / {\n      proxy_http_version 1.1;\n      proxy_pass http://localhost:3333;\n      proxy_set_header Upgrade $http_upgrade;\n      proxy_set_header Connection \"Upgrade\";\n      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n      proxy_set_header Host $http_host;\n      proxy_cache_bypass $http_upgrade;\n      proxy_redirect off;\n    }\n  }\n\n  server { \n    listen 80;\n    server_name ndoepad_proxy;\n    \n    location / {\n      proxy_http_version 1.1;\n      proxy_pass http://localhost:3000;\n      proxy_set_header Upgrade $http_upgrade;\n      proxy_set_header Connection \"Upgrade\";\n      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n      proxy_set_header Host $http_host;\n      proxy_cache_bypass $http_upgrade;\n      proxy_redirect off;\n    }\n  }\n}\n```\n\n### Sample HAProxy configuration\n\n```\nglobal\ndefaults\n\ttimeout client          30s\n\ttimeout server          30s\n\ttimeout connect         30s\n\nfrontend frontend_dashboard\n\tbind 0.0.0.0:81\n  mode http\n\tdefault_backend backend_dashboard\n\nfrontend frontend_proxy\n\tbind 0.0.0.0:80\n  mode http\n\tdefault_backend backend_proxy\n\nbackend backend_dashboard\n\tmode http\n  option forwardfor\n\tserver upstream nodepad:3333\n\nbackend backend_proxy\n\tmode http\n  option forwardfor\n\tserver upstream nodepad:3000\n```\n\n## Authorization\n**NodePad** supports Basic Auth. You can configure it in `./config.js` by uncommenting `auth` section:\n\n```javascript\nmodule.exports = {\n  // ...\n  auth: {\n    user: 'admin',\n    pass: 'mysecretpass'\n  }\n};\n```\n\nIt will secure both: the UI and the API.\n\nAdditional security measures could be applied on a firewall level since the dashboard of **NodePad** is available at a dedicated port. See `dashboardPort` parameter in `./config.js`.\n\n## Command Line Interface\nNodepad can be controlled over command line. The simplest way to start it is:\n```bash\n  ./bin/nodepad\n```\nThe configuration file can be altered by:\n```bash\n  ./bin/nodepad --config /path/to/your/config.js\n```\n\nIt is possible to run the dashboard and the proxy in separate processes by:\n```bash\n  ./bin/nodepad --module=dashboard\n  ./bin/nodepad --module=proxy\n```\n# Architecture\n![System Architecture](./docs/arch.png)\n\n# Troubleshooting\n\n## How to manually deploy an app?\nAll app files are kept in `/repo` by default The path can be changed in `config.js` by setting `appRepoPath` parameter. To manually change the app copy all files (including `index.js`) to `/repo/[AppId].[AppPort]/bin`. Remember to restart the application to apply changes.\n\n## How to manually the check status of running apps?\nRun `npm run pm2 -- ls`\n\n## How to manually stop an app?\nRun `npm run pm2 -- stop [AppId]`\n\n## How to manually read logs?\nAll logs are kept in `[appRepoPath]/[AppId].[AppPort]/log-[AppId].log` file. To get logs directly from PM2 call `npm run pm2 -- logs [AppId]`\n\n## PM2 is not responding. \nYou can kill PM2 daemon by running `npm run pm2 -- kill`. Please notice that it will stop all running apps.\n\n## How to manually run PM2 command? \nNPM scripts expose PM2 CLI: `npm run pm2 -- [arguments...]`\nFor example `npm run pm2 -- ls` is an equivalent of `pm2 ls`.\n\n## How to manually remove an app?\nRemove application directory located at `[appRepoPath]/[AppId].[AppPort]`. Keep in mind that the NodePad proxy may keep it cached after removal for some time.\n\n## How to manually create an alias?\nCreate an empty alias file `[appRepoPath]/[AppId].[AppPort].alias`. \n\n## How to manually remove an alias?\nDelete the alias file located at`[appRepoPath]/[AppId].[AppPort].alias`. Keep in mind that the NodePad proxy may keep it cached after removal for some time.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjamro%2Fnodepad","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjamro%2Fnodepad","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjamro%2Fnodepad/lists"}