-
Notifications
You must be signed in to change notification settings - Fork 0
Development
- Scope
- Set-Up
- Directory structure
- Start the development server
- Build the site manually without starting a server
- Localization
- Layout/Component development
This document will contain the necessary information to:
- create a local development version of the SmartAQnet-Website
- change layouts and components of the website
- modify the stylesheets to make design changes [TBD]
- modify the dashboards style and behavior
- understand how the internationalization and other functions work on the code level [TBD]
When you clone the repository, make sure that you also check out all submodules (currently only the dashboard) with the --recursive switch:
# HTTPS:
git clone --recursive https://github.com/SmartAQnet/smartAQnet.github.io.git
# OR SSH:
git clone --recursive git@github.com:SmartAQnet/smartAQnet.github.io.gitUse the Editor / IDE you are most comfortable with. Both, Visual Studio Code and Atom, are a good compromise between extensibility and performance with a quick learning process.
Please see the Home document for the full directory structure.
The following files define how the page looks like.
.
├── assets
│ ├── src
│ │ └── css
│ │ ├── bootstrap.scss # custom themed version of bootstrap, based on npm module
│ │ └── main.scss # imports files from _sass to build the sites main theme
│ └── static
│ └── css
│ └── vendor # includes font-awesome and KaTeX
├── _sass # main theme generated at jekyll build
│ └── layouts # styles for a specific page layout (posts, pages, ...)
│ └── includes # styles for a specific component (calendar, footer, ...)
│ └── base # variables and global styles
|
|
└── dashboard
└── content
└── css
└── app.css # theme and styles for the dashboardIf you are not sure where to put a style rule, you might follow this process:

For changing the behavior of the dashboard please see the Dashboard section.
All the sites logic is either implemented in <script> tags within posts and pages or in a file in the assets/src/js/partials directory. In the latter case, the script is bundled while building with gulp and put into assets/dist/js/main.min.js.
There is no module loader, all partials are executed in the global browser scope. The main script is loaded through a script tag within the <head> of every page.
The dashboard is an AngularJS (== Angular 1.XX, not to be confused with Angular which usually means Angular >=2) web application.
The dashboard is a git submodule from https://github.com/SmartAQnet/dashboard. The embedded-dashboard branch is used for the websites dashboard.
The dashboard consists of a jekyll page in (24.05.2019)pages/en/dashboard/dashboard.html which loads all the dashboards views and controllers (and is also responsible for the top navigation menu) and the dashboard (dashboard/) itself.
The Dashboard is located in dashboard/. All views, controllers and stylesheets are found in this directory. The main page dashboard/content/index.html is a jekyll page that includes all AngularJS controllers.
Since its permalink is set to /en/dashboard/, the dashboard is available as host.xy/en/dashboard/ despite not being in the pages subfolder.
Two files, redirect-to-jekyll-post.html and redirect-slash.html are used to redirect host.xy/dashboard/content and host.xy/en/dashboard to host.xy/en/dashboard/.
The development server is defined as a docker-compose project with two services. You need Docker and Docker Compose (already included in Docker Desktop for Mac and Windows) in order to proceed.
Start the development server by bringing up all services:
cd dev # assumes you are already at the root of the repository
docker-compose upThis will:
- Start a Jekyll-Server on Port
4000- You should be able to reach it at
http://localhost:4000/
- You should be able to reach it at
- A gulp task to process the assets.
The development server uses jekylls and gulps watch features. Under most Linux systems gulp and the jekyll server will rebuild the site after a change automatically.
- The gulp service will only update CSS and JS while the server is running. To minify additional images added after the server start you have to restart the server or run gulp manually while the server is running.
- Docker for Windows does not allow containers to monitor file changes (no inotify support). The
docker-compose.polling.ymlfile can be used to activate polling. This is untested but might enable automatic rebuilds on Windows:docker-compose -f docker-compose.yml -f docker-compose.polling.yml up
The compose project is configured to use the PORT environment variable for the jekyll server:
PORT=5000 docker-compose up
Note: The stdout from jekyll will still tell you that the server is running on port 4000 since this is the container internal port.
You can again use the services in the dev folder:
- Process the assets with gulp
cd dev docker-compose -f docker-compose.yml -f docker-compose.build-once.yml run gulp - Run jekyll to regenerate the site in
_sitedocker-compose -f docker-compose.yml -f docker-compose.build-once.yml run gh-pages
the assets folder contains a gulpfile.js which defines how the assets should be processed.
Gulp builds:
- The main Javascript file
assets/dist/js/main.min.jscontaining most logic of the sites components.- The file consists of all the partials in
assets/src/js/partials.
- The file consists of all the partials in
- A compressed version of images in
assets/static/imgwhich replace their original file. - A custom version of Bootstrap from the the
assets/src/cssfolder based on the bootstrap-material-design npm module in built in theassets/dist/cssdirectory.
The _config.yml defines dafault front-matter that is added to all posts/pages where it is not overridden:
defaults:
- scope:
path: ''
values:
lang: 'en'
#[...]
- scope:
path: '_posts/en'
values:
lang: 'en'
permalink: /en/:title
- scope:
path: '_posts/de'
values:
lang: 'de'
permalink: /de/:title
- scope:
path: 'pages/de'
values:
lang: 'de'
permalink: /de/:basename/
- scope:
path: 'pages/en'
values:
lang: 'en'
permalink: /en/:basename/At page generation the variable page.lang is used to distinguish between the languages and to generate language-specific versions of the site.
-
lang="XX"is added to the html element. This has various effects (e.g. loading correct twitter language versions). - Adding
alternatelink-Tags to the header -> Tell Google about localized versions of your page<link rel="alternate" hreflang="de" href="/de/about-us/"> <link rel="alternate" hreflang="en" href="/en/about-us/"> - Render certain includes (e.g calendar, footer, ...) with data from
_data/XXwhere XX is the specified language. - The language switcher will be able to switch between the different versions.
The home layout is specified in _layouts/home.html.
The twitter card is specified in _includes_/twitter-timeline.html.
The twitter card uses the official twitter embed code and waits for its rendered event to inject the sites own stylesheet into the embedded iframe.
Language support was already present after setting the lang="XX" attribute on the html element.
The calendar card is specified in _includes_/twitter-timeline.html.
In its main for-loop {% for item in site.data[page.lang].calendar.entries %} this iterates over entries from _data/XX/calendar.yml.
Mainly, data is just inserted as-is. However, the month is inserted as a class month-{{item.end.month}} on the month's div element. The name of the month is determined by scss rules in _sass/includes/_calendar.scss built from dictionaries.
These rules insert a pseudo element with content set according to the dictionaries defined in these files. For example, the english months are determined by
// From _sass/includes/_calendar.scss
$months-en: (
"01": "JAN",
"02": "FEB",
"03": "MAR",
"04": "APR",
"05": "MAY",
"06": "JUN",
"07": "JUL",
"08": "AUG",
"09": "SEPT",
"10": "OCT",
"11": "NOV",
"12": "DEC");The blog is defined in _includes/blog.html. It is used to generate the post list on the home page.
The logic of listing the posts is interwoven with the pagination logic.
The pagination plugin for Jekyll / Github pages can not exclude posts written in the wrong language.
Therefore, the plugin is not used and all pages with all posts are generated and subsequently served at once to a user.
The following procedure is used:
- Find all posts written in the current language
- Calculate the total number of pages with respect to
site.items_per_page, the number of posts per page defined in_config.yml. - For each page:
- Render the post teasers (See
_includes/post-teaser.html) - Render the pagination (See
_includes/blog-pagination.html)- The pagination does not use Javascript, only CSS.
- Each page is represented as a hash in the url (e.g.
#post-page-2). - Pages are hidden per default. A CSS rule with the
:targetselector is used to display the correct page:.post-page:target{ display: block; } - The total and current page numbers are given to the pagination include. For each page, a page-specific version of the pagination is rendered.
- Render the post teasers (See
- Render the first page again with the special
post-page-special-firstclass.- This is the page that is rendered when no page is the target (no hash specified in the url)
Post navigation is the "Previous Post" / "Next Post" section at the bottom of posts.
It is defined in _includes/post-nav.html.
To provide support for different languages the default methods for getting the next / previous post are not used.
Instead:
- The posts are filtered to only include the correct language in a list
- The index of the current and next post are found in the list
- The previous and next posts are found in the list by index comparison
The redirection layout is specified in _layouts/redirection.html.
The generated page redirects a user to whatever location is given in the destination option in the page's front matter.
The generated site uses
- the
document.location.replacefunction on the body load event to replace the current page in the browser history - the
http-equiv="refresh"meta tag to instruct the browser to go to the destination after one second.- The original page remains in the browser history unlike a 30X redirection.
- The redirection is delayed for one second to prioritize the Javascript method.
- Google should pick up this type of redirection.
- a link that is displayed to the user if anything else fails.