diff --git a/.gitmodules b/.gitmodules
index 28770e46d05930c7f2b342a98e70062be3be85ef..97112d748142dd60fbe08f5eb2cc308e332b60a8 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,6 +1,3 @@
-[submodule "duniter4j-cesium/src/main/cesium"]
-	path = duniter4j-cesium/src/main/cesium
-	url = git://github.com/duniter/cesium.git
 [submodule "duniter4j-elasticsearch/src/main/resources/cities"]
 	path = duniter4j-elasticsearch/src/main/resources/cities
 	url = git://github.com/David-Haim/CountriesToCitiesJSON.git
diff --git a/duniter4j-es-assembly/src/main/assembly/config/elasticsearch.yml b/duniter4j-es-assembly/src/main/assembly/config/elasticsearch.yml
index 46095a0f1a870e4e4400f7a142ea12d25fd12e77..184f1a706f38af1e13b7547098686fc32d0b36d2 100644
--- a/duniter4j-es-assembly/src/main/assembly/config/elasticsearch.yml
+++ b/duniter4j-es-assembly/src/main/assembly/config/elasticsearch.yml
@@ -249,4 +249,19 @@ duniter.subscription.enable: false
 #
 # Email subscription: URL to a Cesium site, for links in the email content (default: https://g1.duniter.fr)
 #
-# duniter.subscription.email.cesium.url: 'http://domain.com/cesium'
\ No newline at end of file
+# duniter.subscription.email.cesium.url: 'http://domain.com/cesium'
+#
+# ---------------------------------- Duniter4j User (profile, message) module -------------------
+#
+#
+# Share link: `og:site_name` (default: 'Cesium')
+#
+# duniter.user.share.site.name: 'Cesium - Ğ1'
+#
+# Share link: `og:url` - URL to a Cesium site, for links in the email content (default: https://g1.duniter.fr)
+#
+# duniter.share.cesium.url: 'https://domain.com/cesium'
+#
+# Share link: Base URL of the ES cluster, to resolve `og:image` URL (default: none => /!\ Will use relative image path)
+#
+# duniter.share.base.url: 'https://data.domain.com'
\ No newline at end of file
diff --git a/duniter4j-es-assembly/src/test/es-home/config/elasticsearch.yml b/duniter4j-es-assembly/src/test/es-home/config/elasticsearch.yml
index cd42a48aef7696c6608cfdeddb046cd5b3e8763a..124f71b8c5443388105ff26fe60d1b987a37dcab 100644
--- a/duniter4j-es-assembly/src/test/es-home/config/elasticsearch.yml
+++ b/duniter4j-es-assembly/src/test/es-home/config/elasticsearch.yml
@@ -251,4 +251,19 @@ duniter.subscription.enable: true
 #
 # Email subscription: URL to a Cesium site, for links in the email content (default: https://g1.duniter.fr)
 #
-#duniter.subscription.email.cesium.url: 'https://domain.com/cesium'
\ No newline at end of file
+#duniter.subscription.email.cesium.url: 'https://domain.com/cesium'
+#
+# ---------------------------------- Duniter4j User (profile, message) module -------------------
+#
+#
+# Share link: og:site_name (default: 'Cesium')
+#
+# duniter.user.share.site.name: 'Cesium - Ğ1'
+#
+# Share link : URL to a Cesium site, for links in the email content (default: https://g1.duniter.fr)
+#
+#duniter.share.cesium.url: 'https://domain.com/cesium'
+#
+# Share link : Base URL of cluster, to resolve image (default: none => /!\ Will use relative image path)
+#
+#duniter.share.base.url: 'http://localhost:9200'
\ No newline at end of file
diff --git a/duniter4j-es-core/pom.xml b/duniter4j-es-core/pom.xml
index a2d3ebe77f40fd014d06a026471b2eb6e76da2e6..4a5ecfd698a69dacfc8b15a0d2ed4a1e495abfc5 100644
--- a/duniter4j-es-core/pom.xml
+++ b/duniter4j-es-core/pom.xml
@@ -76,6 +76,14 @@
       <artifactId>jackson-databind</artifactId>
     </dependency>
 
+
+    <dependency>
+      <groupId>org.antlr</groupId>
+      <artifactId>stringtemplate</artifactId>
+      <version>${stringtemplate.version}</version>
+      <scope>compile</scope>
+    </dependency>
+
     <!-- JNA (need for OS shutdown hook) -->
     <dependency>
       <groupId>net.java.dev.jna</groupId>
diff --git a/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/rest/attachment/RestImageAttachmentAction.java b/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/rest/attachment/RestImageAttachmentAction.java
index f861333dfd6230a9538538c5b4135ebbe8273bbc..e46a5926a10e170d5e51eadbb46875330ee65794 100644
--- a/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/rest/attachment/RestImageAttachmentAction.java
+++ b/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/rest/attachment/RestImageAttachmentAction.java
@@ -95,4 +95,17 @@ public class RestImageAttachmentAction extends BaseRestHandler {
             }
         });
     }
+
+
+    public static String computeImageUrl(String index,
+                                         String type,
+                                         String id,
+                                         String imageField,
+                                         String contentType) {
+
+        int lastSlashIndex = contentType  != null ? contentType.lastIndexOf('/') : -1;
+        String extension = (lastSlashIndex >= 0) ? contentType.substring(lastSlashIndex+1) : contentType;
+
+        return String.format("/%s/%s/%s/_image/%s.%s", index, type, id, imageField, extension);
+    }
 }
\ No newline at end of file
diff --git a/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/rest/share/AbstractRestShareLinkAction.java b/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/rest/share/AbstractRestShareLinkAction.java
new file mode 100644
index 0000000000000000000000000000000000000000..ff97fada10df8a93d416f847e86196295e3c881b
--- /dev/null
+++ b/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/rest/share/AbstractRestShareLinkAction.java
@@ -0,0 +1,91 @@
+package org.duniter.elasticsearch.rest.share;
+
+import org.apache.http.entity.ContentType;
+import org.duniter.core.exception.BusinessException;
+import org.duniter.core.util.Preconditions;
+import org.duniter.core.util.StringUtils;
+import org.duniter.elasticsearch.exception.DuniterElasticsearchException;
+import org.duniter.elasticsearch.rest.XContentThrowableRestResponse;
+import org.duniter.elasticsearch.util.opengraph.OGData;
+import org.duniter.elasticsearch.util.springtemplate.STUtils;
+import org.elasticsearch.client.Client;
+import org.elasticsearch.common.logging.ESLogger;
+import org.elasticsearch.common.logging.Loggers;
+import org.elasticsearch.common.settings.Settings;
+import org.elasticsearch.rest.*;
+import org.nuiton.i18n.I18n;
+import org.stringtemplate.v4.*;
+
+import java.util.Locale;
+
+import static org.elasticsearch.rest.RestRequest.Method.GET;
+import static org.elasticsearch.rest.RestStatus.OK;
+
+public abstract class AbstractRestShareLinkAction extends BaseRestHandler {
+
+    protected final ESLogger log;
+
+    public interface OGDataResolver {
+        OGData resolve(String id) throws DuniterElasticsearchException, BusinessException;
+    }
+
+    private OGDataResolver resolver;
+    private STGroup templates;
+
+    public AbstractRestShareLinkAction(Settings settings, RestController controller, Client client,
+                                       String indexName,
+                                       String typeName,
+                                       OGDataResolver resolver
+                                        ) {
+        super(settings, controller, client);
+        log = Loggers.getLogger("duniter.rest." + indexName, settings, String.format("[%s]", indexName));
+        controller.registerHandler(GET,
+                String.format("/%s/%s/{id}/_share", indexName, typeName),
+                this);
+        this.resolver = resolver;
+
+        // Configure springtemplate engine
+        this.templates = STUtils.newSTGroup("org/duniter/elasticsearch/templates");
+        Preconditions.checkNotNull(this.templates.getInstanceOf("html_share"), "Unable to load ST template for share page");
+
+    }
+
+    @Override
+    protected void handleRequest(final RestRequest request, RestChannel restChannel, Client client) throws Exception {
+        String id = request.param("id");
+
+        try {
+
+            OGData data = resolver.resolve(id);
+            Preconditions.checkNotNull(data);
+            Preconditions.checkNotNull(data.title);
+
+            // Compute HTML content
+            ST template = templates.getInstanceOf("html_share");
+            template.add("type", data.type);
+            template.add("title", data.title);
+            template.add("summary", StringUtils.truncate(data.description, 500));
+            template.add("description", data.description);
+            template.add("siteName", data.siteName);
+            template.add("image", data.image);
+            template.add("url", data.url);
+            template.add("locale", data.locale);
+            if (StringUtils.isNotBlank(data.url)) {
+                Locale locale = data.locale != null ? new Locale(data.locale) : I18n.getDefaultLocale();
+                template.add("redirectMessage", I18n.l(locale, "duniter4j.share.redirection.help"));
+            }
+
+            String html = template.render();
+
+            restChannel.sendResponse(new BytesRestResponse(OK, ContentType.TEXT_HTML.getMimeType(), html));
+        }
+        catch(DuniterElasticsearchException | BusinessException e) {
+            log.error(e.getMessage(), e);
+            restChannel.sendResponse(new XContentThrowableRestResponse(request, e));
+        }
+        catch(Exception e) {
+            log.error(e.getMessage(), e);
+        }
+    }
+
+}
diff --git a/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/util/opengraph/OGData.java b/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/util/opengraph/OGData.java
new file mode 100644
index 0000000000000000000000000000000000000000..0530ead6288cd913cacb01fc7fc11883688e864b
--- /dev/null
+++ b/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/util/opengraph/OGData.java
@@ -0,0 +1,13 @@
+package org.duniter.elasticsearch.util.opengraph;
+
+public class OGData {
+    public String type;
+    public String title;
+    public String description;
+    public String image;
+    public String url;
+    public String locale;
+    public String imageType;
+    public String siteName;
+
+}
diff --git a/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/util/springtemplate/DateRenderer.java b/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/util/springtemplate/DateRenderer.java
new file mode 100644
index 0000000000000000000000000000000000000000..507fd6169aa0a88bfac49f54f0117eb58e2bf46a
--- /dev/null
+++ b/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/util/springtemplate/DateRenderer.java
@@ -0,0 +1,67 @@
+package org.duniter.elasticsearch.util.springtemplate;
+
+/*-
+ * #%L
+ * Duniter4j :: ElasticSearch Subscription plugin
+ * %%
+ * Copyright (C) 2014 - 2017 EIS
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public
+ * License along with this program.  If not, see
+ * <http://www.gnu.org/licenses/gpl-3.0.html>.
+ * #L%
+ */
+
+import org.stringtemplate.v4.AttributeRenderer;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.Locale;
+
+public class DateRenderer implements AttributeRenderer {
+
+    public DateRenderer() {
+    }
+
+    public String toString(Object o, String formatString, Locale locale) {
+        if(formatString == null) {
+            formatString = "short";
+        }
+
+        Date d;
+        if(o instanceof Calendar) {
+            d = ((Calendar)o).getTime();
+        } else {
+            d = (Date)o;
+        }
+
+        Integer styleI = (Integer)org.stringtemplate.v4.DateRenderer.formatToInt.get(formatString);
+        Object f;
+        if(styleI == null) {
+            f = new SimpleDateFormat(formatString, locale);
+        } else {
+            int style = styleI.intValue();
+            if(formatString.startsWith("date:")) {
+                f = DateFormat.getDateInstance(style, locale);
+            } else if(formatString.startsWith("time:")) {
+                f = DateFormat.getTimeInstance(style, locale);
+            } else {
+                f = DateFormat.getDateTimeInstance(style, style, locale);
+            }
+        }
+
+        return ((DateFormat)f).format(d);
+    }
+}
\ No newline at end of file
diff --git a/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/util/springtemplate/STUtils.java b/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/util/springtemplate/STUtils.java
new file mode 100644
index 0000000000000000000000000000000000000000..cd0cb61b9f40bc0a38a92d411daa633c35253073
--- /dev/null
+++ b/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/util/springtemplate/STUtils.java
@@ -0,0 +1,25 @@
+package org.duniter.elasticsearch.util.springtemplate;
+
+import org.stringtemplate.v4.DateRenderer;
+import org.stringtemplate.v4.STGroup;
+import org.stringtemplate.v4.STGroupDir;
+import org.stringtemplate.v4.StringRenderer;
+
+import java.util.Date;
+
+public class STUtils {
+
+    private STUtils() {
+        /*help class*/
+    }
+
+    public static STGroup newSTGroup(String dirName) {
+        // Configure springtemplate engine
+        STGroup templates = new STGroupDir(dirName, '$', '$');
+        templates.registerRenderer(Date.class, new DateRenderer());
+        templates.registerRenderer(String.class, new StringRenderer());
+        return templates;
+    }
+
+
+}
diff --git a/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/util/springtemplate/StringRenderer.java b/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/util/springtemplate/StringRenderer.java
new file mode 100644
index 0000000000000000000000000000000000000000..01e3ac3e5ebfcbaf053a22c9efed87f7250854c7
--- /dev/null
+++ b/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/util/springtemplate/StringRenderer.java
@@ -0,0 +1,52 @@
+package org.duniter.elasticsearch.util.springtemplate;
+
+/*-
+ * #%L
+ * Duniter4j :: ElasticSearch Subscription plugin
+ * %%
+ * Copyright (C) 2014 - 2017 EIS
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public
+ * License along with this program.  If not, see
+ * <http://www.gnu.org/licenses/gpl-3.0.html>.
+ * #L%
+ */
+
+import org.duniter.core.client.model.ModelUtils;
+import org.duniter.core.util.CollectionUtils;
+import org.nuiton.i18n.I18n;
+
+import java.util.Locale;
+
+/**
+ * Add format capabilities: i18n, pubkey
+ * Created by blavenie on 10/04/17.
+ */
+public class StringRenderer extends org.stringtemplate.v4.StringRenderer{
+
+    @Override
+    public String toString(Object o, String formatString, Locale locale) {
+        return formatString == null ? (String)o :
+                (formatString.equals("pubkey") ? ModelUtils.minifyPubkey((String)o) :
+                        (formatString.startsWith("i18n") ? toI18nString(o, formatString, locale) :
+                            super.toString(o, formatString, locale)));
+    }
+
+    protected String toI18nString(Object key, String formatString, Locale locale) {
+        String[] params = formatString.startsWith("i18n:") ? formatString.substring(5).split(",") : null;
+        if (CollectionUtils.isNotEmpty(params)) {
+            return I18n.l(locale, key.toString(), params);
+        }
+        return I18n.l(locale, key.toString());
+    }
+}
diff --git a/duniter4j-es-core/src/main/resources/i18n/duniter4j-es-core_en_GB.properties b/duniter4j-es-core/src/main/resources/i18n/duniter4j-es-core_en_GB.properties
index 4ada9bb98edcc894fcc032a9291ca10215d21b6d..9a1bb01daa4734bbaf2aff4f6a3c15a5847620e3 100644
--- a/duniter4j-es-core/src/main/resources/i18n/duniter4j-es-core_en_GB.properties
+++ b/duniter4j-es-core/src/main/resources/i18n/duniter4j-es-core_en_GB.properties
@@ -47,6 +47,7 @@ duniter4j.job.stopped=
 duniter4j.job.stopping=
 duniter4j.job.success=
 duniter4j.service.waitThenRetry=Error [%s]... will retry [%s/%s]
+duniter4j.share.redirection.help=If you are not redirected automatically, follow this link\:
 duniter4j.task.issuer.system=System
 duniter4j.task.starting=Starting task...
 duniter4j.threadPool.clusterHealthStatus.changed=Cluster health status changed to [%s]
diff --git a/duniter4j-es-core/src/main/resources/i18n/duniter4j-es-core_fr_FR.properties b/duniter4j-es-core/src/main/resources/i18n/duniter4j-es-core_fr_FR.properties
index a2854149be7a599f50ed4b957d98b93c52e422dd..43a57823caeaca108c0a12c4a9d9f8cb79baa43a 100644
--- a/duniter4j-es-core/src/main/resources/i18n/duniter4j-es-core_fr_FR.properties
+++ b/duniter4j-es-core/src/main/resources/i18n/duniter4j-es-core_fr_FR.properties
@@ -49,6 +49,7 @@ duniter4j.job.stopped=
 duniter4j.job.stopping=
 duniter4j.job.success=
 duniter4j.service.waitThenRetry=Echec [%s]... tentative [%s/%s]
+duniter4j.share.redirection.help=Si vous n'êtes pas redirigé automatiquement, cliquez sur le lien suivant \:
 duniter4j.task.issuer.system=Système
 duniter4j.task.starting=Démarrage du traitement...
 duniter4j.threadPool.clusterHealthStatus.changed=Cluster health status changed to [%s]
diff --git a/duniter4j-es-subscription/src/main/resources/templates/cesium_logo.st b/duniter4j-es-core/src/main/resources/org/duniter/elasticsearch/templates/cesium_logo.st
similarity index 100%
rename from duniter4j-es-subscription/src/main/resources/templates/cesium_logo.st
rename to duniter4j-es-core/src/main/resources/org/duniter/elasticsearch/templates/cesium_logo.st
diff --git a/duniter4j-es-core/src/main/resources/org/duniter/elasticsearch/templates/html_share.st b/duniter4j-es-core/src/main/resources/org/duniter/elasticsearch/templates/html_share.st
new file mode 100644
index 0000000000000000000000000000000000000000..664245e3511d95a8b6d5d74c8825c691e38b178d
--- /dev/null
+++ b/duniter4j-es-core/src/main/resources/org/duniter/elasticsearch/templates/html_share.st
@@ -0,0 +1,64 @@
+html_share(type, title, summary, description, image, siteName, locale, url, redirectMessage) ::= <<
+<html prefix="og: http://ogp.me/ns#">
+    <head>
+        <meta charset="UTF-8">
+
+    $if(siteName)$
+        <title>$siteName$ | $title$</title>
+    $else$
+        <title>$title$</title>
+    $endif$
+
+    $if(type)$
+        <meta property="og:type" content="$type$" />
+    $else$
+        <meta property="og:type" content="website" />
+    $endif$
+
+        <meta property="og:title" content="$title$" />
+
+    $if(summary)$
+        <meta property="og:description" content="$summary$" />
+    $else$
+        <meta property="og:description" content="$description$" />
+    $endif$
+
+    $if(siteName)$
+        <meta property="og:site_name" content="$siteName$" />
+    $endif$
+
+    $if(image)$
+        <meta property="og:image" content="$image$" />
+    $endif$
+
+    $if(locale)$
+        <meta property="og:locale" content="$locale$" />
+    $endif$
+
+    $if(url)$
+        <meta property="og:url" content="$url$" />
+        <script type="text/javascript">
+            window.location.href = "$url$"
+        </script>
+        <META HTTP-EQUIV="Refresh" CONTENT="0; URL=$url$">
+    $endif$
+    </head>
+    <body>
+        $if(image)$
+        <p>
+            <img src="$image$"/>
+        </p>
+        $endif$
+
+        <h1>$title$</h1>
+
+        <p>$description$</p>
+
+        $if(url)$
+        <p>
+            $redirectMessage$ <a href='$url$'>$title$</a>.
+        </p>
+        $endif$
+    </body>
+</html>
+>>
diff --git a/duniter4j-es-subscription/pom.xml b/duniter4j-es-subscription/pom.xml
index c9beba4083d42dc7e961e6f0883ef92419a51fd9..c2ccb92692bfefbb8cd6eac45c731daf224d0934 100644
--- a/duniter4j-es-subscription/pom.xml
+++ b/duniter4j-es-subscription/pom.xml
@@ -46,7 +46,7 @@
       <groupId>org.antlr</groupId>
       <artifactId>stringtemplate</artifactId>
       <version>${stringtemplate.version}</version>
-      <scope>compile</scope>
+      <scope>provided</scope>
     </dependency>
 
     <!-- Unit test -->
diff --git a/duniter4j-es-subscription/src/main/java/org/duniter/elasticsearch/subscription/service/SubscriptionService.java b/duniter4j-es-subscription/src/main/java/org/duniter/elasticsearch/subscription/service/SubscriptionService.java
index 871c8863dfa34d6654879fae2f3508fa16b4dc30..5f93f052166cc1abf1767bf27afacf380c409d42 100644
--- a/duniter4j-es-subscription/src/main/java/org/duniter/elasticsearch/subscription/service/SubscriptionService.java
+++ b/duniter4j-es-subscription/src/main/java/org/duniter/elasticsearch/subscription/service/SubscriptionService.java
@@ -51,6 +51,7 @@ import org.duniter.elasticsearch.user.service.AdminService;
 import org.duniter.elasticsearch.user.service.MailService;
 import org.duniter.elasticsearch.user.service.UserEventService;
 import org.duniter.elasticsearch.user.service.UserService;
+import org.duniter.elasticsearch.util.springtemplate.STUtils;
 import org.elasticsearch.common.inject.Inject;
 import org.elasticsearch.common.unit.TimeValue;
 import org.nuiton.i18n.I18n;
@@ -76,6 +77,7 @@ public class SubscriptionService extends AbstractService {
     private UserEventService userEventService;
     private UserService userService;
     private String emailSubjectPrefix;
+    private STGroup templates;
 
     @Inject
     public SubscriptionService(Duniter4jClient client,
@@ -100,6 +102,11 @@ public class SubscriptionService extends AbstractService {
         if (StringUtils.isNotBlank(emailSubjectPrefix)) {
             emailSubjectPrefix += " "; // add one trailing space
         }
+
+        // Configure springtemplate engine
+        templates = STUtils.newSTGroup("org/duniter/elasticsearch/subscription/templates");
+        Preconditions.checkNotNull(templates.getInstanceOf("text_email"), "Missing ST template {text_email}");
+        Preconditions.checkNotNull(templates.getInstanceOf("html_email_content"), "Missing ST template {html_email_content}");
     }
 
     public String create(String json) {
@@ -308,11 +315,7 @@ public class SubscriptionService extends AbstractService {
                 subscription.getContent().getLocale().split("-") : new String[]{"en", "GB"};
         Locale issuerLocale = localParts.length >= 2 ? new Locale(localParts[0].toLowerCase(), localParts[1].toUpperCase()) : new Locale(localParts[0].toLowerCase());
 
-        // Configure templates engine
-        STGroup templates = new STGroupDir("templates", '$', '$');
-        templates.registerRenderer(Date.class, new DateRenderer());
-        templates.registerRenderer(String.class, new StringRenderer());
-        //templates.registerRenderer(Number.class, new NumberRenderer());
+
 
         // Compute text content
         final String text = fillTemplate(
diff --git a/duniter4j-es-subscription/src/main/resources/org/duniter/elasticsearch/subscription/templates/cesium_logo.st b/duniter4j-es-subscription/src/main/resources/org/duniter/elasticsearch/subscription/templates/cesium_logo.st
new file mode 100644
index 0000000000000000000000000000000000000000..83cf445c1c6d63f4dfb4612f81a06253aff3769b
--- /dev/null
+++ b/duniter4j-es-subscription/src/main/resources/org/duniter/elasticsearch/subscription/templates/cesium_logo.st
@@ -0,0 +1,6 @@
+cesium_logo(url, data) ::= <<
+$if(data)$<img height="144" width="144" src="data:image/png;base64,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">
+$else$
+<img height="144" width="144" src="$url$/img/logo_128px.png">
+$endif$
+>>
\ No newline at end of file
diff --git a/duniter4j-es-subscription/src/main/resources/templates/css.st b/duniter4j-es-subscription/src/main/resources/org/duniter/elasticsearch/subscription/templates/css.st
similarity index 100%
rename from duniter4j-es-subscription/src/main/resources/templates/css.st
rename to duniter4j-es-subscription/src/main/resources/org/duniter/elasticsearch/subscription/templates/css.st
diff --git a/duniter4j-es-subscription/src/main/resources/templates/css_logo.st b/duniter4j-es-subscription/src/main/resources/org/duniter/elasticsearch/subscription/templates/css_logo.st
similarity index 100%
rename from duniter4j-es-subscription/src/main/resources/templates/css_logo.st
rename to duniter4j-es-subscription/src/main/resources/org/duniter/elasticsearch/subscription/templates/css_logo.st
diff --git a/duniter4j-es-subscription/src/main/resources/templates/event_item.st b/duniter4j-es-subscription/src/main/resources/org/duniter/elasticsearch/subscription/templates/event_item.st
similarity index 100%
rename from duniter4j-es-subscription/src/main/resources/templates/event_item.st
rename to duniter4j-es-subscription/src/main/resources/org/duniter/elasticsearch/subscription/templates/event_item.st
diff --git a/duniter4j-es-subscription/src/main/resources/templates/html.st b/duniter4j-es-subscription/src/main/resources/org/duniter/elasticsearch/subscription/templates/html.st
similarity index 100%
rename from duniter4j-es-subscription/src/main/resources/templates/html.st
rename to duniter4j-es-subscription/src/main/resources/org/duniter/elasticsearch/subscription/templates/html.st
diff --git a/duniter4j-es-subscription/src/main/resources/templates/html_email_content.st b/duniter4j-es-subscription/src/main/resources/org/duniter/elasticsearch/subscription/templates/html_email_content.st
similarity index 100%
rename from duniter4j-es-subscription/src/main/resources/templates/html_email_content.st
rename to duniter4j-es-subscription/src/main/resources/org/duniter/elasticsearch/subscription/templates/html_email_content.st
diff --git a/duniter4j-es-subscription/src/main/resources/templates/html_event_item.st b/duniter4j-es-subscription/src/main/resources/org/duniter/elasticsearch/subscription/templates/html_event_item.st
similarity index 100%
rename from duniter4j-es-subscription/src/main/resources/templates/html_event_item.st
rename to duniter4j-es-subscription/src/main/resources/org/duniter/elasticsearch/subscription/templates/html_event_item.st
diff --git a/duniter4j-es-subscription/src/main/resources/templates/i18n.st b/duniter4j-es-subscription/src/main/resources/org/duniter/elasticsearch/subscription/templates/i18n.st
similarity index 100%
rename from duniter4j-es-subscription/src/main/resources/templates/i18n.st
rename to duniter4j-es-subscription/src/main/resources/org/duniter/elasticsearch/subscription/templates/i18n.st
diff --git a/duniter4j-es-subscription/src/main/resources/templates/i18n_args.st b/duniter4j-es-subscription/src/main/resources/org/duniter/elasticsearch/subscription/templates/i18n_args.st
similarity index 100%
rename from duniter4j-es-subscription/src/main/resources/templates/i18n_args.st
rename to duniter4j-es-subscription/src/main/resources/org/duniter/elasticsearch/subscription/templates/i18n_args.st
diff --git a/duniter4j-es-subscription/src/main/resources/templates/text_email.st b/duniter4j-es-subscription/src/main/resources/org/duniter/elasticsearch/subscription/templates/text_email.st
similarity index 100%
rename from duniter4j-es-subscription/src/main/resources/templates/text_email.st
rename to duniter4j-es-subscription/src/main/resources/org/duniter/elasticsearch/subscription/templates/text_email.st
diff --git a/duniter4j-es-subscription/src/main/resources/templates/text_event_item.st b/duniter4j-es-subscription/src/main/resources/org/duniter/elasticsearch/subscription/templates/text_event_item.st
similarity index 100%
rename from duniter4j-es-subscription/src/main/resources/templates/text_event_item.st
rename to duniter4j-es-subscription/src/main/resources/org/duniter/elasticsearch/subscription/templates/text_event_item.st
diff --git a/duniter4j-es-subscription/src/main/resources/plugin-security.policy b/duniter4j-es-subscription/src/main/resources/plugin-security.policy
index 3ea59400b9bd2a3d0e1b89091169fa50b60e1123..ea5437f6726c44547a1dce7470385fc69c055e22 100644
--- a/duniter4j-es-subscription/src/main/resources/plugin-security.policy
+++ b/duniter4j-es-subscription/src/main/resources/plugin-security.policy
@@ -1,4 +1,4 @@
-grant codeBase "file:${es.path.home}/plugins/duniter4j-es-gchange/"{
+grant codeBase "file:${es.path.home}/plugins/duniter4j-es-subscription/"{
   permission java.io.FilePermission "/etc/ld.so.conf", "read";
   permission java.io.FilePermission "/etc/ld.so.conf.d/*.conf", "read";
   permission java.io.FilePermission "/usr/local/lib/*", "read";
diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/PluginSettings.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/PluginSettings.java
index 00601581814e13aeab27fcdb714404e86418a8f7..e640a389057facdda36a00115d2cbe8fbc794f7a 100644
--- a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/PluginSettings.java
+++ b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/PluginSettings.java
@@ -212,8 +212,17 @@ public class PluginSettings extends AbstractLifecycleComponent<PluginSettings> {
         return this.nodePubkey;
     }
 
+    public String getCesiumUrl() {
+        return this.settings.get("duniter.share.cesium.url", "https://g1.duniter.fr");
+    }
 
+    public String getShareSiteName() {
+        return this.settings.get("duniter.user.share.site.name", "Cesium");
+    }
 
+    public String getBaseUrl() {
+        return settings.get("duniter.share.base.url");
+    }
 
     /* -- protected methods -- */
 
diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/model/Attachment.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/model/Attachment.java
new file mode 100644
index 0000000000000000000000000000000000000000..3073c805f247a62e2eb6a0c1c8d2f62cda28178b
--- /dev/null
+++ b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/model/Attachment.java
@@ -0,0 +1,63 @@
+package org.duniter.elasticsearch.user.model;
+
+/*
+ * #%L
+ * Duniter4j :: Core Client API
+ * %%
+ * Copyright (C) 2014 - 2016 EIS
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the 
+ * License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public 
+ * License along with this program.  If not, see
+ * <http://www.gnu.org/licenses/gpl-3.0.html>.
+ * #L%
+ */
+
+import com.fasterxml.jackson.annotation.JsonGetter;
+import com.fasterxml.jackson.annotation.JsonSetter;
+import org.duniter.core.client.model.elasticsearch.Record;
+
+/**
+ * Created by blavenie on 01/03/16.
+ */
+public class Attachment extends Record {
+
+    public static final String JSON_PROPERTY_CONTENT_TYPE = "_content_type";
+    public static final String JSON_PROPERTY_CONTENT  = "_content";
+
+    public static final String PROPERTY_CONTENT_TYPE = "contentType";
+    public static final String PROPERTY_CONTENT = "content";
+
+    private String contentType;
+
+    private String content;
+
+    @JsonSetter(JSON_PROPERTY_CONTENT_TYPE)
+    public void setContentType(String contentType) {
+        this.contentType = contentType;
+    }
+
+    @JsonGetter(JSON_PROPERTY_CONTENT_TYPE)
+    public String getContentType() {
+        return contentType;
+    }
+
+    @JsonGetter(JSON_PROPERTY_CONTENT)
+    public String getContent() {
+        return content;
+    }
+
+    @JsonSetter(JSON_PROPERTY_CONTENT)
+    public void setContent(String content) {
+        this.content = content;
+    }
+}
diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/model/UserProfile.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/model/UserProfile.java
index 6ef6ecb0cc217f821fb3399e98370fbc4f8f8371..99c94b55a8ae38bad94d70b3ec0ea852565ec625 100644
--- a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/model/UserProfile.java
+++ b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/model/UserProfile.java
@@ -43,6 +43,7 @@ public class UserProfile extends Record {
     private String locale;
     private String address;
     private String city;
+    private Attachment avatar;
 
     public String getTitle() {
         return title;
@@ -91,4 +92,12 @@ public class UserProfile extends Record {
     public void setCity(String city) {
         this.city = city;
     }
+
+    public Attachment getAvatar() {
+        return avatar;
+    }
+
+    public void setAvatar(Attachment avatar) {
+        this.avatar = avatar;
+    }
 }
diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/RestModule.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/RestModule.java
index 1422b77c0aac986165ae788fa60932df524ed010..fd91b23d0607055b152d9848d1e520c408abadba 100644
--- a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/RestModule.java
+++ b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/RestModule.java
@@ -50,6 +50,7 @@ public class RestModule extends AbstractModule implements Module {
         bind(RestUserEventMarkAsReadAction.class).asEagerSingleton();
         bind(RestUserEventSearchAction.class).asEagerSingleton();
         bind(RestUserAvatarAction.class).asEagerSingleton();
+        bind(RestUserShareLinkAction.class).asEagerSingleton();
 
         // Group
         bind(RestGroupIndexAction.class).asEagerSingleton();
@@ -76,6 +77,7 @@ public class RestModule extends AbstractModule implements Module {
         bind(RestPageCommentUpdateAction.class).asEagerSingleton();
         bind(RestPageCategoryAction.class).asEagerSingleton();
         bind(RestPageImageAction.class).asEagerSingleton();
+        bind(RestPageShareLinkAction.class).asEagerSingleton();
 
         // Mixed search
         bind(RestMixedSearchAction.class).asEagerSingleton();
diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/page/RestPageShareLinkAction.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/page/RestPageShareLinkAction.java
new file mode 100644
index 0000000000000000000000000000000000000000..ecd1c817499ab22f60f370ff4ba7e231ba7da755
--- /dev/null
+++ b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/page/RestPageShareLinkAction.java
@@ -0,0 +1,108 @@
+package org.duniter.elasticsearch.user.rest.page;
+
+import com.google.common.html.HtmlEscapers;
+import org.duniter.core.exception.BusinessException;
+import org.duniter.core.exception.TechnicalException;
+import org.duniter.core.util.StringUtils;
+import org.duniter.elasticsearch.exception.DuniterElasticsearchException;
+import org.duniter.elasticsearch.rest.attachment.RestImageAttachmentAction;
+import org.duniter.elasticsearch.rest.share.AbstractRestShareLinkAction;
+import org.duniter.elasticsearch.user.PluginSettings;
+import org.duniter.elasticsearch.user.dao.page.PageIndexDao;
+import org.duniter.elasticsearch.user.dao.page.PageRecordDao;
+import org.duniter.elasticsearch.user.model.UserProfile;
+import org.duniter.elasticsearch.user.model.page.RegistryRecord;
+import org.duniter.elasticsearch.user.service.PageService;
+import org.duniter.elasticsearch.user.service.UserService;
+import org.duniter.elasticsearch.util.opengraph.OGData;
+import org.elasticsearch.client.Client;
+import org.elasticsearch.common.inject.Inject;
+import org.elasticsearch.common.settings.Settings;
+import org.elasticsearch.rest.RestController;
+import org.nuiton.i18n.I18n;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.util.Locale;
+
+public class RestPageShareLinkAction extends AbstractRestShareLinkAction {
+
+    @Inject
+    public RestPageShareLinkAction(final Settings settings, final RestController controller, final Client client,
+                                   final PluginSettings pluginSettings,
+                                   final PageService service) {
+        super(settings, controller, client, PageIndexDao.INDEX, PageRecordDao.TYPE,
+                createResolver(pluginSettings, service));
+    }
+
+    protected static OGDataResolver createResolver(
+            final PluginSettings pluginSettings,
+            final PageService service) throws DuniterElasticsearchException, BusinessException {
+
+        return (id) -> {
+            try {
+                RegistryRecord record = service.getPageForSharing(id);
+
+                OGData data = new OGData();
+
+                if (record != null) {
+
+                    // og:title
+                    if (StringUtils.isNotBlank(record.getTitle())) {
+                        data.title = record.getTitle();
+                    }
+                    else {
+                        data.title = pluginSettings.getShareSiteName();
+                    }
+
+                    // og:description
+                    data.description = HtmlEscapers.htmlEscaper().escape(record.getDescription());
+
+                    // og:image
+                    if (record.getThumbnail() != null && StringUtils.isNotBlank(record.getThumbnail().get("_content_type"))) {
+                        String baseUrl = pluginSettings.getBaseUrl();
+                        data.image = StringUtils.isBlank(baseUrl) ? "" : baseUrl;
+                        data.image += RestImageAttachmentAction.computeImageUrl(PageIndexDao.INDEX, PageRecordDao.TYPE, id, RegistryRecord.PROPERTY_THUMBNAIL, record.getThumbnail().get("_content_type"));
+                    }
+
+                    // og:url
+                    data.url = String.format("%s/#/app/page/view/%s/%s",
+                            pluginSettings.getCesiumUrl(),
+                            id,
+                            URLEncoder.encode(record.getTitle(), "UTF-8"));
+                }
+                else {
+
+                    // og:title
+                    data.title = pluginSettings.getShareSiteName();
+
+                    // og:description
+                    data.description = I18n.t("duniter.user.share.description");
+
+                    // og:url
+                    data.url = String.format("%s/#/app/page/view/%s/%s",
+                            pluginSettings.getCesiumUrl(),
+                            id,
+                            "");
+                }
+
+                // og:type
+                data.type = "website";
+
+                // og:site_name
+                data.siteName = pluginSettings.getShareSiteName();
+
+                // default og:image
+                if (StringUtils.isBlank(data.image)) {
+                    data.image = pluginSettings.getCesiumUrl() + "/img/logo_128px.png";
+                    data.imageType = "image/png";
+                }
+
+                return data;
+            }
+            catch(UnsupportedEncodingException e) {
+                throw new TechnicalException(e);
+            }
+        };
+    }
+}
diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/user/RestUserShareLinkAction.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/user/RestUserShareLinkAction.java
new file mode 100644
index 0000000000000000000000000000000000000000..540e6e4e0fcdf07c324b0b6a248d078763e7b2c2
--- /dev/null
+++ b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/rest/user/RestUserShareLinkAction.java
@@ -0,0 +1,130 @@
+package org.duniter.elasticsearch.user.rest.user;
+
+import com.google.common.collect.Maps;
+import com.google.common.html.HtmlEscapers;
+import org.duniter.core.exception.BusinessException;
+import org.duniter.core.exception.TechnicalException;
+import org.duniter.core.util.StringUtils;
+import org.duniter.elasticsearch.exception.DuniterElasticsearchException;
+import org.duniter.elasticsearch.rest.attachment.RestImageAttachmentAction;
+import org.duniter.elasticsearch.rest.share.AbstractRestShareLinkAction;
+import org.duniter.elasticsearch.user.PluginSettings;
+import org.duniter.elasticsearch.user.model.UserProfile;
+import org.duniter.elasticsearch.user.service.UserService;
+import org.duniter.elasticsearch.util.opengraph.OGData;
+import org.elasticsearch.client.Client;
+import org.elasticsearch.common.inject.Inject;
+import org.elasticsearch.common.settings.Settings;
+import org.elasticsearch.rest.RestController;
+import org.nuiton.i18n.I18n;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.util.Locale;
+
+public class RestUserShareLinkAction extends AbstractRestShareLinkAction {
+
+    @Inject
+    public RestUserShareLinkAction(final Settings settings, final RestController controller, final Client client,
+                                   final PluginSettings pluginSettings,
+                                   final UserService userService) {
+        super(settings, controller, client, UserService.INDEX, UserService.PROFILE_TYPE,
+                createResolver(pluginSettings, userService));
+
+        if (StringUtils.isBlank(pluginSettings.getBaseUrl())) {
+            log.warn(I18n.t("duniter4j.es.share.error.noBaseUrl", "duniter.share.base.url"));
+        }
+    }
+
+    protected static AbstractRestShareLinkAction.OGDataResolver createResolver(
+            final PluginSettings pluginSettings,
+            final UserService userService) throws DuniterElasticsearchException, BusinessException {
+
+        return (id) -> {
+            try {
+                UserProfile profile = userService.getUserProfileForSharing(id);
+
+                OGData data = new OGData();
+
+                if (profile != null) {
+
+                    // og:locale
+                    Locale locale;
+                    if (StringUtils.isNotBlank(profile.getLocale())) {
+                        locale = new Locale(profile.getLocale());
+                        data.locale = profile.getLocale();
+                    }
+                    else {
+                        locale = I18n.getDefaultLocale();
+                    }
+
+                    String pubkey = I18n.l(locale, "duniter.user.share.pubkey", id);
+
+                    // og:title
+                    if (StringUtils.isNotBlank(profile.getTitle())) {
+                        data.title = profile.getTitle();
+                        data.description = pubkey;
+                    }
+                    else {
+                        data.title = pubkey;
+                        data.description = "";
+                    }
+
+                    // og:description
+                    if (StringUtils.isNotBlank(data.description)) data.description += " | ";
+                    if (StringUtils.isNotBlank(profile.getDescription())) {
+                        data.description += HtmlEscapers.htmlEscaper().escape(profile.getDescription());
+                    }
+                    else {
+                        data.description += I18n.l(locale, "duniter.user.share.description");
+                    }
+
+                    // og:image
+                    if (profile.getAvatar() != null && StringUtils.isNotBlank(profile.getAvatar().getContentType())) {
+                        String baseUrl = pluginSettings.getBaseUrl();
+                        data.image = StringUtils.isBlank(baseUrl) ? "" : baseUrl;
+                        data.image += RestImageAttachmentAction.computeImageUrl(UserService.INDEX, UserService.PROFILE_TYPE, id, UserProfile.PROPERTY_AVATAR, profile.getAvatar().getContentType());
+                    }
+
+                    // og:url
+                    data.url = String.format("%s/#/app/wot/%s/%s",
+                            pluginSettings.getCesiumUrl(),
+                            id,
+                            URLEncoder.encode(profile.getTitle(), "UTF-8"));
+                }
+                else {
+
+                    // og:title
+                    String pubkey = I18n.t("duniter.user.share.pubkey", id);
+                    data.title = pubkey;
+
+                    // og:description
+                    data.description = I18n.t("duniter.user.share.description");
+
+                    // og:url
+                    data.url = String.format("%s/#/app/wot/%s/%s",
+                            pluginSettings.getCesiumUrl(),
+                            id,
+                            "");
+                }
+
+                // og:type
+                data.type = "website";
+
+                // og:site_name
+                data.siteName = pluginSettings.getShareSiteName();
+
+                // default og:image
+                if (StringUtils.isBlank(data.image)) {
+                    data.image = pluginSettings.getCesiumUrl() + "/img/logo_128px.png";
+                    data.imageType = "image/png";
+                }
+
+                return data;
+            }
+            catch(UnsupportedEncodingException e) {
+                throw new TechnicalException(e);
+            }
+        };
+    }
+}
diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/PageService.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/PageService.java
index 881fd85ef293b7d62b20afade1c87d375c4d5cd0..f4b4429e5af3cca16913fdff7eaf0fc9742d8c80 100644
--- a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/PageService.java
+++ b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/PageService.java
@@ -32,6 +32,8 @@ import org.duniter.elasticsearch.user.PluginSettings;
 import org.duniter.elasticsearch.user.dao.page.PageCommentDao;
 import org.duniter.elasticsearch.user.dao.page.PageIndexDao;
 import org.duniter.elasticsearch.user.dao.page.PageRecordDao;
+import org.duniter.elasticsearch.user.model.UserProfile;
+import org.duniter.elasticsearch.user.model.page.RegistryRecord;
 import org.elasticsearch.common.inject.Inject;
 
 /**
@@ -138,6 +140,13 @@ public class PageService extends AbstractService {
         commentDao.update(id, json);
     }
 
+    public RegistryRecord getPageForSharing(String id) {
+
+        return client.getSourceByIdOrNull(recordDao.getIndex(), recordDao.getType(), id, RegistryRecord.class,
+                RegistryRecord.PROPERTY_TITLE,
+                RegistryRecord.PROPERTY_DESCRIPTION,
+                RegistryRecord.PROPERTY_THUMBNAIL);
+    }
 
     /* -- Internal methods -- */
 
diff --git a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/UserService.java b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/UserService.java
index 745f5b828e6eb0bfe35efa97b875556329b5c4d9..2d080a88ba9d1309ec607cb8aa9a5345c5103003 100644
--- a/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/UserService.java
+++ b/duniter4j-es-user/src/main/java/org/duniter/elasticsearch/user/service/UserService.java
@@ -24,19 +24,26 @@ package org.duniter.elasticsearch.user.service;
 
 
 import com.fasterxml.jackson.databind.JsonNode;
+import org.apache.lucene.queryparser.flexible.core.util.StringUtils;
 import org.duniter.core.util.Preconditions;
 import org.apache.commons.collections4.MapUtils;
 import org.duniter.core.client.model.ModelUtils;
-import org.duniter.core.client.model.elasticsearch.UserProfile;
+import org.duniter.elasticsearch.user.model.Attachment;
+import org.duniter.elasticsearch.user.model.UserProfile;
 import org.duniter.core.service.CryptoService;
 import org.duniter.elasticsearch.client.Duniter4jClient;
+import org.duniter.elasticsearch.rest.attachment.RestImageAttachmentAction;
+import org.duniter.elasticsearch.rest.share.AbstractRestShareLinkAction;
 import org.duniter.elasticsearch.user.PluginSettings;
 import org.duniter.elasticsearch.exception.AccessDeniedException;
 import org.duniter.elasticsearch.service.AbstractService;
 import org.duniter.elasticsearch.user.dao.profile.UserIndexDao;
 import org.duniter.elasticsearch.user.dao.profile.UserProfileDao;
 import org.duniter.elasticsearch.user.dao.profile.UserSettingsDao;
+import org.duniter.elasticsearch.util.opengraph.OGData;
 import org.elasticsearch.common.inject.Inject;
+import org.elasticsearch.rest.BytesRestResponse;
+import org.elasticsearch.rest.RestStatus;
 
 import java.util.HashMap;
 import java.util.Map;
@@ -226,6 +233,15 @@ public class UserService extends AbstractService {
         return sb.substring(separator.length());
     }
 
+    public UserProfile getUserProfileForSharing(String id) {
+
+        return client.getSourceByIdOrNull(INDEX, PROFILE_TYPE, id, UserProfile.class,
+                UserProfile.PROPERTY_TITLE,
+                UserProfile.PROPERTY_DESCRIPTION,
+                UserProfile.PROPERTY_LOCALE,
+                UserProfile.PROPERTY_AVATAR);
+    }
+
     /* -- Internal methods -- */
 
 }
diff --git a/duniter4j-es-user/src/main/resources/i18n/duniter4j-es-user_en_GB.properties b/duniter4j-es-user/src/main/resources/i18n/duniter4j-es-user_en_GB.properties
index 98d218d1ac2674b2a99cc8e0d673c1eb85d6576e..3c47a593117794059ed2628a702289ef4d3798b0 100644
--- a/duniter4j-es-user/src/main/resources/i18n/duniter4j-es-user_en_GB.properties
+++ b/duniter4j-es-user/src/main/resources/i18n/duniter4j-es-user_en_GB.properties
@@ -15,4 +15,7 @@ duniter.user.event.NODE_BMA_UP=Duniter node [%1$s\:%2$s] is UP again.
 duniter.user.event.NODE_STARTED=Your node ES API [%1$s] is UP.
 duniter.user.event.TX_RECEIVED=You received a payment from %2$s.
 duniter.user.event.TX_SENT=Your payment to %2$s was executed.
+duniter.user.share.description=Follow your "libre money" wallets easily
+duniter.user.share.pubkey=Public key\: %1$s
+duniter4j.es.share.error.noBaseUrl=Image path are relative for share links (og\:image). /\!\\ Set [%s] in the configuration (recommended).
 duniter4j.ws.user.open=User [%1$s] connecting with id [%2$s] with locale [%3$s]
diff --git a/duniter4j-es-user/src/main/resources/i18n/duniter4j-es-user_fr_FR.properties b/duniter4j-es-user/src/main/resources/i18n/duniter4j-es-user_fr_FR.properties
index e4e31362232b4af585877a5b90a3541bf51c8da1..ec9ace345c37859ec4eebeece40f906bd7d5233d 100644
--- a/duniter4j-es-user/src/main/resources/i18n/duniter4j-es-user_fr_FR.properties
+++ b/duniter4j-es-user/src/main/resources/i18n/duniter4j-es-user_fr_FR.properties
@@ -15,4 +15,7 @@ duniter.user.event.NODE_BMA_UP=Noeud Duniter [%1$s\:%2$s] à nouveau accessible.
 duniter.user.event.NODE_STARTED=Noeud ES API [%1$s] est démarré.
 duniter.user.event.TX_RECEIVED=Vous avez recu un paiement de %2$s.
 duniter.user.event.TX_SENT=Votre paiement à %2$s a bien été executé.
+duniter.user.share.description=Suivez vos comptes de monnaie libre en toute simplicité \!
+duniter.user.share.pubkey=Clé publique \: %1$s
+duniter4j.es.share.error.noBaseUrl=Chemins relatif pour les images, dans les partages (og\:image). /\!\\ Renseignez [%s] dans la configuration (conseillé).
 duniter4j.ws.user.open=Utilisateur [%1$s] connecté id\=[%2$s] sur la locale [%3$s]
diff --git a/pom.xml b/pom.xml
index ea42a4859c7081124d9c4a627b95c62efbdd3942..a58713254a8ae40c7e5eecc5a9478632480fd1dd 100644
--- a/pom.xml
+++ b/pom.xml
@@ -33,8 +33,8 @@
     <slf4j.version>1.7.5</slf4j.version>
     <guava.version>22.0</guava.version>
     <xml-apis.version>2.0.2</xml-apis.version>
-    <kalium.version>0.5.0_blavenie</kalium.version>
-    <jnr-ffi.version>2.1.0</jnr-ffi.version>
+    <kalium.version>0.6.0_PR64</kalium.version>
+    <jnr-ffi.version>2.1.7</jnr-ffi.version>
     <scrypt.version>1.4.0</scrypt.version>
     <elasticsearch.version>2.4.6</elasticsearch.version>
     <jna.version>4.2.0</jna.version>
diff --git a/src/scripts/start-es-node.sh b/src/scripts/start-es-node.sh
new file mode 100755
index 0000000000000000000000000000000000000000..a9be23c2a5700cafb7bcfa08b37ab480d64a0ea4
--- /dev/null
+++ b/src/scripts/start-es-node.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+
+PID=`ps -efl | grep duniter4j-es | grep g1/lib | awk '/^([0-9]+) ([^\s]) ([a-zA-Z0-9]+) ([0-9]+).*/ {printf "%s", $4}'`
+
+if [ "$PID" != "" ];
+then
+        echo "Error: ES node already started!"
+        exit -1
+else
+        cd /opt/duniter4j-es-g1/bin
+        ./elasticsearch -d
+        echo "ES node started !"
+        echo "...to follow log: tail -f /opt/duniter4j-es-g1/logs/g1-es-data.log"
+fi
+
diff --git a/src/scripts/stop-es-nodes.sh b/src/scripts/stop-es-nodes.sh
new file mode 100755
index 0000000000000000000000000000000000000000..8181a733c99af4acddd1e759dcb3b3effc6cfcca
--- /dev/null
+++ b/src/scripts/stop-es-nodes.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+
+# Get ES PID
+PID=`ps -efl | grep duniter4j-es | grep lib | awk '{printf "%s", $4}'`
+
+if [ "$PID" != "" ];
+then
+        echo "Stopping ES node running on PID $PID..."
+        sudo kill -15 $PID
+
+        sleep 5s
+
+        # Check if still alive
+        PID=`ps -efl | grep duniter4j-es | grep g1/lib | awk '{printf "%s", $4}'`
+        if [ "$PID" != "" ];
+        then
+                sleep 10s
+        fi
+
+        PID=`ps -efl | grep duniter4j-es | grep g1/lib | awk '{printf "%s", $4}'`
+        if [ "$PID" != "" ];
+        then 
+                echo "Error: Unable to stop ES node !"
+                exit -1
+        else
+                echo "ES node stopped"
+        fi
+
+else
+        echo "ES node not running!"
+fi
+
diff --git a/src/scripts/update-es-node.sh b/src/scripts/update-es-node.sh
new file mode 100755
index 0000000000000000000000000000000000000000..28702aadeaff634210f4a1ecbd87ac75b1b60860
--- /dev/null
+++ b/src/scripts/update-es-node.sh
@@ -0,0 +1,90 @@
+#!/bin/bash
+
+VERSION=$1
+OLD_VERSION=$2
+
+if [ "${VERSION}" == "" ]; then
+        echo "ERROR: Missing version argument !"
+        echo " "
+        echo "usage: sudo ./update-es.sh <version> [<old_version>]"
+        exit
+fi
+if [ "${OLD_VERSION}" == "" ]; then
+        OLD_VERSION=`ps -efl | grep duniter4j-es | grep g1/lib | sed -r 's/.*duniter4j-es-([0-9.]+)-g1.*/\1/g'`
+        if [ "${OLD_VERSION}" == "" ]; then
+                echo "Error: unable to known previous version"
+                exit
+        fi
+fi
+
+READLINK=`which readlink`
+if [ -z "$READLINK"  ]; then
+  message "Required tool 'readlink' is missing. Please install before launch \"$0\" file."
+  exit 1
+fi
+
+# ------------------------------------------------------------------
+# Ensure BASEDIR points to the directory where the soft is installed.
+# ------------------------------------------------------------------
+SCRIPT_LOCATION=$0
+if [ -x "$READLINK" ]; then
+  while [ -L "$SCRIPT_LOCATION" ]; do
+    SCRIPT_LOCATION=`"$READLINK" -e "$SCRIPT_LOCATION"`
+  done
+fi 
+
+export BASEDIR=`dirname "$SCRIPT_LOCATION"`                                                                                                                                                                                                        
+cd $BASEDIR 
+
+echo "--- Downloading duniter4j-es-standalone v$VERSION... ----------------------"
+
+if [ -f "downloads/duniter4j-es-${VERSION}-standalone.zip" ]; then
+        echo "...removing file, as it already exists in ./downloads/duniter4j-es-${VERSION}-standalone.zip" 
+        rm ./downloads/duniter4j-es-${VERSION}-standalone.zip
+fi
+
+if [ ! -e "downloads" ]; then
+        mkdir downloads
+fi
+
+cd downloads
+wget -kL https://github.com/duniter/duniter4j/releases/download/duniter4j-${VERSION}/duniter4j-es-${VERSION}-standalone.zip
+cd ..
+
+if [ -f "downloads/duniter4j-es-${VERSION}-standalone.zip" ]; then
+        echo ""
+else
+        echo "Error: unable to dowlonad this version!"
+        exit -1
+fi
+
+echo "--- Installating duniter4j-es v$VERSION... ---------------------"
+if [ -d "/opt/duniter4j-es-${VERSION}-g1" ]; then
+        echo "Error: Already installed in /opt/duniter4j-es-${VERSION}-g1 !"
+        exit -1
+fi
+
+unzip -o ./downloads/duniter4j-es-${VERSION}-standalone.zip
+mv duniter4j-es-${VERSION} duniter4j-es-${VERSION}-g1
+sudo mv duniter4j-es-${VERSION}-g1 /opt/
+sudo rm /opt/duniter4j-es-g1
+sudo ln -s /opt/duniter4j-es-${VERSION}-g1 /opt/duniter4j-es-g1
+
+mkdir /opt/duniter4j-es-${VERSION}-g1/data
+mv /opt/duniter4j-es-${VERSION}-g1/config/elasticsearch.yml /opt/duniter4j-es-${VERSION}-g1/config/elasticsearch.yml.ori
+
+./stop-es-nodes.sh
+
+if [ "$OLD_VERSION" != "$VERSION" ];
+then
+        echo "--- Restoring files (data+config) from previous version $OLD_VERSION... ---------------------"
+        tar -cvf /opt/duniter4j-es-${OLD_VERSION}-g1/data/save.tar.gz /opt/duniter4j-es-${OLD_VERSION}-g1/data/g1-*
+        mv /opt/duniter4j-es-${OLD_VERSION}-g1/data/g1-* /opt/duniter4j-es-${VERSION}-g1/data  
+        cp /opt/duniter4j-es-${OLD_VERSION}-g1/config/elasticsearch.yml /opt/duniter4j-es-${VERSION}-g1/config
+fi
+
+#./start-es-nodes.sh
+
+echo "--- Successfully installed duniter4j-es v$VERSION ! -------------"
+echo ""
+