{"id":15164615,"url":"https://github.com/lumen-cms/lumen-cms","last_synced_at":"2025-09-30T20:31:25.080Z","repository":{"id":39801151,"uuid":"127282514","full_name":"lumen-cms/lumen-cms","owner":"lumen-cms","description":"GraphQL API-First CMS based on NodeJS and Vue 2, Nuxt and Vuetify","archived":true,"fork":false,"pushed_at":"2022-06-25T02:49:54.000Z","size":3391,"stargazers_count":77,"open_issues_count":10,"forks_count":7,"subscribers_count":12,"default_branch":"master","last_synced_at":"2025-01-16T06:59:17.900Z","etag":null,"topics":["cms","cms-framework","graphcool","graphcool-cli","graphql","nodejs","nuxt","nuxt-module","nuxtjs","vue2","vuejs","vuetify","vuetifyjs"],"latest_commit_sha":null,"homepage":"","language":"Vue","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/lumen-cms.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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-03-29T11:33:48.000Z","updated_at":"2024-03-12T21:14:26.000Z","dependencies_parsed_at":"2022-09-13T02:32:17.832Z","dependency_job_id":null,"html_url":"https://github.com/lumen-cms/lumen-cms","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lumen-cms%2Flumen-cms","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lumen-cms%2Flumen-cms/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lumen-cms%2Flumen-cms/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lumen-cms%2Flumen-cms/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lumen-cms","download_url":"https://codeload.github.com/lumen-cms/lumen-cms/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":234774934,"owners_count":18884523,"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":["cms","cms-framework","graphcool","graphcool-cli","graphql","nodejs","nuxt","nuxt-module","nuxtjs","vue2","vuejs","vuetify","vuetifyjs"],"created_at":"2024-09-27T03:41:51.133Z","updated_at":"2025-09-30T20:31:19.707Z","avatar_url":"https://github.com/lumen-cms.png","language":"Vue","funding_links":[],"categories":["Vue"],"sub_categories":[],"readme":"# nuxtjs/lumen-cms\n[![npm (scoped with tag)](https://img.shields.io/npm/v/lumen-cms/latest.svg?style=flat-square)](https://npmjs.com/package/lumen-cms)\n[![npm](https://img.shields.io/npm/dt/lumen-cms.svg?style=flat-square)](https://npmjs.com/package/lumen-cms)\n[![Codecov](https://img.shields.io/codecov/c/github/lumen-cms/lumen-cms.svg?style=flat-square)](https://codecov.io/gh/lumen-cms/lumen-cms)\n[![Dependencies](https://david-dm.org/lumen-cms/lumen-cms.svg?style=flat-square)](https://david-dm.org/lumen-cms/lumen-cms)\n[![js-standard-style](https://img.shields.io/badge/code_style-standard-brightgreen.svg?style=flat-square)](http://standardjs.com)\n\n\u003e Module for a cms based on Nuxt and GraphQl\n\n[📖 **Release Notes**](./CHANGELOG.md)\n\n# Lumen CMS \n#### NodeJS | Vue 2.x | NuxtJs | Vuetify | GraphQl - graph.cool\n\n## Attention!\nDue to the shutdown of Graphcool BaaS service this project sadly is coming to an end. I started with a different approach - feel free to contact me if you are interested in checking it out.\n\n## Motivation\nThis project aims to combine very popular open-source projects and a solid managed backend service of graph.cool. It is API-Driven and extendable with graphql schema definition. Due to the nature of NuxtJs and the powerful modularization concept it extends your NuxtJs project with a fully-featured CMS. As a component framework Vuetify is included and brings Google Material Design specification out of the box. It offers best practices for SEO combined with a lot of performance optimization for the website render process.\n\n#### Features\n* Content management system\n* Google Analytics integration\n* Sitemap generator\n* 301 Redirects\n* SEO optimized \n* SSR-rendered SPA feel of static website\n* Imageproxy (CDN + scale/crop)\n* Lazy-loading / Intersection Observer\n* Responsive images \n* Fontloader\n* In-Page-Editing\n* Multi-Language\n* Multi-Domain\n* Configurable\n* 95%+ on GooglePageSpeed\n\n#### Technology stack\n* NodeJS (https://nodejs.org)\n* Vue 2.x (https://vuejs.org/)\n* NuxtJs (https://nuxtjs.org/)\n* Vuetify (https://vuetifyjs.com)\n* GraphQL managed backend by graph.cool (https://graph.cool/)\n* Apollo (https://www.apollographql.com/client/, https://github.com/Akryum/vue-apollo)\n* Vue-i18n (https://kazupon.github.io/vue-i18n/en/)\n* Intersection-Observer (https://github.com/Akryum/vue-observe-visibility)\n* Fast deplyoment with zeit.co/now (https://zeit.co/now)\n\n## Requirement\n* NodeJS v \u003e=8 (check out https://nuxtjs.org dependencies)\n* NPM/Yarn\n* GraphQL endpoint (https://graph.cool)\nYou need a graph.cool endpoint and backend. Head over to [lumen-graphcool](https://github.com/lumen-cms/lumen-graphcool) to install and deploy your backend.\n\n## Installation \n### New project\nMake use of the vue-cli [starter-template](https://github.com/lumen-cms/starter-template)\n```bash\n$ vue init lumen-cms/starter-template my-project  \n$ cd my-project                     \n# install dependencies\n$ npm install # Or yarn install\n# open localhost:3000/admin to proceed with login\n```\n\n### Existing project\n- Add `nuxtjs/lumen-cms` dependency using yarn or npm to your project\n- Add `lumen-cms` to `modules` section of `nuxt.config.js`\n```bash\nnpm i lumen-cms --save\n```\n\n```js\n// nuxt.config.js\nexport default = {\n  // check out https://github.com/lumen-cms/lumen-graphcool to set it up\n  env:{\n    GRAPHQL_PROJECT_ID: '[Project ID]',\n    GRAPHQL_SUBSCRIPTION: '[SUBSCRIPTION]'\n  },\n  modules: [\n    'lumen-cms' // add lumen-cms module\n  ],\n  // customize settings\n  'lumen-cms':{\n    // here comes your configuration\n  }\n```\n## First Start\n* Visit http://localhost:3000/admin and register a user\n* Visit your graphcool backend and add `Moderator/Admin` role to the user\n* Now you can log in and start a very basic installation (http://localhost:3000/installation)\n  * your installation respects the [languages](#install-routepath-admininstall) array and create for each locale one default root page\n  * keep in mind: every language starts with the \"/[locale]\" slug\n  * you can configure canonical tags or any custom behaviour for multi-language websites\n=\u003e After successful installation will be redirected to the root of your website and you can start adding content\n\n## Pages\nLumen CMS provides admin interfaces and render entry points for your top-level article/page schema. Below is the list and routePath of all pre-configured routes. Make sure that these paths does not collide with any of your NuxtJs pages setup. All of the pages are accessible through the [Admin-Bar](#admin-bar) \n\n### Root - Index.vue (routePath \"/any/path\")\nCatches all requests and renders the schema [`Article`](#article---view) based on the slug. The slug can be any slug as\n* /simple-slug\n* /directory/slug/deep/nested\n* On Error / Not found\n  * try to find a 301 =\u003e redirect\n  * render 404 if no article found\n  * render 500 if any error occurs\nImportant: make sure you don't provide any index.vue file inside your `pages` folder otherwise the CMS won't be able to render the content.\n\n### Admin (routePath: '/admin')\nLogin/Sign Up for the website administration. After successful login you get forwarded to the root of your website. In case of sign up a new user: you have to enable a permission role (Admin|Moderator) to the user in your graph.cool console interface. \n\n### Install (routePath: '/admin/install')\nCreates the root page/entry point for each locale you provide in your configuration:\n```js\n'lumen-cms':{\n  cms:{\n    languages:['en','de','it','fr'] // =\u003e install would create all 4 articles with a basic content element as a starter \n  }\n}\n```\n\n### Article-Admin (routePath: '/admin/article-admin'\nDatatable lists all articles and you can view/edit it. The Footer shows a language switch to change the locale for your listing.\n\n### Article-Edit (routePath: '/admin/article-edit/:id?')\nCreates/updates the article schema. You can either click on the edit inside of the `Admin-Bar` or inside of the `Article Admin` to reach the edit page.\n\n### Page-Templates (routePath: '/admin/page-templates')\nOverview over all page templates. Page templates is `vue-rendered` content you can specify inside of footer/header/sidebars/toolbars. Basically it holds generic content which should be displayed in static parts of the layout.\n\n### Redirects (routePath: '/admin/redirects')\nDatatable lists all redirects in case you moved pages/paths to a different location\n\n### Article/Blog list (routePath: '/blog|articles')\nConfigurable alias path to render an article list. \n```js\n'lumen-cms':{\n  cms:{\n    routes: {\n      // map locale to each routes.path\n      listMapLocale: {\n        articles: 'en',\n        blog: 'de'\n      },\n      // all available path alias for the article list\n      list: ['articles', 'blog']\n    }\n  }\n}\n```\n\n## Admin-Bar\nOn logged in you will see on the bottom left corner a floating speed-dial button this action menu buttons:\n* Logout\n* Media Gallery (only visible if content edit mode is ON)\n* Redirects\n* Blog admin list\n* Page templates\n* Content-Edit-Mode toggle\n* Add new article\n* Edit article\n#### Use Admin-Bar\nYou can include the `LcAdminBar` into your own template. You can enable `add` or `edit` action and the toggle for `content-edit`:\n```vue\n\u003clc-admin-bar v-if=\"$store.getters.canEdit\"\n              :edit-route=\"{name: 'articleEdit', params: {id: $store.state.lc.pageProps.articleId}}\"\n              :add-route=\"{name:'articleEdit'}\"\n              :content-edit-toggle=\"true\"/\u003e\n```\n#### Customize Admin-Bar\nAdd links into the Admin-Bar panel\n```js\n'lumen-cms':{\n  // overwrite the entire widget\n  component:{\n    edit:{\n      LcAdminBar: '~/component/yourCustomAdminBar.vue' \n    }\n  },\n  cms:{\n    // add some link(s) to the admin bar\n    adminBarLinks:[{\n      title: 'Some custom page',\n      to: {name: 'customPageRouteName'},\n      color: 'yellow darken-2', // any color variant\n      icon: 'code' //material icon name\n    }]\n  }\n}\n```\n\n## Configuration\nYou can customize your website bundle in several ways: \n* `lumen-cms` configuration options from the nuxt.config.js file\n* `Webpack alias` to provide a custom file and replace the default\n\n### Options\n\n#### [disableCSS] - Boolean (default: false)\nDisable the CSS import and manualy add it with stylus\n```js\n 'lumen-cms':{\n    disableCSS: true \n } \n css: [\n   {src: '~assets/style/app.styl', lang: 'styl'}\n ]\n```\n```stylus\n@import '~lumen-cms/lib/templates/assets/style/vuetify-imports.styl'\n$themeprimary = #ff6f00\n$themeaccent = #ffc400\n$themesecondary = $grey.darken-3\n$themeinfo = $light-blue.darken-1\n$themewarning = $orange.darken-1\n$themeerror = $red.darken-1\n$themesuccess = $light-green.darken-1\n@import '~lumen-cms/lib/templates/assets/style/imports.styl'\n```\n\n#### [fonts] - Object (default: roboto)\nModify fonts of Google to get loading with fontloader API\n```js\nfonts:{montserrat: 'Montserrat:thin,extra-light,light,100,200,300,400,500,600,700,800'}\n```\n```css\nh1, h2, h3 {\n  font-family: 'Montserrat'\n}\n```\n\n#### [components] - Object (default: empty)\n\nOverwrite build-in components by provide a custom component path. All components are prefixed with `Lc`ComponentName. Components are loaded as asynchronous and are devided in four sections: `core|layout|view|edit`. \n* Find all available components [here](/lib/templates/plugins/components) \n* Further custumization options follow overwrite [section](README.md#overwrite)\n\n#### [pages] - Object (default: empty)\n\nOverwrite built-in pages by provide a custom page path. Following pages are provided. Provide a `pages` object with the exact name and custom path to overwrite the default:\n```js\npages:{\n  admin: resolve(__dirname, './templates/pages/admin.vue'),\n  install: resolve(__dirname, './templates/pages/install.vue'),\n  articleAdmin: resolve(__dirname, './templates/pages/articleAdmin.vue'),\n  articleEdit: resolve(__dirname, './templates/pages/articleEdit.vue'),\n  pageTemplates: resolve(__dirname, './templates/pages/pageTemplates.vue'),\n  redirects: resolve(__dirname, './templates/pages/redirects.vue',\n  articleList: resolve(__dirname, './templates/pages/articleList.vue'),\n  index: resolve(__dirname, './templates/pages/index.vue')\n}\n\n// in case you want to overwrite articleList page\npages:{\n  articleList: '~/pages/customArticleList.vue'\n}\n```\n\n#### [cms] - Object \n\nThe `cms` config object is getting injected into the context of your app (https://nuxtjs.org/guide/plugins#inject-in-root-amp-context). \n* `Vuex` - actions as `this.app.$cms`\n* Vue Components as `this.$cms`\n* Check out all [options](lib/defaults.js)\n```js\ncms:{\n  pageToolbarExtension: false,\n  Head:{\n    site_name: 'Your domain',\n  }\n}\n```\n\n## Data Schema\nThe backend is configured to fit most website usecases. The main top-level schema is called Article, its the main schema for all pages/articles. The difference between a page and article is marginal - you can change it with a switch and its made to differenciate inside of the content list widget. \n### Article - [View](https://github.com/lumen-cms/lumen-graphcool/blob/master/types.graphql#L1)\n* holds the top level schema\n* can hold many content elements\n* Taxonomy with `ArticleCategory`\n* Add a media image to show a picture in `ListWidget`-lists\n* `languageKey` is important to represent the locale of the content\n* `slug` has to be unique\n  * locale is always the root of a landing page (`en` for english, `de` for german)\n  * you can pass in directives `parent/my/subpage` \n  * every string will get slugified \n  * no leading slashes - no `.html` endings needed (they will get redirected automatically)\n  * there is no locale directive as `/en/any-page` | `/de/german-page` needed due to uniqness of the slug\n\n### ArticleCategory - [View](https://github.com/lumen-cms/lumen-graphcool/blob/master/types.graphql#L26)\n* categorization/taxonomy/tagging for each article\n\n### Author - [View](https://github.com/lumen-cms/lumen-graphcool/blob/master/types.graphql#L38)\n* basic author schema\n\n\n### Content - [View](https://github.com/lumen-cms/lumen-graphcool/blob/master/types.graphql#L47)\n* holds the content element schema for any content element\n* extandable through \n  - properties JSON\n  - styles JSON\n\n### File - [View](https://github.com/lumen-cms/lumen-graphcool/blob/master/types.graphql#L71)\n* graph.cool internal file schema\n\n### FileReference - [View](https://github.com/lumen-cms/lumen-graphcool/blob/master/types.graphql#L89)\n* holds the reference to each file via media browser\n\n### FileTag - [View](https://github.com/lumen-cms/lumen-graphcool/blob/master/types.graphql#L110)\n* categorization/taxonomy/tagging for each file\n\n### Media - [View](https://github.com/lumen-cms/lumen-graphcool/blob/master/types.graphql#L116)\n* media image for preview images of articles\n\n### PageTemplate - [View](https://github.com/lumen-cms/lumen-graphcool/blob/master/types.graphql#L132)\n* holds generic content for different and global layout positions\n  - toolbars\n  - navigation drawer\n  - footer \n  - configurable\n\n### UrlAlias (301 redirects) - [View](https://github.com/lumen-cms/lumen-graphcool/blob/master/types.graphql#L132)\n* 301 in case of renamed paths/slugs\n\n### User - [View](https://github.com/lumen-cms/lumen-graphcool/blob/master/types.graphql#L142)\n* graph.cool internal user schema for authentication\n\n## Content Elements\nAll content elments can be added/edited for each article. Lumen CMS ships 5 content elements while each of them is \ncustomizable through stylesheets and properties. The most common element is `LcTextImage` which has many configuration option and fit many usecases. You can overwrite either the content element with providing a custom path or create custom elements and add them to your project [read more](README.md#customize-content-elements).\n\n### Text with image (`LcTextImage`)\n* Header (h1 - h6)\n* Text (enabled richt text editor from QuillJs)\n* Image(s) as gallery or single\n* Parallax/Jumbotron/Fixed-Background effect\n* Flexible arrangement\n* Highly customizable through styles\n* \"Component-Pre-Set\" as a collection of class names can be defined or added to the [defaults](lib/templates/util/contentElementStylePresets.js)\n\n### Divider (`LcDivider`)\n* Recognizes google material icons\n* Different sizing\n* Colorization\n* Border widths\n\n### Layout (`LcLayout`)\n* Tabs\n* Columns\n  - Parralax/Jumbotron/Fixed-Background images\n* Slider\n* Expansion-panel\n =\u003e holds as many content elmements inside each row/column\n\n### List Widget (`LcListWidget`)\n* List of articles\n* Different list styles\n* Filter based on taxonomy\n\n### Read more accordion (`LcReadMore`)\n* Teaser text (richt text)\n* Body text (rich text)\n\n### Customize content elements and layout\nThere are two ways of customizing your website render. Either you overwrite an existing component or you want to create a new custom content element or you extend the current content elements\n#### Overwrite components\nOverwrite existing components with keeping the exact name and pass a new path. Keep the same [group and componentName](/lib/templates/plugins/components) and webpack will bundle your customized file instead of the default file.\n```\ncomponents: {\n  layout: {\n     LcLanguageSwitch: '~/components/overwrites/LanguageSwitch.vue',\n     LcMainFooter: '~/components/overwrites/MainFooter.vue'\n  },\n  view: {\n     LcArticleList: '~/components/overwrites/ArticleList.vue',\n     LcListWidget: '~/components/overwrites/ListWidget.js'\n  }\n}\n```\n#### Extend content elements\nEvery content element needs a unique component name. It should be UpperCamelCase and inside the componentMapping it takes the prefix `LC`. Example: `LcCustomComponentName`. To extend the default elements two options needs to get passed: a new componentMapping declaration and the edit and view component files.\n```js\n'lumen-cms':{\n  components:{\n    view:{\n      LcCustomComponent: '~/component/MyCustomComponent.vue' // must match componentMapping view\n    },\n    edit:{\n      LcCustomComponentEdit: '~/component/MyCustomComponentEdit.vue' // must match componentMapping name\n    }\n  },\n  cms:{\n   componentMapping:{\n    'CustomComponent':{\n      name: 'lc-custom-component-edit', // component to render the edit dialog\n      icon: 'material-icon', // shows the icon in the bottom bar\n      text: 'My custom component', // readable component title\n      view: 'lc-custom-component' // component to render the view\n    }\n   }\n  }\n}\n```\n\n## Custom Webpack Alias\nTo extend/overwrite the default behaviour there are following paths to overwrite the default functionality. Following is a complete example to extend your Webpack config with all available path alias. \n* Pass file with [predefinedStyles](lib/templates/util/contentElementStylePresets.js)\n* Customize GQL main schema files to fits your needs\n* [Three hooks](lib/templates/util/hooks) are available to customize the output of your render:\n1. initialAsync Data\nReturns `locale`, `host` and `slug` to process further website render\n2. getCanonical\nIn case you want to render a canonical tag\n3. getMeta\nDefault meta data as robots or google-site-verification in case you have multi-domain setup.\n\n```js\n// nuxt.config.js  \nbuild:{\n extend(config){\n   // extend pre-defined content element options\n   config.resolve.alias['~predefinedStyles'] = '~/customPath/predefinedStyles.js' // array of pre-defined custom layout\n   // gql schema and mutation files for top level schemas \n   config.resolve.alias['~updateArticle'] = '~/customPath/updateArticle.gql' // in case you customized article\n   config.resolve.alias['~createArticle'] = '~/customPath/createArticle.gql' // in case you customized article\n   config.resolve.alias['~extendedArticleFragment'] = '~/customPath/extendedArticleFragment.gql' // in case you customized article\n   config.resolve.alias['~createMedia'] = '~/customPath/createMedia.gql' // in case you need to add media in some other schemas\n   // hooks for initial data render\n   config.resolve.alias['~initialAsyncData'] = '~/customPath/initialAsyncData.js' // initial render of asyncData\n   config.resolve.alias['~getCanonical'] = '~/customPath/getCanonical.js' // receive canonical tag\n   config.resolve.alias['~getMeta'] = '~/customPath/getMeta.js' // get default head meta\n }\n}\n```\n \n\n## Deploy\nWith https://zeit.now the deploy of your Lumen CMS is as simple as typing:\n```\n$ npm i now -g\n$ cd pathOfProject\n$ now\n```\nTo connect the now deployment with your custom domain head over to the [documentation](https://zeit.co/docs/features/aliases) \nSidenote: you need at least a premium account due to the size of the website bundle.\n## Websites built with Lumen CMS\n* https://planet.training\n* https://www.studentsgoabroad.com | https://www.studentsgoabroad.org\n\n## Contribute\n\n- Clone this repository\n- Install dependencies using `yarn install` or `npm install`\n- Start development server using `npm run dev`\n\n## License\n\n[MIT License](./LICENSE)\n\nCopyright (c) Dominic Garms \u003cdjgarms@gmail.com\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flumen-cms%2Flumen-cms","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flumen-cms%2Flumen-cms","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flumen-cms%2Flumen-cms/lists"}