Getting Started

First of all, you have to keep in mind that your frontend and your backend are decoupled.

Let’s begin by creating your data source.

Create your data sources

Before deploying any SIB applications you will need SIB servers able to provide all capabilities your application relies on.

Our SiB server is called DjangoLDP which is based on Django framework and adapted to be compatible with Linked Datas convention but you can use any servers exposing data as LDP containers.

DjangoLDP come with packages developed and maintained by the Startin’Blox team. You can pick up the ones you like or write your own.

Requirements

The SIB server requires:

  • python 3.6

  • postgresql database (for production)

Warning

if you are using Windows, you may get some trouble. Please help us to improve reporting your problem on this issue

1. Install SIB Manager command

We have developed a command to facilitate the deployment of servers : ** Sib Manager**. It is not yet perfect and if you encounter a problem, help us to improve, open a issue.

Install sib-manager that allow you to use the sib command.

python3 -m pip install -U sib-manager

2. Initialize the server

Set up the server with SIB Manager where sibserver will be the name of your server.

sib startproject sibserver
cd sibserver
sib install server

now your architecture should look like :

sibserver/
    server/
        __init__.py
        settings.py
        urls.py
        wsgi.py
    manage.py
    packages.yml

You will find in your package.yml the configuration of your server.

On this server, you will add the package relative to the data shape you want to use in your component.

Server overview

Let’s now create a package.

3. Create a package

We are going to make a very simple data source to start which will be composed by questions and its answers.

You use the SIB Manager to create a new project :

sib startpackage djangoldp_mypack
cd djangoldp_mypack

Note

All your package should respect this semantic. For example djangoldp_skills.

Go to your models.py and set the models of datas you need :

from django.db import models
from djangoldp.models import Model

class FAQElement(Model):
   question = models.CharField(max_length=128, verbose_name="Question", blank=True, null=True)
   answer = models.CharField(max_length=128, verbose_name="Answer", blank=True, null=True)

   class Meta:
      anonymous_perms = ['']
      authenticated_perms = ['view', 'edit', 'delete', 'add']
      serializer_fields=["@id","question", "answer"]

5. Set up your server

Warning

If you want to configure a server with a package that already exist, you will need to make the “sib install sibserver” to update your server with it.

Go at the root of your development server at the level where your manage.py file resides.

Then run this command :

# Make the migration
python manage.py makemigrations
python manage.py migrate --run-syncdb

#Create a super user
python manage.py createsuperuser

#launch your server
python manage.py runserver

Now access your Django administration http://127.0.0.1:8000/admin/. You should see your model in the admin.

Fill one question and answer to test.

Access your API

To access to the jsonLD API, go to http://127.0.0.1:8000/faqelements/, where faqelement is the name of you model.

You should get something like this :

{
   "@id": "http://localhost:8000/faqelements/",
   "@type": "ldp:Container",
   "ldp:contains": [
      {
            "@id": "http://localhost:8000/faqelements/1/",
            "question": "What is SOLID ?",
            "answer": "SOLID is a set of standard to create interoperability.",
            "permissions": [
               {
                  "mode": {
                        "@type": "view"
                  }
               },
               {
                  "mode": {
                        "@type": "delete"
                  }
               }
            ]
      }
   ],
   "permissions": [
      {
            "mode": {
               "@type": "add"
            }
      },
      {
            "mode": {
               "@type": "view"
            }
      }
   ],
   "@context": "https://cdn.happy-dev.fr/owl/hdcontext.jsonld"
}

Congratulations! You’ve made a data source.

Note

To see how our API is structured, have a look to our SOLID Introduction

Make a frontend app

If you are familiar with React or VusJS, learning how to use Startin’blox is going to be easy for you. It’s even easier.

So why use Startin’blox instead of React or VueJS?

Because it allows you to easily grasp the SOLID standards and web components latest standards. It is also lighter to install.

See more about it in our FAQ.

How to set up the technology ?

First set up a server for your frontend App using :

  • NPM via http-server

  • Python via python3 -m http.server 8001

To start, simply import the core in the head tag of a index.html file:

<!-- ... Import the core ... -->
<script type="module" src="https://unpkg.com/@startinblox/core"></script>

Base Components

It enables you to use Startin’blox technology and all the base components from the core of the framework like Solid-display, that displays data or Solid-form that offer a form to post data.

<solid-display
   data-src="https://apiprod.happy-dev.fr/collectives/"
   fields="name, email"
></solid-display>

Note

The ``data-src`` attribute

You will find it in almost all Startin’blox components. It is the attribute that defines the data source you want to interact with in the component. You can see what the API looks like at (https://apiprod.happy-dev.fr/collectives/ ).

For our example, let’s display your data sources by replacing the data-source below by the one you created :

<solid-display
   data-src="http://127.0.0.1:8000/faqelements/"
   fields="question, answer"
></solid-display>

Note

Some public sources to play

To make your tests with Startin’blox, here are some public readonly data sources:

External Components

Some useful components aren’t in the core to keep it light and modular. It’s the case for Solid-Router or Solid Auth for example. To use them, you have to import them independently.

<!-- ... Import the core ... -->
<script type="module" src="https://unpkg.com/@startinblox/core"></script>
<script type="module" src="https://unpkg.com/@startinblox/router@latest"></script>

Create a component

A component should be independent from your application so you should create a new project to develop it.

Note

If you want to know when it’s relevant to create a component go to the “About our Components” page.

Requirements

Be sure you have at least the version 6.14.5 of npm with :

npm -v

To update your npm version :

npm install -g npm@latest

Warning

You may need to prefix these commands with sudo, especially on Linux, or OS X if you installed Node using its default installer.

We will assume that you are at least comfortable with HTML, CSS and JavaScript. However, you don’t really need to be an expert. We recommend this good guide to get you back on track with JS.

Steps

Let’s set up a local development environment for a FAQ component as example.

1. Set the file you need .

solid-faq
  - index.html
  - solid-faq.js

Note

By convention, we prefix Startin’blox components with “solid”. Example: solid-faq, solid-agenda, solid-map..

2. Init npm and set your server Open a terminal, go to your folder and type the following commands:

# Init a npm management
npm init -y

# Install a server in a development environment
npm i -D http-server

Go to your package.json and replace the ‘test’ script by the following :

"serve": "http-server"

Your package.json should look like this :

{
    "name": "solid-faq",
    "version": "1.0.0",
    "description": "",
    "main": "index.js",
    "scripts": {
        "serve": "http-server"
    },
    "keywords": [],
    "author": "",
    "license": "ISC",
    "dependencies": {},
    "devDependencies": {
        "http-server": "^0.12.3"
    }
}

3. Start your component

We have create SolidTemplateElement that is a class that can extend your component in order to purify your code of all useless complexity so that you can concentrate on the essential: your functionality.

What are we going to do?

Let’s just display questions and answers in an accordion and allow the user to submit a new question.

Something like this:

A FAQ component as example

Let’s suppose we want to make the recipient’s email customizable. To obtain this rendering, it would be enough to implement in our html page a component that looked like this:

<solid-faq
    data-src="https://api.startinblox.com/faqs/"
    recipient-email="alice@startinblox.com"
></solid-faq>

Note

Remember the ``data-src`` attribute ? This attribute hosts the data source you want to interact with in this component.

Note

Want to learn more about web components ? We recommend this introduction.

Let’s start !

Here is the minimum code your component must contain that extends SolidTemplateElement.

/**
* solid-faq.js
*/
// Import SolidTemplateElement
import SolidTemplateElement from "https://unpkg.com/@startinblox/core@0.10/dist/solid-template-element.js";

// Name your component and extend SolidTemplateElement
export class SolidFAQ extends SolidTemplateElement {

        constructor() {
        super();
    }

    // Define the attributes you want
    static get propsDefinition() {
        return {
        dataSrc: "data-src",
        recipientEmail: "recipient-email",
        };
    }

    // Pass your attributes to your template
    template({ dataSrc, recipientEmail }) {
        // If we have no data sources, we display nothing
        if (!dataSrc) return "";
        let tmpl = `
            <solid-display
                data-src="${dataSrc}"
                fields="question, answer"
                id="faq"
            ></solid-display>
            `;
        // Otherwise, set the possibility to submit a question
        if (recipientEmail) {
        tmpl += `
            <a href='mailto:${recipientEmail}?subject=A%20new%20question%20for%20the%20FAQ&body=Hi!'>
                Your question question not here ?
            </a>
        `;
        }
        return tmpl;
    }
}

customElements.define("solid-faq", SolidFAQ);

4. Pay attention to propsDefinition method

You are going to set your attribute in this method. recipientEmail is the parameter where we are going to fill in the email of our recipient.

static get propsDefinition() {
    return {
        dataSrc: 'data-src',
        recipientEmail: 'recipient-email'
    }
}

Note

Note the syntax convention => recipientEmail: ‘recipient-email’

5. Let’s focus on the template

The template contains the HTML you want to render. Pass your attributes to your template and write it. To display the questions and answers, we are going to use solid-display. The attributes fields is used to define which datas you want to display from your data source.

We add a conditional rendering: if no email is filled in, the possibility to submit a question is not displayed.

// Pass your attributes to your template
template({ dataSrc, recipientEmail }) {
    // If we have no data sources, we display nothing
    if (!dataSrc) return "";
    let tmpl = `
        <solid-display
            data-src="${dataSrc}"
            fields="question, answer"
            id="faq"
        ></solid-display>
        `;
    // Otherwise, set the possibility to submit a question
    if (recipientEmail) {
    tmpl += `
        <a href='mailto:${recipientEmail}?subject=A%20new%20question%20for%20the%20FAQ&body=Hi!'>
            Your question question not here ?
        </a>
    `;
    }
    return tmpl;
}

6. Set your datas

You can set here the data source you’ve created. Or you can just set fake datas, with those static datas in JSON-LD by create a file named data-faq.jsonld at the root of your project.

{
    "@id": "",
    "@type": "ldp:Container",
    "ldp:contains": [
        {
            "question": "What is Startin'blox ?",
            "answer": "A cooperative and a technology to build the web of our dreams",
            "@id": "questions-1",
            "permissions": []
        },
        {
            "question": "What is the SOLID project ?",
            "answer": "A set of standards that allows web applications to all speak the same language and become interoperable.",
            "@id": "questions-2",
            "permissions": []
        }
    ],
    "permissions": [],
    "@context": "https://cdn.happy-dev.fr/owl/hdcontext.jsonld"
}

Note

If you want to know more about how our API looks like, have a look to our SOLID introduction.

7. Implement your component

Import the script of your component and set the component in your index.html.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <!--Import a custom font-->
    <link href="https://fonts.googleapis.com/css2?family=Montserrat&display=swap" rel="stylesheet">
    <!--Import the framework-->
    <script type="module" src="https://unpkg.com/@startinblox/core"></script>
    <!--Import the component-->
    <script type="module" src="/solid-faq.js"></script>
    <title>Solid FAQ Demo</title>
</head>
<body>
    <h1>Solid FAQ Demo</h1>
    <!--Import the component-->
    <solid-faq
        data-src="data-faq.jsonLD"
        recipient-email="alice@startinblox.com"
    ></solid-faq>
</body>
</html>

6. Test your component

npm run serve

You should be able to display your datas but at the moment it’s a bit ugly.

A FAQ component as example

You’re almost done !

Let’s now add some style.

7. Implement JS and CSS in your component

For this example, we propose you to create a js file, like /js/main.js.

Add the JS you need to make your accordion work, like this:

/**
* js/main.js
*/
// Select the component
var component = document.getElementById("faq");

// We use populate event to detect when the component is generated
component.addEventListener("populate", (event) => {

    // Select each question
    var acc = document.querySelectorAll("solid-display-value[name='question']");
    var i;

    for (i = 0; i < acc.length; i++) {
        //For each question, if we click..
        acc[i].addEventListener("click", function () {
        // Add or remove the "active" class
        this.classList.toggle("active");

        // Select the answer just below the question
        var panel = this.nextElementSibling;
        // If the answer is opened, then close it
        if (panel.style.maxHeight) {
            panel.style.maxHeight = null;
        // Otherwise, open it.
        } else {
            panel.style.maxHeight = panel.scrollHeight + "px";
        }
        });
    }
})

Note

Did you notice the populate event? It’s an event that allows you to trigger javascript only after the component you want to manipulate has been generated. See the Event documentation for more explanation.

Here is the CSS used for the demo:

/**
* css/main.css
*/

body {
    font-family: 'Montserrat', sans-serif;
    background-color: #4475B8;
}
h1{
    color : white;
}

solid-faq {
    max-width : 700px;
}

solid-display-value[name='question'] {
    cursor: pointer;
    padding: 18px;
    text-align: left;
    border: none;
    outline: none;
    transition: 0.4s;
    display : block;
    background-color: white;
    color : #4475B8;
}

solid-display-value[name='answer'] {
    padding: 0 30px;
    max-height: 0;
    overflow: hidden;
    transition: max-height 0.2s ease-out;
    display : block;
    background-color : #ECECEC;
    color : #414141;
    border : 1px #FDD17A solid;
    line-height: 30px;
}

solid-display-value[name='question']:after {
    content: '\02795';
    font-size: 13px;
    float: right;
    margin-left: 5px;
}

solid-display-value[name='question'].active:after {
    content: "\2796";
}

solid-faq solid-display+a{
    color : white;
    line-height : 50px ;
}

Use Helper functions

SiB framework provide you Helpers function to add JS and CSS in your component.

Add at the begin of your solid-faq.js, import your JS and CSS with those functions:

...

// Import Helper functions
import {
importCSS,
importJS,
} from "https://unpkg.com/@startinblox/core@0.10/dist/libs/helpers.js";

// Use the Helpers functions
importJS(`./js/main.js`);
importCSS(`/css/main.css`);

export class SolidFAQ extends SolidTemplateElement {

...

It should be better now, no ?

A FAQ component as example

8. Translate your component

Warning

This part is not working and need improvement. You can jump to the step 8 :)

To translate the static strings of your components, follow these steps:

  • In your component, create a folder which contains all the translation files. You can name it locales for example. Inside, create one file per language, with the structure [code_language].json, for example: fr.json.

  • In each file, add one line per string to translate. Your file should look like this:

{
    "label.question": "Your question is not here ?"
}
  • In the constructor of your component, define the path of your folder:

// For the demo
const base_url = "./";
// The production url of your component =>
//const base_url = "https://path/to/your/component";

export class SolidFAQ extends SolidTemplateElement {

    constructor() {
        ...

        this.setTranslationsPath(`${base_url}/locales`);
    }

...

}
  • Use the localize method to show the translated strings in your template:

const base_url = "https://unpkg.com/@startinblox/solid-faq"; // url of your component

export class SolidFAQ extends SolidTemplateElement {

    ...

    template( { dataSrc, recipientEmail } ) {
        if (!dataSrc) return '';
        let tmpl = `
            ...
            <a href='mailto:p.${recipientEmail}?subject=A%20new%20question%20for%20the%20FAQ&body=Hi!'>
                ${this.localize('label.question')}
            </a>
        `;
        return tmpl
    }
}

As a developer who uses a component, you can also add your own translation files by configuring your translation folder. Like for the component, this folder should contain one file per language:

<solid-conversation
    data-src="./data/conversations.jsonld"
    extra-translations-path="http://my_app/locales"
></solid-conversation>

9. Does it work well?

A FAQ component as example

If you get any trouble (or any idea to improve!), please mail me :)

Note

Document your component!

Each time you create a component, remember to document it with a README.md, especially the version of the core with which it was developed. If you create a component by default you will be considered as the maintainer. This means that you are responsible for its future updates but also that you could get support contracts on this component in the future :)

Releases are posted here. Subscribe to the newsletter not to miss the next ones!

Warning

This tutorial could be improved by adding accessibility.

Go Deeper

Discover other features of the framework playing with the demo on the website.