Getting Started
Elemental CMS is published under MPL-2.0 license and can be easily installed by issuing the following command:
pip install elemental-cms
Before We Start #
We need a working MongoDB server to be able to explore the tool and all the available samples. We can use a standalone installation, or we can always create an account on MongoDB Atlas. The free tier will be more than enough to follow this guide.
Since the tool is written using Python, before we start to build our application we will create a Python "project":
mkdir getting-started && \
cd getting-started
It is always recommended working with virtual environments so we can isolate problems and avoid installing undesired packages globally.
python -m venv .venv && \
source .venv/bin/activate
Now that we have our virtual environment up and activated, we are ready to install elemental-cms CLI exclusively on our new isolated "project". This will also install all the dependencies.
Command Line Interface (CLI) #
Now that the tool is installed, we can use it by typing:
elemental-cms
This will display the tool help that will look something like this:
Usage: elemental-cms [OPTIONS] COMMAND [ARGS]...
Elemental CMS management CLI
Options:
--help Show this message and exit.
Commands:
global-deps Global dependencies management
init Initialize Elemental CMS workspace
media Media content management
pages Pages management
snippets Snippets management
static Static resources management
version Show version information
Initializing Elemental CMS Workspace #
The CLI includes an "init" command which will create a basic structure on the working directory. But before we can issue the init command, we need to create a settings file under the name local.cli.json in our settings folder.
mkdir settings && \
nano local.cli.json
Minimum local.cli.json file content to run the init command:
{
"cmsCoreContext": {
"DEBUG": true,
"ENV": "development",
"SECRET_KEY": "your-secret-key-here",
"SITE_NAME": "Elemental CMS Getting Started",
"COMPANY": "Your Company",
"CANONICAL_URL": "https://www.your-site.com",
"LANGUAGES": [
"en",
"es"
],
"DEFAULT_LANGUAGE": "en",
"LANGUAGE_MODE": "multi",
"STATIC_FOLDER": "static",
"MEDIA_FOLDER": "media",
"STATIC_URL": "https://storage.googleapis.com/your-static-bucket",
"MEDIA_URL": "https://storage.googleapis.com/your-media-bucket",
"STATIC_BUCKET": "your-static-bucket",
"MEDIA_BUCKET": "your-media-bucket",
"GOOGLE_SERVICE_ACCOUNT_INFO": {
"type": "service_account",
"project_id": "your-project-id"
},
"GLOBAL_DEPS_FOLDER": "workspace/global_deps",
"PAGES_FOLDER": "workspace/pages",
"SNIPPETS_FOLDER": "workspace/snippets",
"USER_IDENTITY_SESSION_KEY": "userIdentity",
"SESSION_STORAGE_ENABLED": true,
"SESSION_TIMEOUT_IN_MINUTES": 360
},
"cmsDbContext": {
"id": "elemental-cms-db-friendly-name",
"connectionString": "mongodb://my-username:my-passwd@mongodb-hostname:27017/admin?directConnection=true",
"databaseName": "elemental_getting_started"
}
}
The folder properties and database properties are vital to the init command to run. If any of these properties are missing or misconfigured, the command will not work.
elemental-cms init -c settings/local.cli.json
If everything goes ok, we must have the following folder structure:
└── getting-started
├── .elemental
├── media
├── settings
│ └── local.cli.json
├── static
├── templates
│ └── base.html
├── translations
└── workspace
├── global_deps
├── pages
└── snippets
Additionally, our MongoDB server will have our CMS database:
> show dbs
admin 0.000GB
config 0.000GB
elemental_getting_started 0.000GB
local 0.000GB
Creating Our First Page #
To create a new page, we start by issuing the pages CLI command like this:
elemental-cms pages create -p home en
This will create the page content file and the page spec file under the workspace/pages/en directory.
Spec File
The spec file has the page metadata which can then be pushed to the database in order to make the page available in the CMS.
The structure of the spec file can be seen below:
{
"_id": {
"$oid": "625b675f0c82e4f4d2107e8d"
},
"name": "home",
"language": "en",
"title": "home page",
"description": "",
"isHome": false,
"cssDeps": [],
"jsDeps": [],
"createdAt": {
"$date": 1650157407821
},
"lastModifiedAt": {
"$date": 1650157407821
}
}
As this is our first and only page, we should set the isHome property to true.
Content File
The content file will have the HTML for the page. After the create command execution, it will have a simple HTML like the following:
<div></div>
Pushing Our New Page #
In order to push a page, we must use the pages push command which will send the metadata and content to the database and create a "draft" version of the page.
elemental-cms pages push -p home en
Publishing Our Page #
Until now, the new page is stored in the "drafts" repository. In order to be accessible through the web application, we must publish the page by running the following command:
elemental-cms pages publish -p home en
Flask Application #
Until now, we have created a multi-language page and successfully published it, but we are missing our application entry point. Since this framework is based on Flask, we must create a simple entry point as we will do it for any Flask application.
So we will create the main.py script file, and then we will add the minimum required script to launch a simple web application.
import json
import os
from elementalcms import Elemental, ElementalContext
from elementalcms.core import FlaskContext, MongoDbContext
from flask import Flask
www = Flask(__name__, template_folder='templates', static_folder='static')
CONFIG_FILEPATH = os.environ.get('CONFIG_FILEPATH', 'settings/local.www.json')
with open(CONFIG_FILEPATH) as config_file:
settings = json.load(config_file)
cms_core_context = FlaskContext(settings['cmsCoreContext'])
cms_db_context = MongoDbContext(settings['cmsDbContext'])
elemental_context = ElementalContext(cms_core_context, cms_db_context)
Elemental(www, elemental_context)
if __name__ == '__main__':
www.run(host='0.0.0.0', port=8000)
Running the Application
In order to run the application, we use python as we would do with any other application:
python main.py
CLI & WWW Settings
If we run the application right now, we will get an error because the file settings/local.www.json does not exist. We can create this file by copying the local.cli.json version.
cp settings/local.cli.json settings/local.www.json
Then we edit the local.www.json file so its content looks like this:
{
"cmsCoreContext": {
"DEBUG": true,
"ENV": "development",
"SECRET_KEY": "your-secret-key-here",
"SITE_NAME": "Elemental CMS Getting Started",
"COMPANY": "Your Company",
"CANONICAL_URL": "https://www.your-site.com",
"LANGUAGES": [
"en",
"es"
],
"DEFAULT_LANGUAGE": "en",
"LANGUAGE_MODE": "multi",
"STATIC_FOLDER": "static",
"MEDIA_FOLDER": "media",
"STATIC_URL": "/static",
"MEDIA_URL": "/media",
"GLOBAL_DEPS_FOLDER": "workspace/global_deps",
"PAGES_FOLDER": "workspace/pages",
"SNIPPETS_FOLDER": "workspace/snippets",
"USER_IDENTITY_SESSION_KEY": "userIdentity",
"SESSION_STORAGE_ENABLED": true,
"SESSION_TIMEOUT_IN_MINUTES": 360,
"DESIGN_MODE_ENABLED": true
},
"cmsDbContext": {
"id": "elemental-cms-db-friendly-name",
"connectionString": "mongodb://my-username:my-passwd@mongodb-hostname:27017/admin?directConnection=true",
"databaseName": "elemental_getting_started"
}
}
As we can see, the main differences are in the following cmsCoreContext properties:
Property |
local.www.json |
local.cli.json |
---|---|---|
STATIC_URL |
/static |
https://storage.googleapis.com/your-static-bucket |
MEDIA_URL |
/media |
https://storage.googleapis.com/your-media-bucket |
STATIC_BUCKET |
NOT REQUIRED NOR USED |
your-static-bucket |
MEDIA_BUCKET |
NOT REQUIRED NOR USED |
your-media-bucket |
GOOGLE_SERVICE_ACCOUNT_INFO |
NOT REQUIRED NOR USED |
Google Cloud Service account with granted access over GCS |
DESIGN_MODE_ENABLED |
true (optional) |
NOT USED |
local.cli.json file is used by the CLI in order to be able to publish media and static files to GCS.
local.www.json file is used in our local development environment. It uses /media and /static URLs to serve local files while we are in development mode. In development mode, we will not use GCS, and because of that, the debug file can miss related settings like STATIC_BUCKET, MEDIA_BUCKET and GOOGLE_SERVICE_ACCOUNT_INFO. We can also activate the design mode by adding DESIGN_MODE_ENABLED property and setting it to true.