{"id":23773485,"url":"https://github.com/beenotung/auto-cms","last_synced_at":"2025-09-05T18:31:16.180Z","repository":{"id":218468600,"uuid":"746259954","full_name":"beenotung/auto-cms","owner":"beenotung","description":"Auto turn any webpage into editable CMS without coding.","archived":false,"fork":false,"pushed_at":"2025-06-20T10:45:37.000Z","size":179,"stargazers_count":8,"open_issues_count":0,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-08-28T16:31:52.879Z","etag":null,"topics":["cli","cms","content","editor","html","low-code","nocode","server"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/auto-cms-server","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-2-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/beenotung.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2024-01-21T14:50:10.000Z","updated_at":"2025-06-20T10:45:40.000Z","dependencies_parsed_at":"2024-04-25T11:53:20.549Z","dependency_job_id":"c12906db-86ff-4de6-816f-f83b8e2e41b0","html_url":"https://github.com/beenotung/auto-cms","commit_stats":null,"previous_names":["beenotung/auto-cms"],"tags_count":61,"template":false,"template_full_name":null,"purl":"pkg:github/beenotung/auto-cms","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/beenotung%2Fauto-cms","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/beenotung%2Fauto-cms/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/beenotung%2Fauto-cms/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/beenotung%2Fauto-cms/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/beenotung","download_url":"https://codeload.github.com/beenotung/auto-cms/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/beenotung%2Fauto-cms/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":273799022,"owners_count":25170300,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-05T02:00:09.113Z","response_time":402,"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":["cli","cms","content","editor","html","low-code","nocode","server"],"created_at":"2025-01-01T05:40:45.197Z","updated_at":"2025-09-05T18:31:16.163Z","avatar_url":"https://github.com/beenotung.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# auto-cms\n\nAuto turn any webpage into editable CMS without coding.\n\n[![npm Package Version](https://img.shields.io/npm/v/auto-cms-server)](https://www.npmjs.com/package/auto-cms-server)\n\n## Features\n\n- [x] Click with `Ctrl` key or `Alt` key to show menu\n- [x] Edit from web UI\n  - text\n  - link\n  - image\n  - audio\n  - video\n- [x] media management\n  - [x] view\n  - [x] upload\n  - [x] delete\n  - [ ] see which pages are using the media\n  - [x] support image\n  - [x] support video / audio\n- [x] Reuse html template\n  - For common header, footer, e.t.c.\n- [ ] style editing\n  - text alignment\n  - text color\n  - font size\n  - font family\n- [x] SEO settings\n  - title\n  - description\n  - preview image\n- [x] Save changes to file\n- [x] Custom 404 layout (send `404.html` if exists, otherwise send `index.html`)\n- [x] Multi-language support\n  - convert 150+ languages with [node-EasyNMT](https://github.com/beenotung/node-EasyNMT)\n  - convert traditional Chinese / simplified Chinese with [繁化姬 API](https://docs.zhconvert.org)\n  - convert 104 languages with [open-google-translator](https://github.com/vidya-hub/open-google-translator)\n- [x] Contact form\n- [x] IFrame inlining\n- [ ] Auto scan 404\n- [x] Auto setup `.env` file\n- [x] Robust\n  - Correctly set Content-Type even when the filename of the HTML file is not ending with `.html`\n  - Support next.js image proxy url (e.g. \"/\\_next/image?url=xxx\u0026w=xx\u0026q=xx\")\n  - Auto backup edits\n  - View and restore from backups\n\n## Enhancement\n\n- [x] support editing element with multiple text nodes with br\n- [x] cleanup html\n  - remove duplicated script, style and css link caused by repeated runtime script injection\n  - deduplicate class names\n  - remove tracking scripts\n  - fix elements position\n    - move `title`, `meta`, `link` from `body` into `head`\n\n## Usage\n\nUsage with installation to lock the version:\n\n```bash\nnpm i -D auto-cms-server\nnpx auto-cms-server\n```\n\nUsage without installation:\n\n```bash\nnpx -y auto-cms-server\n```\n\n## API\n\n### Multi Language\n\nThe `lang` cookie is used to specify the client-preferred language. Possible values are: `en`, `zh_cn`, `zh_hk`, `ja`, `ko`, and `ar`.\n\nThe default value can be set in the environment variable `AUTO_CMS_DEFAULT_LANG`.\n\nBelow is example UI and code to show and set the language:\n\n```html\n\u003cform id=\"langForm\"\u003e\n  Language:\n  \u003clabel\u003e\n    \u003cinput type=\"radio\" name=\"lang\" value=\"en\" /\u003e\n    English\n  \u003c/label\u003e\n  \u003clabel\u003e\n    \u003cinput type=\"radio\" name=\"lang\" value=\"zh_cn\" /\u003e\n    簡體中文\n  \u003c/label\u003e\n  \u003clabel\u003e\n    \u003cinput type=\"radio\" name=\"lang\" value=\"zh_hk\" /\u003e\n    繁體中文\n  \u003c/label\u003e\n  \u003clabel\u003e\n    \u003cinput type=\"radio\" name=\"lang\" value=\"ja\" /\u003e\n    日本語\n  \u003c/label\u003e\n  \u003clabel\u003e\n    \u003cinput type=\"radio\" name=\"lang\" value=\"ko\" /\u003e\n    한국어\n  \u003c/label\u003e\n  \u003clabel\u003e\n    \u003cinput type=\"radio\" name=\"lang\" value=\"ar\" /\u003e\n    عربي\n  \u003c/label\u003e\n\u003c/form\u003e\n\u003cscript\u003e\n  {\n    let lang = Object.fromEntries(document.cookie.split(';').map(s=\u003es.trim().split('='))).lang\n    langForm.lang.value = lang\n    langForm.lang.forEach(input =\u003e {\n      input.addEventListener('change', event =\u003e {\n        if (input.checked) {\n          let maxAge = 365 * 24 * 60 * 60 // one year in seconds\n          document.cookie = `lang=${input.value}; path=/; max-age=${maxAge}`\n          location.reload()\n        }\n      })\n    })\n  }\n\u003c/script\u003e\n```\n\n### Submit Contact Form\n\n```\nMethod: POST\nPathname: /contact\nContent-Type: application/x-www-form-urlencoded or application/json\nAccept: text/html or application/json\nBody Fields:\n- name\n- email\n- tel\n- company_name\n- business_nature\n- remark\n- extra\n```\n\nAll body fields are optional.\n\nIf you submit additional fields in the request body, they will be stored as JSON in the `extra` field.\n\nIf the `Accept` is `application/json`, the response will be a json object with optional `error` string; otherwise the response will be a html page.\n\nThe response file can be configured in the env variable `SUBMIT_CONTACT_RESULT_PAGE`. If it is not specified, or specified as `default`, a simple html page will be response as below:\n\n```html\n\u003c!DOCTYPE html\u003e\n\u003chtml lang=\"en\"\u003e\n  \u003chead\u003e\n    \u003cmeta charset=\"UTF-8\" /\u003e\n    \u003cmeta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" /\u003e\n    \u003ctitle\u003eSubmitted\u003c/title\u003e\n  \u003c/head\u003e\n  \u003cbody\u003e\n    \u003cp\u003eYour submission has been received.\u003c/p\u003e\n    ${error ? `\n    \u003cpre\u003e\u003ccode\u003e${escapeHTML(error)}\u003c/code\u003e\u003c/pre\u003e\n    ` : ''}\n    \u003cp\u003eBack to \u003ca href=\"/\"\u003ehome page\u003c/a\u003e.\u003c/p\u003e\n  \u003c/body\u003e\n\u003c/html\u003e\n```\n\nIf you want to implement custom form submission experience, you can do that with AJAX like below example:\n\n```html\n\u003cform method=\"POST\" action=\"/contact\" onsubmit=\"submitContact(event)\"\u003e\n  \u003ch1\u003eContact Form\u003c/h1\u003e\n  \u003cdiv class=\"contact-form--field\"\u003e\n    \u003clabel\u003e\n      Nickname: \u003cinput type=\"text\" name=\"name\" autocomplete=\"nickname\" /\u003e\n    \u003c/label\u003e\n  \u003c/div\u003e\n  \u003cdiv class=\"contact-form--field\"\u003e\n    \u003clabel\u003e\n      Email: \u003cinput type=\"email\" name=\"email\" autocomplete=\"email\" /\u003e\n    \u003c/label\u003e\n  \u003c/div\u003e\n  \u003cdiv\u003e\n    \u003cinput type=\"submit\" value=\"Submit\" /\u003e\n  \u003c/div\u003e\n  \u003cdiv class=\"contact-form--submit-result\"\u003e\u003c/div\u003e\n\u003c/form\u003e\n\u003cscript\u003e\n  async function submitContact(event) {\n    let form = event.target\n    let result = form.querySelector('.contact-form--submit-result')\n    function showResult(text) {\n      result.textContent = text\n    }\n    try {\n      let formData = new FormData(form)\n      let params = new URLSearchParams(formData)\n      let body = params.toString()\n      event.preventDefault()\n      let res = await fetch('/contact', {\n        method: 'POST',\n        headers: {\n          'Content-Type': 'application/x-www-form-urlencoded',\n          'Accept': 'application/json',\n        },\n        body,\n      })\n      let json = await res.json()\n      if (json.error) throw json.error\n      showResult('Thank you. Your submission is received.')\n    } catch (error) {\n      showResult(String(error))\n    }\n  }\n\u003c/script\u003e\n```\n\n## License\n\nThis project is licensed with [BSD-2-Clause](./LICENSE)\n\nThis is free, libre, and open-source software. It comes down to four essential freedoms [[ref]](https://seirdy.one/2021/01/27/whatsapp-and-the-domestication-of-users.html#fnref:2):\n\n- The freedom to run the program as you wish, for any purpose\n- The freedom to study how the program works, and change it so it does your computing as you wish\n- The freedom to redistribute copies so you can help others\n- The freedom to distribute copies of your modified versions to others\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbeenotung%2Fauto-cms","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbeenotung%2Fauto-cms","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbeenotung%2Fauto-cms/lists"}