Using Next.js and Material UI Together

Next.js is a convenient and powerful framework for React. Its main benefit over using React directly is its transparent support for Server-Side Rendering.
Material UI is a very popular set of React components implementing Google’s Material Design guidelines.

Both libraries are impressive, but there are some tricks to know to make them playing well together.

Bootstrapping

Setting up MUI in a Next project requires some non-trivial tweaks to Next’s initialization process. Conveniently, Material UI provides a skeleton containing a working Next.js project with Material UI already properly configured. It’s the easiest way to kickstart a new project using both tools, don’t miss it!

# Download the skeleton
$ curl https://codeload.github.com/mui-org/material-ui/tar.gz/master | tar -xz --strip=2  material-ui-master/examples/nextjs
$ cd nextjs
# Install the deps
$ yarn install
# Start the project
$ yarn dev

To learn how to integrate Material UI in an existing project, take a look to pages/_document.js and pages/_app.js they contain most the wiring logic.

Forms

Material UI is especially useful because of the large set of form components it provides. But handling forms with React (and so with Next) is tedious and verbose. My colleague Morgan Auchedé recently told me about Formik. Formik is a tiny yet super powerful library allowing to easily create forms with React. And good news: it plays very well with Next! Here is how a basic login form looks when using Formik:

import React from 'react';
import { Formik, Form, Field, ErrorMessage } from 'formik';

export default MyForm = () => (
    <Formik
      initialValues={{ email: '', password: '' }}
      validate={values => {
        // Your client-side validation logic
      }}
      onSubmit={(values, { setSubmitting }) => {
        // Call your API
      }}
    >
      {({ isSubmitting }) => (
        <Form>
          <Field type="email" name="email" />
          <ErrorMessage name="email" />
          <Field type="password" name="password" />
          <ErrorMessage name="password" />
          <button type="submit" disabled={isSubmitting}>
            Submit
          </button>
        </Form>
      )}
    </Formik>
);

Nice! However, when switching to Material UI inputs, the high level helper components provided by Formik become almost useless. Our forms are verbose again. Fortunately, a small library intuitively named formik-material-ui makes it easy to bridge both libraries! Here is the same form as before (including error handling), but rendered using Material UI components:

import React from 'react';
import { Formik, Form, Field } from 'formik';
import { TextField } from 'formik-material-ui';
import Button from "@material-ui/core/Button";

export default MyForm = () => (
    <Formik
      initialValues={{ email: '', password: '' }}
      validate={values => {
        // Your client-side validation logic
      }}
      onSubmit={(values, { setSubmitting }) => {
        // Call your API
      }}
    >
      {({ isSubmitting }) => (
        <Form>
          <Field type="email" name="email" component="TextField" />
          <Field type="password" name="password" component="TextField" />
          <Button
           type="submit"
           fullWidth
           variant="contained"
           color="primary"
           disabled={isSubmitting}
         >
           Submit
         </Button>
        </Form>
      )}
    </Formik>
);

This form is even less verbose, and is now looking good!

Buttons and Routing

Next.js comes with a nice routing system working transparently regardless if the app is executed client-side or server-side. It’s one of the biggest strength of the framework. However, in Material UI, the Button component is often used to trigger navigation between pages, and using buttons with the Router isn’t very intuitive. Still, it’s easy to do:

import React from "react";
import Link from "next/link";
import Button from "@material-ui/core/Button";

export default MyLink = () => (
  <Link href="/pricing" passHref>
    <Button component="a">Managed version</Button>
  </Link>
);

First, we set the component prop of Button to a. It tells Material UI to use an anchor for this button, instead of a… button by default. Then, we set the passHref prop of the Link element, it hints the Router to pass the href prop to the child component, even if doesn’t look like an anchor. Actually (because of the component prop we set earlier), the grandchild will be an anchor, and Material UI will forward the href prop to it! The rendered a element now has a proper href attribute, both client-side and in the server-side generated HTML. Good SEO, for free!

The same trick can be used with the Typography component:

import React from "react";
import Link from "next/link";
import Button from "@material-ui/core/Typography";

export default MyLink = () => (
  <Link href="/pricing" passHref>
    <Typography variant="caption" component="a">Managed version</Typography>
  </Link>
);

This time, we created a link looking like a caption!

That’s all for today. Have fun with Next and Material UI! For more tricks about JavaScript (among various other technologies), follow me on Twitter!

PHP Schema: generate a fully functional PHP / Doctrine / Symfony data model from Schema.org vocabulary in minutes

PHP Schema is a code generator that instantly generates a PHP data model from the Schema.org vocabulary : browse Schema.org, choose the types and properties you need, run our code generator and you’re done! You get a fully featured PHP data model including:

  • A set of PHP entities with properties, constants (enum values), getters, setters, adders and removers. The class hierarchy provided by Schema.org will be translated to a PHP class hierarchy with parents as abstract classes. The generated code complies with PSR coding standards.
  • Full high-quality PHPDoc for classes, properties, constants and methods extracted from Schema.org.
  • Doctrine ORM annotation mapping including database columns with type guessing, relations with cardinality guessing, class inheritance (through the @AbstractSuperclass annotation).
  • Data validation through Symfony Validator annotations including data type validation, enum support (choices) and check for required properties.
  • Interfaces and Doctrine ResolveTargetEntityListener support.
    Custom PHP namespace support.
  • List of values provided by Schema.org with PHP Enum classes.

Bonus:

  • The code generator is fully configurable and extensible: all features can be deactivated (e.g.: the Doctrine mapping generator) and custom generator can be added (e.g.: a Doctrine ODM mapping generator).
  • The generated code can be used as is in a Symfony app (but it will work too in a raw PHP project or any other framework including Laravel and Zend Framework).

Why use Schema.org data to generate a PHP model?

Don’t Reinvent The Wheel

Data models provided by Schema.org are popular and have been proved efficient. They cover a broad spectrum of topics including creative work, e-commerce, event, medicine, social networking, people, postal address, organization, place or review. Schema.org has its root in a ton of preexisting well designed vocabularies and is successfully used by more and more website and applications.

Pick up schemas applicable to your application, generate your PHP model, then customize and specialize it to fit your needs.

Improve SEO and user experience

Adding Schema.org markup to websites and apps increase their ranking in search engines results and enable awesome features such as Google Rich Snippets and Gmail markup.

Mapping your app data model to Schema.org structures can be a tedious task. Using the generator, your data model will be a derived from Schema.org. Adding microdata markup to your templates or serializing your data as JSON-LD will not require specific mapping nor adaptation. It’s a matter of minutes.

Be ready for the future

Schema.org improves the interoperability of your applications. Used with hypermedia technologies such as Hydra it’s a big step towards the semantic and machine readable web. It opens the way to generic web API clients able to extract and process data from any website or app using such technologies.

Using SocialShare with WordPress to create custom social networks buttons

2013/02/14: Take care of the smarter caching system introduced in version 0.2.0.

Here is how to use the SocialShare PHP library to create custom Facebook, Twitter and Google Plus share buttons including the number of share.

The SocialShare library

Installing the library

The first step is to install SocialShare through the awesome Composer dependency manager. If you have not installed composer already, grab it!

In your custom WordPress themes directory (something like wp-content/themes/<mytheme-name>/), run the following command to get a copy of the library:

php /path/to/composer.phar require dunglas/php-socialshare:~0.1

Two Composer related files are created: composer.json and composer.lock. They contain the list dependencies of our project (only SocialShare for now). The code of SocialShare and Doctrine Cache (a dependecy of SocialShare) have been downloaded in the vendor/ directory.

Initializing SocialShare and creating helper functions

Put the following code in your theme’s functions.php file:

// Social share initialization

use Doctrine\Common\Cache\PhpFileCache;
use SocialShare\SocialShare;
use SocialShare\Provider\Facebook;
use SocialShare\Provider\Twitter;
use SocialShare\Provider\Google;

require 'vendor/autoload.php';

$cache = new PhpFileCache('/a/cache/directory'); // Use sys_get_temp_dir() to get the system temporary directory, but be aware of the security risk if your website is hosted on a shared server
$socialShare = new SocialShare($cache);

$socialShare->registerProvider(new Facebook());
$socialShare->registerProvider(new Twitter());
$socialShare->registerProvider(new Google());

function social_share_link($providerName, $url, $options = array())
{
    global $socialShare;

    return $socialShare->getLink($providerName, $url, $options);
}

function social_share_shares($providerName, $url)
{
    global $socialShare;

    return $socialShare->getShares($providerName, $url, true);
}

add_action('shutdown', array($socialShare, 'update'), 10000);

if (function_exists('fastcgi_finish_request')) {
    add_action('shutdown', 'fastcgi_finish_request', 1);
}

It loads the library through the Composer autoloading system, initializes a file based cache system (be sure to set a directory writable by your web server)  and loads Facebook, Twitter and Google Plus providers.

If you want to use other social networks such as Pinterest (bundled with SocialShare) or the newly supported LinkedIn, register them here.

Then, we create two helper functions to use in our theme’s templates: social_share_links that returns a share link and social_share_shares that returns the share counter. The last parameter of \SocialShare\SocialShare::getShares() function is set to true. This allows to delay the retrieving of share counts from social network when the \SocialShare\SocialShare::update() method will be called. If a value is already in the cache (how old it is doesn’t matter) it will be used, otherwise 0 will be returned.

Finally, we register the call to the update method on the WordPress’ shutdown hook. Thanks to this tweak, HTTP requests retrieving shares counts from social networks will be issued after the page load. Of course, only the next visitor will see updated counts, but this allows fast pages loading even in the worst case: when the data must be updated from social networks servers.

A last trick: if WordPress is served through PHP FPM (the most performant solution for PHP websites), we take care of the fastcgi_finish_request method. This method (only available when using PHP FPM) allows flushing the buffer and closing the connection to the client before retrieving data from social networks. By default, WordPress flush the response buffer but does not close the connection, even on FPM.

I’ve submitted a patch upstream using this trick to increase performance of all WordPress installations on PHP FPM, so I hope that the last lines of code will become unnecessary soon!

Using the helpers

You can now use the registered helpers in any template. Here is an example to put inside The WordPress Loop (e.g. content.php) to display a link to share the post and it’s number of share on Twitter, Facebook and Google Plus:

        <ul class="entry-social">
            <li><a href="<?php echo social_share_link('facebook', get_permalink()) ?>" rel="nofollow" class="facebook-share"><span class="facebook">Facebook</span> <span class="number"><?php echo social_share_shares('facebook', get_permalink()) ?></span></a></li>
            <li><a href="<?php echo social_share_link('twitter', get_permalink(), array('text' => html_entity_decode(get_the_title()), 'via' => 'dunglas')) ?>" class="twitter-share" rel="nofollow"><span class="twitter">Twitter</span> <span class="number"><?php echo social_share_shares('twitter', get_permalink()) ?></span></a></li>
            <li><a href="<?php echo social_share_link('google', get_permalink()) ?>" class="google-share"><span class="google-plus">Google Plus</span> <span class="number"><?php echo social_share_shares('google', get_permalink()) ?></span></a></li>
        </ul>

Customize the apparence of your social buttons with all the CSS you want!

Introducing the SocialShare PHP library

I’ve released a new PHP library allowing to retrieve the number of shares of URLs on popular social networks. It currently supports Facebook, Twitter, Google Plus / Plus One, Pinterest, LinkedIn and Scoop.it!. This library is also able to generate sharing links for these networks.

The main advantages of this library over traditional JavaScript share buttons are:

  • Speed: counts are retrieved server-side and can be cached through a lot of backends including Memcache, MongoDB and Redis; no JavaScript SDK loading; no HTTP request from your visitor’s browser to social networks
  • Privacy: therefore, no data from your visitors is send to social networks, their privacy is respected
  • Customization: there is no need to use official social networks buttons, you can create beautiful custom buttons displaying the number of shares

This library is installable with Composer, is fully tested with phpSpec, gets a platinum medal on the SensioLabs Insight monitoring system and is compatible with HHVM.

As usual, download it and learn how to use it on GitHub.

Workshop sur le référencement mardi 16 juillet à Lille

Workshop référencement Co-Factory

Mardi prochain, j’animerais un workshop traitant du référencement pour le centre de formation lillois Co-Factory. Ce workshop est destiné à tous ceux qui animent un site internet, un blog, une boutique en ligne… et qui souhaitent découvrir les bases du positionnement dans les moteurs de recherche. Il est destiné aux débutants complets, aucune connaissance préalable n’est nécessaire. Seuls les aspects généraux du référencement seront abordés (pas les aspects techniques plus avancés).

Réservation obligatoire auprès de David (son mail dans l’affiche).

Vous avez créer votre site internet et vous vous demandez comment faire en sorte qu’il soit plus visible ? Vous vous interrogez sur la pertinence de créer des liens avec d’autres sites internet ? Vous vous demandez comment rédiger vos textes pour qu’ils soient bien référencés ? Autant de questions qui seront abordées lors de ce workshop animé par Kévin Dunglas de la Coopérative des Tilleuls.

Diaporama diffusé lors du workshop sur le référencement avec HTML5

Voici le diaporama qui a servi de support au workshop sur le référencement avec HTML5 que j’ai animé jeudi 31 janvier pour La Coopérative des Tilleuls :

Ce sont le thème Prestashop HTML5 optimisé pour le référencement et l’implémentation de TodoMVC avec Symfony et Backbone.js qui ont servi de support.

Le prochain workshop de cette série sera justement dédié à la programmation JavaScript avancée avec Chaplin.js et Backbone.js. Il se déroulera début mars, toujours à Co-Factory.

Workshop HTML5

Workshop gratuit sur le référencement naturel avec HTML5 jeudi 31 janvier à Lille

Worskhop sur le référencement naturel avec HTML5

Jeudi prochain, j’animerais pour La Coopérative des Tilleuls, un atelier gratuit sur l’utilisation des propriétés sémantiques de HTML5 pour améliorer le référencement naturel des sites internet. C’est chez nos amis de Co-Factory que ça se passe (677 avenue de la République, Lille).

Au programme :

  • Introduction au référencement
  • Présentation des balises sémantiques de HTML5
  • Comprendre l’algorithme de « outline » HTML5 pour mettre en valeur l’information pertinente
  • Mettre en avant ses pages dans les moteurs de recherche avec les microdata, Schema.org et les extraits enrichis
  • Allez plus loin, jouer avec Javascript pour référencer des SPA (Single Page Application)

Ce workshop est gratuit et ouvert à tous mais il est impératif de réserver au préalable. Venez !

Un thème Prestashop HTML5 optimisé pour le référencement avec Rich Snippets

Exemple d'extrait enrichi (Rich Snippet) sur Google

Exemple d’extrait enrichi (Rich Snippet) sur Google

Mise à jour : ces fonctionnalités sont maintenant incluses dans le thème par défaut de Prestashop 1.6. Ce thème n’est donc plus maintenu.

J’ai contribué il y’à quelques temps déjà la migration vers HTML5 du thème par défaut de Prestashop, la plateforme e-commerce libre. En attendant l’inclusion de ce patch dans la version upstream je vous propose au téléchargement un thème autonome libre et gratuit compatible avec les versions 1.5 et supérieures de Prestashop.

Il s’agit donc du thème par défaut techniquement optimisé pour un meilleur référencement naturel, plus accessible aux personnes handicapées et avec le support automatique des extraits enrichis affichés dans Google (voir l’illustration plus haut).

Voici la liste détaillée des fonctionnalités ajoutées :

  • Microdata HTML5 Schema.org Offer, Product et Breadcrumb pour afficher des “extraits enrichis” (Rich Snippets) dans Google
  • Nouvelles balises sémantiques HTML5 header, nav, footer et article pour un meilleur référencement (support des anciens navigateurs via Modernizr)
  • Rôles ARIA mainnavigationsearchcomplementarycontentinfo et banner pour rendre le site plus accessible aux personnes souffrant de déficiences visuelles, auditives ou cognitives

Bien sûr cette template est complétement personnalisable, faites pour se charger vite et compatible avec le mode multiboutique et multilingue de Prestashop. C’est une base moderne pour personnaliser l’apparence de sa boutique sans négliger le référencement.

Elf Hostel où le référencement viral efficace

Cet été je me suis dans une auberge de jeunesse de Prague dénommée Elf Hostel dont la stratégie marketing est assez remarquable.

L’hôtel dispose d’un site au design d’un autre âge mais disponible dans de nombreuses langues. Sur ce site il est possible de réserver chambres et lits en ligne et de consulter quelques chaleureux reportages photos et vidéos. On y retrouve également les informations détaillées d’accès au lieu. Bref du très classique pour un hôtel, sans fioritures, juste ce qu’il faut.

Le réferencement naturel du site semble avoir était un peu travaillé (balises meta, titres des pages, …), sans grand succès apparent.

La ou leur démarche devient intéressante, c’est que l’équipe de l’hôtel a mis en place une page Facebook régulièrement mise à jour. A la fin de leur séjour, les clients sont invités à en devenir fan. L’appât : 5% de réduction lors des séjours suivants !

Grâce à ce petit stratagème environ 700 personnes sont “fans” de l’hôtel sur Facebook et les éléments publiés dans le mini-feed sont repris sur de nombreux profils via les commentaires et la fonction “j’aime ça”. Le marketing viral tourne à plein régime, les amis des anciens clients entendent parler en bien de l’hôtel, en découvrent l’ambiance rock’n’roll par ce biais et réservent plutôt la qu’ailleurs.

Encore mieux, ils encouragent les gens à écrire des revues sur les sites dédiés à ça, et la c’est plus de 200 avis qui ont étés rédigés. Les avis des consommateurs comptant pour une part importante dans le classement des résultats sur Google Maps, l’hôtel grimpe en seconde position sur ce dernier… Ces résultats géolocalisés sont repris sous forme de widget en tête de l’index principal de Google. Voilà notre hôtel deuxième sur Google.com avec la requete “Hostel Prague” !

Grâce à cette stratégie, sommes toutes simple à mettre en place, l’hôtel, profite d’une visibilité énorme. Même si la bière de 50cl vendue moins de 1€ et l’ambiance sympa doivent également y être pour quelque chose, il est bondé, et l’écrasante majorité des réservations proviennent du net.

Feedburner: Switching to Google account with MyBrand enabled

Since I’ve migrated my FeedBurner account to Google I encounter a lot of problems, especially with the MyBrand service. MyBrand is a service allowing to use custom domain names with FeedBurner. Instead of something like http://feeds.feedburner.com/lapin-blanc, your feed address become http://feeds.dunglas.fr/lapin-blanc. I’ve already explained why it’s better !

My subdomain for feeds was rss.dunglas.fr. There is no way to get this subdomain working since I’ve switched to Google accounts. I’ve followed the Tim Heuer’s tutorial but the message The domain “rss.dunglas.fr” you specified is already in use. is still displayed when I try to recreate my main custom URL in the MyBrand settings page. I’ve just managed to get my “backup” domain called feeds.dunglas.fr working.

So I’ve created this quick-and-dirty hack:

  1. Set a working MyBrand domain. For me: feeds.dunglas.fr.
  2. Point the DNS entry of your primary feeds domain on your web server. For me me: replace rss 10800 IN CNAME <my-login>.feedproxy.ghs.google.com. by rss 10800 IN CNAME www.
  3. Create a virtual host on your web server to redirect permanently the old addresses to the new one. For me (using Debian GNU/Linux):
    Create a file called /etc/apache2/sites-available/rss.dunglas.fr containing:

    <VirtualHost *>
            ServerName rss.dunglas.fr
    
            RewriteEngine On
            RewriteRule ^(.*) http://feeds.dunglas.fr$1 [L,R=301]
    </VirtualHost>

    Next type in a shell a2ensite rss.dunglas.fr && /etc/init.d/apache2 reload.

  4. Change all occurrences of your old feeds URL to the new in your site to reduce the number of HTTP requests.

Your burned feed must work without losing readers. This a temporary solution, and I think that the only useful long term solution is to go away from FeedBurner