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.
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"]
4. Link your package to your development server¶
At the root of you Sib server, create a symbolic link to your package :
ln -s ../path/to/package/app/name-of-package
For example :
ln -s ../../djangoldp_mypack/djangoldp_mypack djangoldp_mypack
You can check if it’s correctly done with the ll command :
Tell your server you’ve add a new package in the packages.yml:
ldppackages:
djangoldp_mypack: djangoldp_mypack
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:
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.
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 ?
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?¶
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.