{"id":13833379,"url":"https://github.com/contentacms/contentajs","last_synced_at":"2025-10-20T09:22:01.028Z","repository":{"id":57103793,"uuid":"132868789","full_name":"contentacms/contentajs","owner":"contentacms","description":"A nodejs server that proxies to Contenta CMS and holds custom code.","archived":false,"fork":false,"pushed_at":"2020-03-22T22:22:46.000Z","size":1342,"stargazers_count":102,"open_issues_count":8,"forks_count":23,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-06-16T08:07:26.622Z","etag":null,"topics":["application","cms","contenta","express","performance","proxy"],"latest_commit_sha":null,"homepage":null,"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/contentacms.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":"2018-05-10T08:04:55.000Z","updated_at":"2023-10-05T03:43:41.000Z","dependencies_parsed_at":"2022-08-20T17:10:41.848Z","dependency_job_id":null,"html_url":"https://github.com/contentacms/contentajs","commit_stats":null,"previous_names":[],"tags_count":52,"template":false,"template_full_name":null,"purl":"pkg:github/contentacms/contentajs","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/contentacms%2Fcontentajs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/contentacms%2Fcontentajs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/contentacms%2Fcontentajs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/contentacms%2Fcontentajs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/contentacms","download_url":"https://codeload.github.com/contentacms/contentajs/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/contentacms%2Fcontentajs/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":264505231,"owners_count":23618906,"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","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":["application","cms","contenta","express","performance","proxy"],"created_at":"2024-08-04T12:00:30.395Z","updated_at":"2025-10-20T09:21:55.992Z","avatar_url":"https://github.com/contentacms.png","language":"JavaScript","funding_links":[],"categories":["Decoupled Frontend"],"sub_categories":["Frameworks"],"readme":"\u003c!--\n  This file was generated by emdaer\n\n  Its template can be found at .emdaer/README.emdaer.md\n--\u003e\n\n\u003c!--\n  emdaerHash:6a0ac3213af886b61b0a58a3f2e822bd\n--\u003e\n\n\u003ch1 id=\"contentajs-img-align-right-src-logo-svg-alt-contenta-logo-title-contenta-logo-width-100-\"\u003eContentaJS \u003cimg align=\"right\" src=\"./logo.svg\" alt=\"Contenta logo\" title=\"Contenta logo\" width=\"100\"\u003e\u003c/h1\u003e\n\u003cp\u003eContentaJS is a project that integrates with Contenta CMS to provide\nan high performing headless CMS. It also provides a nodejs application\nwhere to host your Server Side Rendering and custom code integrations.\u003c/p\u003e\n\u003cp align=\"center\"\u003e\u003cimg src=\"./.emdaer/docs/assets/contentacms-node.png\" alt=\"Contenta Stack Architecture\"\u003e\u003c/p\u003e\n\n\u003cp\u003e\u003cstrong\u003eIMPORTANT:\u003c/strong\u003e this project is meant to be a starting kit for the node\nintegration of your application based on Contenta CMS. We \u003cstrong\u003edo not\u003c/strong\u003e provide\nupgrade paths or backwards compatibility. The model for this is \u003cem\u003eFork \u0026amp; Go\u003c/em\u003e.\u003c/p\u003e\n\u003c!-- toc --\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"#videos\"\u003eVideos\u003c/a\u003e\u003cul\u003e\n\u003cli\u003e\u003ca href=\"#contenta-js-introduction\"\u003eContenta JS: Introduction\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#tutorial-install-contenta-cms--contenta-js\"\u003eTutorial: Install Contenta CMS + Contenta JS\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#why\"\u003eWhy?\u003c/a\u003e\u003cul\u003e\n\u003cli\u003e\u003ca href=\"#microservices\"\u003eMicroservices\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#server-side-rendering\"\u003eServer-Side Rendering\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#performance\"\u003ePerformance\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#other\"\u003eOther\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#features\"\u003eFeatures\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#installation\"\u003eInstallation\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#internal-development-notes\"\u003eInternal Development Notes\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#contributors\"\u003eContributors\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#license\"\u003eLicense\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- tocstop --\u003e\n\u003cp\u003e\u003ca href=\"https://travis-ci.org/contentacms/contentajs/\"\u003e\u003cimg src=\"https://img.shields.io/travis/contentacms/contentajs.svg?style=flat-square\" alt=\"Travis\"\u003e\u003c/a\u003e \u003ca href=\"https://coveralls.io/github/contentacms/contentajs/\"\u003e\u003cimg src=\"https://img.shields.io/coveralls/github/contentacms/contentajs.svg?style=flat-square\" alt=\"Coverage\"\u003e\u003c/a\u003e \u003ca href=\"https://david-dm.org/contentacms/contentajs\"\u003e\u003cimg src=\"https://img.shields.io/david/contentacms/contentajs.svg?style=flat-square\" alt=\"David Dependency Management\"\u003e\u003c/a\u003e \u003ca href=\"https://github.com/contentacms/contentajs\"\u003e\u003cimg src=\"https://img.shields.io/github/last-commit/contentacms/contentajs.svg?style=flat-square\" alt=\"Last Commit\"\u003e\u003c/a\u003e \u003ca href=\"http://npmjs.com/package/@contentacms/contentajs\"\u003e\u003cimg src=\"https://img.shields.io/node/v/@contentacms/contentajs.svg?style=flat-square\" alt=\"Node\"\u003e\u003c/a\u003e \u003ca href=\"https://github.com/emdaer/emdaer\"\u003e\u003cimg src=\"https://img.shields.io/badge/📓-documented%20with%20emdaer-F06632.svg?style=flat-square\" alt=\"Documented with emdaer\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003ch2 id=\"videos\"\u003eVideos\u003c/h2\u003e\n\u003ch3 id=\"contenta-js-introduction\"\u003eContenta JS: Introduction\u003c/h3\u003e\n\u003cp align=\"center\"\u003e\n\u003ca href=\"https://www.youtube.com/watch?v=6bdbqo2tETg\"\u003e\u003cimg src=\"https://img.youtube.com/vi/6bdbqo2tETg/0.jpg\" alt=\"Contenta JS video\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n\u003ch3 id=\"tutorial-install-contenta-cms-contenta-js\"\u003eTutorial: Install Contenta CMS + Contenta JS\u003c/h3\u003e\n\u003cp align=\"center\"\u003e\n\u003ca href=\"https://www.youtube.com/watch?v=KGhA61WeTuw\"\u003e\u003cimg src=\"https://img.youtube.com/vi/KGhA61WeTuw/0.jpg\" alt=\"Contenta JS video\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n\u003ch2 id=\"why-\"\u003eWhy?\u003c/h2\u003e\n\u003cp\u003e\u003cstrong\u003eContenta CMS\u003c/strong\u003e (aka \u003cem\u003ethe Drupal part\u003c/em\u003e) is designed to serve your project’s\ncontent. ContentaJS (aka \u003cem\u003ethe node.js part\u003c/em\u003e) is designed to serve the requests\nto your client side applications. Some of those requests will end up requesting\ndata from Contenta CMS, others won’t.\u003c/p\u003e\n\u003cp\u003eYou may need \u003cstrong\u003eContentaJS\u003c/strong\u003e because for many reasons \u003cstrong\u003eyou will end up needing a\nnode.js server for your project anyways\u003c/strong\u003e. You may as well use an opinionated\nand optimized starter kit that will solve many of your needs without effort.\u003c/p\u003e\n\u003ch3 id=\"microservices\"\u003eMicroservices\u003c/h3\u003e\n\u003cp\u003eIf your API needs to aggregate data for use on the front-end from other services\nyou \u003cstrong\u003eshould not\u003c/strong\u003e use PHP for that. That is because, in practice, all I/O in\nDrupal is blocking and the performance of these tasks is usually very poor.\u003c/p\u003e\n\u003cp\u003eExamples of this are:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eShowing weather data from a 3rd party API.\u003c/li\u003e\n\u003cli\u003eIf you need to make requests to an analytics tool.\u003c/li\u003e\n\u003cli\u003eIf you need to run a request through an anti-fraud service before accessing the content.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eIn these situations you will want to treat \u003cstrong\u003eContenta CMS\u003c/strong\u003e just as any other\nmicroservice. Then you will need a server, like this one written in node.js, to\norchestrate the different microservices.\u003c/p\u003e\n\u003ch3 id=\"server-side-rendering\"\u003eServer-Side Rendering\u003c/h3\u003e\n\u003cp\u003eChances are that you are building a website as part of your digital project. In\nmost cases you will be using a front-end framework like React, Vue, Angular,\netc. All of those frameworks recommend using server-side rendering\n\u003ca href=\"https://ssr.vuejs.org/#why-ssr\"\u003efor many reasons\u003c/a\u003e. In order to implement\nserver-side rendering you will need a node.js server.\u003c/p\u003e\n\u003cp\u003eYou can use this node.js server (aka \u003cem\u003eContentaJS\u003c/em\u003e) to implement server-side\nrendering on.\u003c/p\u003e\n\u003ch3 id=\"performance\"\u003ePerformance\u003c/h3\u003e\n\u003cp\u003eYour LAMP stack (or alternative) runs your Contenta CMS installation. We all\nknow how flexible and powerful Drupal is. But at the same time it is not great\nfrom a performance point of view. In fact it can rapidly become your bottleneck.\u003c/p\u003e\n\u003cp\u003eWith ContentaJS you can reduce the load in your LAMP stack. This is because you\ndon’t even need to hit this stack to access cached responses. ContentaJS will\nfetch the data from cache, and will only check with Drupal when there is no\ncache. That reduces greatly the amount of requests Apache needs to process. This\nreduces the load on Drupal, hence improving performance overall.\u003c/p\u003e\n\u003cp\u003eContentaJS integrates transparently with Contenta CMS and can analyze requests\nthat will fail in Drupal. When that happens the request never hits Drupal thus\nreducing the load there. Examples of this are: a request to a non-existing\nresource, a request that contains a payload that doesn’t validate against the\nschema of the resource, etc.\u003c/p\u003e\n\u003ch3 id=\"other\"\u003eOther\u003c/h3\u003e\n\u003cp\u003eOther server tasks like executing actions on cron, or sending emails, etc. can\nbe done in this node.js server (and/or the machine running it) instead of on\nthe LAMP stack.\u003c/p\u003e\n\u003ch2 id=\"features\"\u003eFeatures\u003c/h2\u003e\n\u003cp\u003e\u003cem\u003eThis section is still under development.\u003c/em\u003e\u003c/p\u003e\n\u003cp\u003eThe main features of this project cover:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eAutomatic integration with the API exposed by your Contenta CMS install.\nJust provide the URL of the site and everything is taken care of for you.\u003cul\u003e\n\u003cli\u003eJSON API integration.\u003c/li\u003e\n\u003cli\u003eJSON RPC integration.\u003c/li\u003e\n\u003cli\u003eSubrequests integration.\u003c/li\u003e\n\u003cli\u003eOpen API integration.\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eMulti-threaded nodejs server that takes advantage of all the cores of the\nserver’s CPU.\u003c/li\u003e\n\u003cli\u003eA Subrequests server for request aggregation. Learn more about \u003ca href=\"./docs/subrequests.md\"\u003esubrequests\u003c/a\u003e.\u003c/li\u003e\n\u003cli\u003eA \u003ca href=\"http://redis.io\"\u003eRedis\u003c/a\u003e integration via \u003ca href=\"https://github.com/contentacms/contentajsRedis\"\u003e@contentacms/redis\u003c/a\u003e.\u003c/li\u003e\n\u003cli\u003eType safe development environment using \u003ca href=\"http://flow.org\"\u003eFlow\u003c/a\u003e.\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/contentacms/contentajs/blob/master/config/default.yml#L66-L85\"\u003eConfigurable CORS\u003c/a\u003e.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"installation\"\u003eInstallation\u003c/h2\u003e\n\u003cp\u003eIn order to install ContentaJS you will need to meet the following\n\u003cstrong\u003erequirements\u003c/strong\u003e:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ccode\u003enodejs\u003c/code\u003e ^8.11.1 or higher. This corresponds to \u003ccode\u003elts/carbon\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003eA working installation of \u003ca href=\"https://github.com/contentacms/contenta_jsonapi\"\u003eContenta CMS\u003c/a\u003e.\u003c/li\u003e\n\u003cli\u003eA Redis server (optional). Use the\n\u003ca href=\"https://github.com/contentacms/contentajsRedis\"\u003e@contentacms/redis\u003c/a\u003e module\nto leverage the Redis cache back-end.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eSee the \u003ca href=\"./docs/install.md\"\u003einstallation instructions\u003c/a\u003e.\u003c/p\u003e\n\u003ch2 id=\"internal-development-notes\"\u003eInternal Development Notes\u003c/h2\u003e\n\u003cp\u003e\u003cem\u003eThis is a dumping ground of notes. This section will disappear eventually, it’s\njust meant to save ideas for documentation to process some other time.\u003c/em\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eIntroduce the ability to timeout requests.\u003c/li\u003e\n\u003cli\u003eCreate a separate package using passport to integrate with Simple OAuth.\u003c/li\u003e\n\u003cli\u003eIf all subrequests are to the CMS forward the blueprint to Drupal’s subrequests.\u003c/li\u003e\n\u003cli\u003eCompute the appropriate cache-control header from subquests responses.\u003c/li\u003e\n\u003cli\u003eMake sure to mention that the /healthckeck is for auto-scaling policies.\u003c/li\u003e\n\u003cli\u003eCreate a @contentacms/redisShare submodule for a shared Redis server between\nDrupal and node.\u003c/li\u003e\n\u003cli\u003eDocument that the proxied requests are not cached because they are considered\nend responses. The appropriate caching should be in the edge cache layer.\u003c/li\u003e\n\u003cli\u003eMake Cache-Control header overrides configurable.\u003c/li\u003e\n\u003cli\u003eCheck feature conflict between cors.maxAge and OPTIONS cache control header.\u003c/li\u003e\n\u003cli\u003eDocument better the JSON RPC support.\u003c/li\u003e\n\u003cli\u003eAdd documentation about the cache controls\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"contributors\"\u003eContributors\u003c/h2\u003e\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eContributors\u003c/strong\u003e\u003c/summary\u003e\u003cbr\u003e\n\u003ca title=\"Engineer and programmer focused on online applications.\" href=\"https://github.com/e0ipso\"\u003e\n  \u003cimg align=\"left\" src=\"https://avatars0.githubusercontent.com/u/1140906?s=24\"\u003e\n\u003c/a\u003e\n\u003cstrong\u003eMateu Aguiló Bosch\u003c/strong\u003e\n\u003cbr\u003e\u003cbr\u003e\n\u003c/details\u003e\n\n\u003ch2 id=\"license\"\u003eLicense\u003c/h2\u003e\n\u003cp\u003e@contentacms/contentajs is \u003ca href=\"./LICENSE\"\u003eMIT licensed\u003c/a\u003e.\u003c/p\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcontentacms%2Fcontentajs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcontentacms%2Fcontentajs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcontentacms%2Fcontentajs/lists"}