Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
213 commits
Select commit Hold shift + click to select a range
0d9ea33
Initial WP config to confirm understanding of CI/CD pipeline. ENV to …
Jun 14, 2025
da78a1e
Migrate from static site to WordPress with MySQL and Redis
Jun 14, 2025
265be4e
Merge pull request #13 from paul-rtdao/staging
daodevinc Jun 14, 2025
4d958b1
Fix img on CI/CD
daodevinc Jun 14, 2025
0ccb6e0
Fix network CD
daodevinc Jun 14, 2025
7cd018d
Update docker-compose-main.yml
daodevinc Jun 15, 2025
b259070
ENV CHANGES
Jun 21, 2025
89e2b9b
Merge branch 'preprod' of github.com:RealToken-Community/welcome-comm…
Jun 21, 2025
eaecaed
space issue
Jun 21, 2025
1bf9577
Update container name
daodevinc Jul 8, 2025
b30b97b
Update NS
daodevinc Oct 29, 2025
184b71c
first commit
Yohann76 Nov 24, 2025
2ac4a55
feat: add some documentation
Yohann76 Nov 24, 2025
7543507
feat: add design documentation
Yohann76 Nov 24, 2025
fce6be5
feat: add first graphics chart in homepage
Yohann76 Nov 24, 2025
c613492
feat: update Makefile
Yohann76 Nov 26, 2025
68b87b5
feat: add scss in assets
Yohann76 Nov 26, 2025
b968360
feat: update navbar with application, ressources, governance
Yohann76 Nov 26, 2025
6258804
feat: update title page
Yohann76 Nov 26, 2025
3476b12
feat: add some indication in design
Yohann76 Nov 26, 2025
34130c8
feat: add information in homepage
Yohann76 Nov 26, 2025
617649d
feat: add simple translation with navbar button
Yohann76 Nov 26, 2025
c0b603a
feat: update text in header
Yohann76 Nov 26, 2025
1783c62
feat: add some text in homepage
Yohann76 Nov 26, 2025
ed90167
feat: add roadmap.md in documentation
Yohann76 Dec 27, 2025
f52bd44
feat: add information in roadmap.md
Yohann76 Dec 27, 2025
f8ca953
feat: add blog feature with page and markdown content for translation
Yohann76 Dec 29, 2025
57f173c
feat: add external port in docker-compose.yml
Yohann76 Jan 30, 2026
d5df091
feat: resolve equivalents slug in blog.js
Yohann76 Jan 30, 2026
9dcb6e2
feat: add first article with picture
Yohann76 Jan 30, 2026
ab778bf
fix: add extention picture
Yohann76 Jan 30, 2026
49b3948
feat: add second article
Yohann76 Jan 30, 2026
9493b17
feat: add two article for demo blog
Yohann76 Jan 30, 2026
e7fc4ee
feat: add fix nav, and update for responsive
Yohann76 Feb 2, 2026
b5a6d88
feat: add level in navbar
Yohann76 Feb 2, 2026
d1ac317
feat: add footer in website
Yohann76 Feb 2, 2026
15e0d61
feat: add simple icon in footer
Yohann76 Feb 2, 2026
aef63bb
feat: update rmm link
Yohann76 Feb 2, 2026
9adfd9d
feat: add forum link
Yohann76 Feb 2, 2026
2f1dc7d
feat: add simple FAQ page with dropdown
Yohann76 Feb 2, 2026
ea2df78
feat: add wiki link
Yohann76 Feb 2, 2026
9086af1
add comitee view page
Yohann76 Feb 2, 2026
0408032
feat: add tally link
Yohann76 Feb 2, 2026
c0b5393
feat: fix typo in comite page
Yohann76 Feb 3, 2026
40eecae
feat: add dashboard link in nav
Yohann76 Feb 3, 2026
bea1ca9
feat: add bridge link
Yohann76 Feb 3, 2026
9e8a5b6
feat: update social link in footer
Yohann76 Feb 3, 2026
7196d4e
feat: add different link from DAO
Yohann76 Feb 3, 2026
1093c0c
feat: add REG page (with coingecko free API)
Yohann76 Feb 3, 2026
b52f9a0
feat: add information in FAQ page
Yohann76 Feb 3, 2026
9dc5b60
feat: add mailto button for contact
Yohann76 Feb 3, 2026
54271a7
feat: add partners page
Yohann76 Feb 3, 2026
30fcec4
feat: update link button in homepage
Yohann76 Feb 3, 2026
4d7044e
feat: update keyword in homepage
Yohann76 Feb 3, 2026
f5d0470
feat: modernize website with new homepage section
Yohann76 Feb 3, 2026
e1afc2e
feat: update size on last section
Yohann76 Feb 3, 2026
98ee715
feat: update section with new color
Yohann76 Feb 3, 2026
bf179ad
feat: add legal page example
Yohann76 Feb 3, 2026
618437b
fix: fix typography in homepage
Yohann76 Feb 3, 2026
dc68766
feat: update text in homepage
Yohann76 Feb 3, 2026
45780c4
fix: wording in homepage
Yohann76 Feb 3, 2026
2fbc7be
feat: update wording in partner page
Yohann76 Feb 3, 2026
7e7c4ee
feat: update wording in nav and footer
Yohann76 Feb 3, 2026
0d75d40
feat: add realtoken wallet link in nav
Yohann76 Feb 3, 2026
2adee74
fix: add scroll up before each loading page
Yohann76 Feb 5, 2026
e005086
feat: update link page with new section
Yohann76 Feb 5, 2026
d1bcd19
fix: bug in footer typo years
Yohann76 Feb 5, 2026
56e8f5b
feat: update local translation
Yohann76 Feb 5, 2026
8473b5a
feat: update translation in legal page
Yohann76 Feb 5, 2026
1c8623b
feat: update background link in pageLink
Yohann76 Feb 5, 2026
cd426c2
feat: update order link in gouvernance nav
Yohann76 Feb 5, 2026
dea933f
feat: update roadmap.md
Yohann76 Feb 6, 2026
38ebf7b
Merge pull request #1 from Yohann76/feature/blog-page-seo-with-article
Yohann76 Feb 6, 2026
c568ac5
feat: add logo nav/footer
Yohann76 Feb 6, 2026
12c109b
feat: add favicon svg logo
Yohann76 Feb 6, 2026
363e05c
Merge pull request #2 from Yohann76/feature/add-logo-favicon
Yohann76 Feb 6, 2026
24f8c3f
Merge pull request #3 from Yohann76/develop
Yohann76 Feb 6, 2026
924c1a2
Merge pull request #4 from Yohann76/main
Yohann76 Feb 6, 2026
58a52ca
feat: add some documentation
Yohann76 Feb 6, 2026
183aeed
Merge pull request #5 from Yohann76/feature/add-design-documentation
Yohann76 Feb 6, 2026
0d04229
feat: force URL in english
Yohann76 Feb 9, 2026
a40f790
feat: add some documentation for blog
Yohann76 Feb 9, 2026
9b243a2
feat: add sitemap generation for SEO
Yohann76 Feb 9, 2026
1f4b62c
fix: update wording in homepage
Yohann76 Feb 9, 2026
ea1e8f8
feat: add link in tool section
Yohann76 Feb 9, 2026
29671a6
feat: add link in homepage gouvernance
Yohann76 Feb 9, 2026
3579946
Merge pull request #6 from Yohann76/feature/optimize-lang-url
Yohann76 Feb 9, 2026
ef4852c
Merge pull request #7 from Yohann76/develop
Yohann76 Feb 9, 2026
6880c2b
Merge pull request #8 from Yohann76/main
Yohann76 Feb 9, 2026
cc174f3
feat: rename usefull-link to application hub
Yohann76 Feb 11, 2026
de4d8e3
feat: deplace link application hub
Yohann76 Feb 11, 2026
c36a82e
feat: add different management link
Yohann76 Feb 11, 2026
b04f419
feat: deplace information card link
Yohann76 Feb 11, 2026
98d32f8
feat: add section information
Yohann76 Feb 11, 2026
cbf3830
feat: add information text in application hub page
Yohann76 Feb 11, 2026
05488a5
feat: add domain for each app managment
Yohann76 Feb 11, 2026
5feaed9
feat: add simple link in REG section
Yohann76 Feb 11, 2026
a14e1b6
fix: fix nav hamburger bug and cut blog article with mobile screen
Yohann76 Feb 11, 2026
7099c60
Merge pull request #9 from RealToken-Community/feature/application-hub
Yohann76 Feb 11, 2026
91d59df
Merge pull request #10 from RealToken-Community/develop
Yohann76 Feb 11, 2026
9958454
feat: update README.md
Yohann76 Feb 12, 2026
ad9b0e2
Merge pull request #1 from Yohann76/feature/add-some-graphic-details
Yohann76 Feb 12, 2026
8d4015a
Merge pull request #2 from Yohann76/develop
Yohann76 Feb 12, 2026
92c9287
feat: add netlify configuration for not 404 link (on index)
Yohann76 Feb 12, 2026
431fc63
Merge pull request #3 from Yohann76/feature/add-some-graphic-details
Yohann76 Feb 12, 2026
193838d
Merge pull request #4 from Yohann76/develop
Yohann76 Feb 12, 2026
fcb6479
feat: remove toolbar vue kit
Yohann76 Feb 20, 2026
50594df
feat: add label link in application hub
Yohann76 Feb 20, 2026
e9c19b8
feat: order application page in dashboard (not section page)
Yohann76 Feb 20, 2026
2f280b2
Merge pull request #5 from Yohann76/feature/update-some-details-befor…
Yohann76 Feb 20, 2026
0408902
Merge pull request #6 from Yohann76/develop
Yohann76 Feb 20, 2026
7981e8e
Merge pull request #11 from RealToken-Community/main
Yohann76 Feb 20, 2026
0bfd5fd
feat: add article for grealtoken gouvernance
Yohann76 Feb 21, 2026
428532e
feat: fix bug in nav design
Yohann76 Feb 21, 2026
6123ed5
feat: update link application nav
Yohann76 Feb 21, 2026
f6a9604
feat: add link for dao wiki in reg ecosystem
Yohann76 Feb 21, 2026
7a05a08
feat: add simple color in other app link
Yohann76 Feb 21, 2026
36bfd9a
feat: generate sitemap with make dev-run, and add other article
Yohann76 Feb 21, 2026
20ce3df
feat: update FAQ1
Yohann76 Feb 21, 2026
7ecd664
feat improve FAQ2
Yohann76 Feb 21, 2026
e00bce8
feat: improve FAQ3
Yohann76 Feb 21, 2026
8e1decb
feat: add enchors in FAQ page
Yohann76 Feb 21, 2026
3584a2b
feat; adjust scroll anchors from link
Yohann76 Feb 21, 2026
0a8b438
fix: import slug for display blog page
Yohann76 Feb 21, 2026
c7c7387
Merge pull request #7 from Yohann76/feature/update-some-details-befor…
Yohann76 Feb 21, 2026
d5c39cf
Merge pull request #8 from Yohann76/develop
Yohann76 Feb 21, 2026
40b676d
Merge pull request #12 from Yohann76/main
Yohann76 Feb 21, 2026
4669925
fix: update l18n link
Yohann76 Feb 21, 2026
0a11606
Merge pull request #9 from Yohann76/feature/update-some-details-befor…
Yohann76 Feb 21, 2026
bbe86ed
Merge pull request #10 from Yohann76/develop
Yohann76 Feb 21, 2026
c014b8e
feat: add realtoken dashboard in application hub
Yohann76 Feb 22, 2026
7fb43ef
feat: add simple description in link
Yohann76 Feb 22, 2026
7dfad5c
feat: update value and text for proof section in homepage
Yohann76 Feb 22, 2026
da954f2
Merge pull request #11 from Yohann76/feature/update-some-details-befo…
Yohann76 Feb 22, 2026
5cf4e0e
Merge pull request #12 from Yohann76/develop
Yohann76 Feb 22, 2026
b69e031
feat: add simple blog content (6)
Yohann76 Mar 12, 2026
751eaed
feat: add prompt img color
Yohann76 Mar 12, 2026
f165e31
feat: sync all img for article blog with prompt
Yohann76 Mar 12, 2026
bbf07a4
feat: add simple graph in blog list homepage
Yohann76 Mar 12, 2026
efc88b7
Merge pull request #13 from Yohann76/feature/add-blog-content-6
Yohann76 Mar 12, 2026
02164a3
Merge pull request #14 from Yohann76/develop
Yohann76 Mar 12, 2026
e97dc8e
Merge pull request #15 from Yohann76/main
Yohann76 Mar 12, 2026
bc84f51
Merge pull request #13 from Yohann76/develop
Yohann76 Mar 26, 2026
f966ff5
feat: add test permissions
Yohann76 Mar 26, 2026
00a858c
feat: update .env.example
Yohann76 Mar 26, 2026
2a5e444
remove all old file
Yohann76 Mar 26, 2026
1faefec
Merge pull request #14 from RealToken-Community/develop
Yohann76 Mar 26, 2026
b14646f
feat: rename version for prevent conflict
Yohann76 Mar 26, 2026
413ed7e
Import RealToken website main into feat branch while preserving both …
Yohann76 Mar 26, 2026
923e333
Align branch tree exactly with realtoken-upstream/main
Yohann76 Mar 26, 2026
7b0bd1d
feat: add old file from welcome-community docker-compose, LICENSE ...
Yohann76 Mar 26, 2026
66bf809
Merge pull request #1 from Yohann76/feat/migration-new-version-in-pre…
Yohann76 Mar 26, 2026
c83ae6b
fix: remove space in and file name
Yohann76 Mar 26, 2026
b4b2306
fix: remove space in end docker-compose file
Yohann76 Mar 26, 2026
8ad94e9
feat: add develop version with Makefile and dockerfile.dev
Yohann76 Mar 26, 2026
190615c
Merge pull request #14 from Yohann76/preprod
Yohann76 Mar 26, 2026
b78ac04
feat: add CSV prevent XSS attacks in docker-compose-main,preprod
Yohann76 Mar 26, 2026
9b0603d
feat: add security options in docker-compose.yml
Yohann76 Mar 26, 2026
dfb5ada
fix: update translation with web host name
Yohann76 Mar 26, 2026
842a4b5
feat: update blog design (title and width page)
Yohann76 Mar 26, 2026
fa37417
feat: fix name tools YAM and RMM in article blog
Yohann76 Mar 26, 2026
135650c
feat: update description and title balise for SEO managment
Yohann76 Mar 26, 2026
3336c82
feat: add JSON-LD structured data on FAQ page (in javascript)
Yohann76 Mar 26, 2026
9b8c9d8
Merge pull request #15 from RealToken-Community/feat/adjustement-for-…
Yohann76 Mar 26, 2026
8d77fe7
feat: remove line in legal page (text)
Yohann76 Mar 27, 2026
808cc3a
feat: remove duplicate h1 in blog post
Yohann76 Apr 2, 2026
d184248
feat: adjust authors blog coherence
Yohann76 Apr 2, 2026
9e60277
feat: translation REG description
Yohann76 Apr 2, 2026
71e7cd8
feat: update footer copyright page
Yohann76 Apr 2, 2026
0a5651c
feat: coherence for title page application hub
Yohann76 Apr 2, 2026
1841313
feat: organize URL vor SEO structure
Yohann76 Apr 2, 2026
457e630
feat: add 404 not found page
Yohann76 Apr 2, 2026
8dd39ee
feat: replace word case article in end page
Yohann76 Apr 2, 2026
1ca6100
feat: justify text in article blogpost
Yohann76 Apr 2, 2026
312c4de
feat: add status page pour display link
Yohann76 Apr 2, 2026
fad720c
feat: add crontask in makefile and script
Yohann76 Apr 2, 2026
6eba0a1
feat: add scappa link in application-hub and status page
Yohann76 Apr 2, 2026
e0b5cdb
Merge pull request #16 from RealToken-Community/feat/adjustement-for-…
Yohann76 Apr 2, 2026
2235321
feat: change frequency crontab in script
Yohann76 Apr 2, 2026
efae7f7
feat: change format last day in status page
Yohann76 Apr 2, 2026
62ec563
feat: remove http code error column
Yohann76 Apr 2, 2026
3eb7eb9
feat: use logo for check/error link status
Yohann76 Apr 2, 2026
91873bc
feat: improve design status page for array
Yohann76 Apr 2, 2026
b5ec9ea
feat: update design for status page mobile
Yohann76 Apr 2, 2026
5cce3de
feat: update design for status mobile page
Yohann76 Apr 2, 2026
c33779e
Merge pull request #17 from RealToken-Community/feat/adjustement-for-…
Yohann76 Apr 2, 2026
82cce37
feat: update timeoutMs in chack-app-link.js script
Yohann76 Apr 2, 2026
3e96f98
Merge pull request #18 from RealToken-Community/feat/adjustement-for-…
Yohann76 Apr 2, 2026
aabbde3
feat: remove config in docker-compose (already in main config)
Yohann76 Apr 2, 2026
3dbf7ce
fix: update node version for next LTS
Yohann76 Apr 2, 2026
e1f058d
feat: remove netlify configuration (not use netlify - old version dev)
Yohann76 Apr 2, 2026
6e424f7
feat: remove public domain exemple
Yohann76 Apr 2, 2026
cdf1d6c
fix: not install cron, check url only on build application
Yohann76 Apr 2, 2026
2afd940
Merge pull request #20 from RealToken-Community/feat/adjustement-for-…
Yohann76 Apr 2, 2026
f846393
feat: rm .env.exemple
Yohann76 Apr 3, 2026
0b73910
Merge pull request #21 from RealToken-Community/feat/adjustement-for-…
Yohann76 Apr 3, 2026
ea8b0f4
feat: add number tally vote dynamics
Yohann76 Apr 9, 2026
cd7d642
feat: add REG holder from chain
Yohann76 Apr 9, 2026
162904e
feat: update number value of parner assets
Yohann76 Apr 9, 2026
cfc326d
feat: update label for number of proposals voted by the DAO in homepage
Yohann76 Apr 9, 2026
4fdf4b6
Merge branch 'preprod' into feat/fix-number-homepage
Yohann76 Apr 9, 2026
483f6b6
Merge pull request #22 from RealToken-Community/feat/fix-number-homepage
Yohann76 Apr 9, 2026
9a5942f
feat: add markdown article for rmmV3.5
Yohann76 May 13, 2026
e5b4731
feat: update understanging-rmm-version-3.5 markdown article
Yohann76 May 13, 2026
7b8d260
fix: update max-height for img article single blog
Yohann76 May 13, 2026
00cdf42
feat: update title blog for diversification RWA article markdown
Yohann76 May 13, 2026
39d8f8c
feat: add bullet point in context article date
Yohann76 May 13, 2026
c78c969
feat: add array/table in markdown article and update rmm v3.5 markdow…
Yohann76 May 13, 2026
b9fbc8b
feat: update with array, and delete stablecoin REUSD section
Yohann76 May 13, 2026
1770a96
feat: add og twitter for dev test and fix bug EN/FR in legal page
Yohann76 May 13, 2026
fa69449
feat: update legal page for organisation precision
Yohann76 May 13, 2026
b0db60c
feat: update legal page with precision
Yohann76 May 13, 2026
ae84bcf
Merge pull request #24 from RealToken-Community/feat/add-rmm3.5-artic…
Yohann76 May 13, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
},
"scripts": {
"dev": "vite",
"build": "node scripts/generate-sitemap.js && node scripts/check-app-links.js && vite build",
"build": "node scripts/generate-sitemap.js && node scripts/check-app-links.js && vite build && node scripts/inject-blog-social-meta.js",
"preview": "vite preview",
"sitemap": "node scripts/generate-sitemap.js",
"check:app-links": "node scripts/check-app-links.js"
Expand Down
Binary file added public/ArticleImg/rmm-v3-5-blog.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion public/app-links-status.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"checkedAt": "2026-04-02T11:44:25.960Z",
"checkedAt": "2026-05-13T12:43:24.512Z",
"total": 26,
"links": [
{
Expand Down
207 changes: 207 additions & 0 deletions public/articles/en/understanding-rmm-version-3-5.md

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
---
title: "L'Avenir des RWA : Une Feuille de Route Communautaire pour la Diversification"
title: "Diversification des RWA : une feuille de route communautaire"
date: "2026-03-12"
description: "Comment la communauté RealToken DAO explore la diversification des RWA—critères axés sur la recherche, pistes à l'étude et fondations techniques pour le RMM."
tags: ["rwa", "dao", "gouvernance", "diversification", "rmm"]
author: "Equipe Realtoken DAO"
imageHeader: "future-rwa-roadmap-diversification.png"
---

# L'Avenir des RWA : Une Feuille de Route Communautaire pour la Diversification
# Diversification des RWA : une feuille de route communautaire

## Introduction

Expand Down
207 changes: 207 additions & 0 deletions public/articles/fr/comprendre-version-3-5-rmm.md

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions public/sitemap.xml
Original file line number Diff line number Diff line change
Expand Up @@ -81,4 +81,10 @@
<priority>0.7</priority>
<changefreq>monthly</changefreq>
</url>
<url>
<loc>https://realtoken.community/ressource/blog/understanding-rmm-version-3-5</loc>
<lastmod>2026-05-13</lastmod>
<priority>0.7</priority>
<changefreq>monthly</changefreq>
</url>
</urlset>
102 changes: 102 additions & 0 deletions scripts/blog-article-meta-shared.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/**
* Métadonnées Open Graph / Twitter pour les billets (partagé build + plugin Vite dev).
*/

import { readFileSync, existsSync } from 'node:fs'
import { join } from 'node:path'

export const DEFAULT_BLOG_ARTICLE_DESC =
'Explore all our articles on real estate tokenization, decentralized governance and the RealToken ecosystem.'

/** Échappe le contenu des attributs HTML double-quotés. */
export function escapeHtmlAttr(s) {
return String(s ?? '')
.replace(/&/g, '&amp;')
.replace(/"/g, '&quot;')
.replace(/</g, '&lt;')
.replace(/\r?\n/g, ' ')
}

/** Échappe le texte dans <title>. */
export function escapeHtmlText(s) {
return String(s ?? '')
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/\r?\n/g, ' ')
}

/** Parse un frontmatter YAML minimal depuis un fichier .md. */
export function parseFrontmatterFile(filePath) {
const content = readFileSync(filePath, 'utf-8')
const match = content.match(/^---\s*\n([\s\S]*?)\n---\s*\n/)
if (!match) return {}
const data = {}
for (const line of match[1].split('\n')) {
const idx = line.indexOf(':')
if (idx <= 0) continue
const key = line.slice(0, idx).trim()
let value = line.slice(idx + 1).trim()
if (
(value.startsWith('"') && value.endsWith('"')) ||
(value.startsWith("'") && value.endsWith("'"))
) {
value = value.slice(1, -1)
}
data[key] = value
}
return data
}

/** Construit le bloc de meta Open Graph + Twitter Card pour un article. */
export function buildSocialMetaBlock({ title, description, pageUrl, imageUrl }) {
const t = escapeHtmlAttr(title)
const d = escapeHtmlAttr(description)
const lines = [
`<meta name="description" content="${d}">`,
`<meta property="og:title" content="${t}">`,
`<meta property="og:description" content="${d}">`,
`<meta property="og:type" content="article">`,
`<meta property="og:url" content="${escapeHtmlAttr(pageUrl)}">`,
`<meta property="og:site_name" content="RealToken DAO">`,
`<meta name="twitter:title" content="${t}">`,
`<meta name="twitter:description" content="${d}">`
]
if (imageUrl) {
const iu = escapeHtmlAttr(imageUrl)
lines.push(`<meta property="og:image" content="${iu}">`)
lines.push(`<meta name="twitter:card" content="summary_large_image">`)
lines.push(`<meta name="twitter:image" content="${iu}">`)
} else {
lines.push(`<meta name="twitter:card" content="summary">`)
}
return lines.join('\n ')
}

/**
* Lit le frontmatter EN pour un slug et retourne title / description / URLs pour les cartes sociales.
* @returns {null | { title: string, description: string, pageUrl: string, imageUrl: string }}
*/
export function getArticleSocialMeta(slug, articlesDir, baseUrl) {
const mdPath = join(articlesDir, `${slug}.md`)
if (!existsSync(mdPath)) return null
const fm = parseFrontmatterFile(mdPath)
const rawTitle = (fm.title || slug).trim()
const title = rawTitle ? `${rawTitle} | RealToken DAO` : 'RealToken Blog | RealToken DAO'
const description = (fm.description || DEFAULT_BLOG_ARTICLE_DESC).trim()
const pageUrl = `${baseUrl.replace(/\/$/, '')}/ressource/blog/${slug}`
const imageHeader = (fm.imageHeader || '').trim()
const imageUrl = imageHeader
? `${baseUrl.replace(/\/$/, '')}/ArticleImg/${encodeURIComponent(imageHeader)}`
: ''
return { title, description, pageUrl, imageUrl }
}

/** Injecte title + meta dans une page HTML (index Vite ou dist). */
export function applyBlogMetaToHtmlTemplate(template, { title, description, pageUrl, imageUrl }) {
const metaBlock = buildSocialMetaBlock({ title, description, pageUrl, imageUrl })
let outHtml = template
.replace(/<meta\s+name="description"[^>]*>/i, '')
.replace(/<title>[^<]*<\/title>/i, `<title>${escapeHtmlText(title)}</title>`)
outHtml = outHtml.replace('<head>', `<head>\n ${metaBlock}\n `)
return outHtml
}
51 changes: 51 additions & 0 deletions scripts/inject-blog-social-meta.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/**
* Après `vite build`, duplique dist/index.html vers dist/ressource/blog/<slug>/index.html
* en injectant og:* et twitter:* dans le <head> (lecteurs sociaux sans exécution JS).
*
* URL de base pour og:image / og:url :
* SITEMAP_BASE_URL ou VITE_SITE_URL (défaut : https://realtoken.community)
*/

import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'node:fs'
import { join, dirname } from 'node:path'
import { fileURLToPath } from 'node:url'
import { englishSlugs } from '../src/data/blog-slugs.js'
import { getArticleSocialMeta, applyBlogMetaToHtmlTemplate } from './blog-article-meta-shared.js'

const __dirname = dirname(fileURLToPath(import.meta.url))
const rootDir = join(__dirname, '..')
const distDir = join(rootDir, 'dist')
const distIndex = join(distDir, 'index.html')
const articlesDir = join(rootDir, 'public', 'articles', 'en')

const baseUrl = (process.env.SITEMAP_BASE_URL || process.env.VITE_SITE_URL || 'https://realtoken.community').replace(/\/$/, '')

function main() {
if (!existsSync(distIndex)) {
console.error('inject-blog-social-meta: dist/index.html introuvable. Lancez vite build avant ce script.')
process.exit(1)
}

const template = readFileSync(distIndex, 'utf-8')
if (!template.includes('<head>')) {
console.error('inject-blog-social-meta: balise <head> introuvable dans dist/index.html')
process.exit(1)
}

for (const slug of englishSlugs) {
const meta = getArticleSocialMeta(slug, articlesDir, baseUrl)
if (!meta) {
console.warn('inject-blog-social-meta: fichier manquant, ignoré:', join(articlesDir, `${slug}.md`))
continue
}
const outHtml = applyBlogMetaToHtmlTemplate(template, meta)

const outDir = join(distDir, 'ressource', 'blog', slug)
mkdirSync(outDir, { recursive: true })
const outPath = join(outDir, 'index.html')
writeFileSync(outPath, outHtml, 'utf-8')
console.log('inject-blog-social-meta:', outPath)
}
}

main()
3 changes: 2 additions & 1 deletion src/data/blog-slugs.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@ export const englishSlugs = [
'birth-of-realtoken-dao',
'realtoken-dao-scope',
'realtoken-dao-governance-participation',
'future-rwa-community-roadmap-diversification'
'future-rwa-community-roadmap-diversification',
'understanding-rmm-version-3-5'
]
11 changes: 8 additions & 3 deletions src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -139,9 +139,9 @@
"tag": "Proof",
"title": "Verifiable indicators, in real time.",
"assets": "Total value of partner assets in the ecosystem",
"members": "Ecosystem members",
"members": "REG holders",
"regMarketcap": "REG marketcap",
"votes": "Number of votes on Tally",
"votes": "Number of proposals voted by the DAO",
"comingSoon": "Coming soon",
"inProgress": "In progress"
},
Expand Down Expand Up @@ -416,8 +416,13 @@
"s1Title": "Site publisher (LCEN)",
"s1Intro": "In accordance with French law no. 2004-575 of 21 June 2004 on confidence in the digital economy (LCEN), the following identifies the publisher and host of the site.",
"s1List": "Name or designation: RealToken DAO (decentralised organisation)\nEmail: marketing{'@'}realtoken.community\nDirector of publication: DAO marketing committee",
"s1bTitle": "Operation and organisation",
"s1bContent": "RealToken DAO is a decentralised autonomous organisation. It operates without hierarchy or centralised management: every decision and every governance-related action is put to a vote among REG holders. Anyone who holds or has held REG is part of the DAO; anyone who votes or has voted on proposals is also part of the DAO. No single individual represents the DAO on their own. The DAO is a collective: it is expressed through the historical participation of each of its members—whether by voting or by holding REG at one time or another.",
"s1bContent2": "The DAO does not belong to any company. It does not mirror the classic operation of a company or an association: it follows a specific model, without hierarchy, based solely on organisational rules implemented through the blockchain.",
"s1bContent3": "Members of each committee do not represent the DAO in any way: they form small working groups, appointed by the DAO through proposals put to a vote. These groups are not under hierarchical command from the DAO; each group works autonomously and then submits its results to the DAO, where every token holder can comment on the outcomes, on working methods and on overall operation.",
"s1bContent4": "The DAO may also, by vote, grant a mandate to act within a defined scope to an entity or a group of people, in order to streamline certain processes. That mandate remains revocable: the DAO may at any time revoke those authorisations or enforce a decision that supersedes what was previously applied, if it decides otherwise in accordance with the governance rules.",
"s2Title": "Hosting",
"s2Content": "The site is hosted by [host name], [address]. For any question regarding hosting, please contact the host or the site publisher.",
"s2Content": "The site is hosted by OVH. OVH SAS is a subsidiary of OVH Groupe SA, a company registered with the Lille Trade and Companies Register (RCS Lille) under number 537 407 926, with its registered office at 2, rue Kellermann, 59100 Roubaix, France. For any question regarding hosting, please contact the host or the site publisher.",
"s3Title": "Disclaimers and risks",
"s3List": "Tokens and tokenised assets (including in the RealT or RealToken ecosystem) do not constitute a guaranteed investment; their value may fluctuate.\nThe contents of this site do not constitute investment, financial, legal or tax advice.\nDue to the decentralised nature of a DAO, liability may be limited and shared among participants; decisions are made collectively and on-chain.\nFor financial and tokenised aspects (sale, purchase, holding of tokens), tax obligations and, where applicable, rules of the AMF (Autorité des marchés financiers) or equivalent regulator may apply; each user is responsible for compliance with applicable law.",
"s3Disclaimer": "The information on this page is kept up to date where possible. For any questions regarding this legal notice, you may contact us at the address given in the publisher section."
Expand Down
9 changes: 7 additions & 2 deletions src/locales/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -139,9 +139,9 @@
"tag": "Preuves",
"title": "Des indicateurs vérifiables, en temps réel.",
"assets": "Valeur totale des actifs partenaires dans l'écosystème",
"members": "Membres de l'écosystème",
"members": "Détenteurs de REG",
"regMarketcap": "Marketcap REG",
"votes": "Nombre de votes sur Tally",
"votes": "Nombre de propositions votées par la DAO",
"comingSoon": "À venir",
"inProgress": "En cours"
},
Expand Down Expand Up @@ -416,6 +416,11 @@
"s1Title": "Éditeur du site (LCEN)",
"s1Intro": "Conformément à la loi n° 2004-575 du 21 juin 2004 pour la confiance dans l'économie numérique (LCEN), sont indiqués ci-dessous les éléments d'identification de l'éditeur et de l'hébergeur du site.",
"s1List": "Dénomination ou nom : RealToken DAO (organisation décentralisée)\nCourriel : marketing{'@'}realtoken.community\nDirecteur de la publication : comité marketing de la DAO",
"s1bTitle": "Fonctionnement et organisation",
"s1bContent": "La RealToken DAO est une organisation autonome décentralisée. Elle fonctionne sans hiérarchie ni direction centralisée : chaque décision et chaque action soumise à la gouvernance est portée au vote des détenteurs de REG. Toute personne qui détient ou a détenu des REG fait partie de la DAO ; toute personne qui vote ou a voté lors des propositions fait également partie de la DAO. Aucune personne ne représente la DAO à titre individuel. La DAO est un collectif : elle s’exprime par la participation historique de chacun de ses membres, que ce soit par le vote ou par la détention de REG, à un moment ou à un autre.",
"s1bContent2": "La DAO n’appartient à aucune entreprise. Elle ne s’apparente pas au fonctionnement classique d’une entreprise ou d’une association : il s’agit d’un fonctionnement particulier, sans hiérarchie, qui repose uniquement sur des règles d’organisation mises en œuvre à travers la blockchain.",
"s1bContent3": "Les membres présents dans chaque comité ne représentent en aucun cas la DAO : il s’agit de petits groupes de travail, désignés par la DAO lors de propositions soumises au vote. Ces groupes ne sont pas placés sous un commandement hiérarchique de la DAO ; chaque groupe travaille en autonomie et soumet ensuite ses résultats à la DAO, où chaque détenteur de tokens peut s’exprimer sur les résultats obtenus, sur les façons de faire et sur le fonctionnement général.",
"s1bContent4": "La DAO peut aussi, par vote, confier un mandat pour agir dans un cadre défini à une entité ou à un groupe de personnes, afin de fluidifier certains processus. Ce mandat reste réversible : la DAO peut à tout moment révoquer ces habilitations ou faire appliquer une décision contraire à ce qui avait été appliqué, si elle en décide autrement selon les règles de gouvernance.",
"s2Title": "Hébergeur",
"s2Content": "Le site est hébergé par OVH. OVH SAS est une filiale de la société OVH Groupe SA, société immatriculée au RCS de Lille sous le numéro 537 407 926, sise 2, rue Kellermann, 59100 Roubaix. Pour toute question relative à l'hébergement, veuillez contacter l'hébergeur ou l'éditeur du site.",
"s3Title": "Avertissements et risques",
Expand Down
4 changes: 3 additions & 1 deletion src/utils/blog.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,9 @@ const slugEquivalents = {
'participation-gouvernance-realtoken-dao': { en: 'realtoken-dao-governance-participation' },
'realtoken-dao-governance-participation': { fr: 'participation-gouvernance-realtoken-dao' },
'avenir-rwa-diversification-communautaire': { en: 'future-rwa-community-roadmap-diversification' },
'future-rwa-community-roadmap-diversification': { fr: 'avenir-rwa-diversification-communautaire' }
'future-rwa-community-roadmap-diversification': { fr: 'avenir-rwa-diversification-communautaire' },
'understanding-rmm-version-3-5': { fr: 'comprendre-version-3-5-rmm' },
'comprendre-version-3-5-rmm': { en: 'understanding-rmm-version-3-5' }
}

/** Retourne le slug à utiliser pour une locale (équivalent du même article dans l'autre langue si besoin) */
Expand Down
76 changes: 71 additions & 5 deletions src/views/BlogPost.vue
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
</template>

<script setup>
import { ref, onMounted, watch } from 'vue'
import { ref, onMounted, onUnmounted, watch } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { useI18n } from 'vue-i18n'
import { loadArticle } from '../utils/blog.js'
Expand All @@ -43,6 +43,8 @@ const { locale } = useI18n()
const article = ref(null)
const DEFAULT_TITLE = 'RealToken Blog | RealToken DAO'
const DEFAULT_DESCRIPTION = 'Explore all our articles on real estate tokenization, decentralized governance and the RealToken ecosystem.'
/** Marque les meta OG / Twitter injectées par cette page pour les retirer au démontage. */
const BLOG_SOCIAL_META_ATTR = 'data-blog-social-meta'

function upsertMetaDescription(content) {
let descriptionTag = document.querySelector('meta[name="description"]')
Expand All @@ -54,7 +56,21 @@ function upsertMetaDescription(content) {
descriptionTag.setAttribute('content', content)
}

/** Retire les balises Open Graph / Twitter Card ajoutées pour un billet (évite qu’elles restent sur les autres pages). */
function removeBlogSocialMeta() {
document.querySelectorAll(`meta[${BLOG_SOCIAL_META_ATTR}]`).forEach((el) => el.remove())
}

/** Ajoute une meta dans le head, marquée pour nettoyage ultérieur. */
function appendTrackedMeta(attrs) {
const meta = document.createElement('meta')
Object.entries(attrs).forEach(([key, value]) => meta.setAttribute(key, value))
meta.setAttribute(BLOG_SOCIAL_META_ATTR, '1')
document.head.appendChild(meta)
}

function updateSeoHead(post) {
removeBlogSocialMeta()
if (!post) {
document.title = DEFAULT_TITLE
upsertMetaDescription(DEFAULT_DESCRIPTION)
Expand All @@ -64,8 +80,30 @@ function updateSeoHead(post) {
const description = post.description?.trim() ? post.description : DEFAULT_DESCRIPTION
document.title = title
upsertMetaDescription(description)

if (typeof window === 'undefined') return
const pageUrl = `${window.location.origin}${route.path}`
appendTrackedMeta({ property: 'og:title', content: title })
appendTrackedMeta({ property: 'og:description', content: description })
appendTrackedMeta({ property: 'og:type', content: 'article' })
appendTrackedMeta({ property: 'og:url', content: pageUrl })
appendTrackedMeta({ property: 'og:site_name', content: 'RealToken DAO' })
appendTrackedMeta({ name: 'twitter:title', content: title })
appendTrackedMeta({ name: 'twitter:description', content: description })
if (post.imageHeader?.trim()) {
const imageUrl = `${window.location.origin}/ArticleImg/${encodeURIComponent(post.imageHeader.trim())}`
appendTrackedMeta({ property: 'og:image', content: imageUrl })
appendTrackedMeta({ name: 'twitter:card', content: 'summary_large_image' })
appendTrackedMeta({ name: 'twitter:image', content: imageUrl })
} else {
appendTrackedMeta({ name: 'twitter:card', content: 'summary' })
}
}

onUnmounted(() => {
removeBlogSocialMeta()
})

const fetchArticle = async () => {
const slug = route.params.slug
article.value = await loadArticle(slug, locale.value)
Expand Down Expand Up @@ -107,18 +145,17 @@ const formatDate = (dateString) => {

.post-hero-image {
width: 100%;
max-height: 360px;
overflow: hidden;
border-radius: 16px;
margin-bottom: 32px;
background: rgba(0, 0, 0, 0.2);
}

.post-hero-image img {
width: 100%;
height: 100%;
object-fit: cover;
height: auto;
object-fit: contain;
display: block;
border-radius: 16px;
}

.post-header-content {
Expand Down Expand Up @@ -246,6 +283,35 @@ const formatDate = (dateString) => {
font-style: italic;
}

.post-body :deep(table) {
width: 100%;
border-collapse: collapse;
margin: 1.5em 0;
font-size: 0.95rem;
}

.post-body :deep(th),
.post-body :deep(td) {
border: 1px solid rgba(255, 255, 255, 0.12);
padding: 12px 16px;
text-align: left;
vertical-align: top;
}

.post-body :deep(th) {
background: rgba(255, 140, 66, 0.12);
color: #fff;
font-weight: 600;
}

.post-body :deep(tbody tr:nth-child(even)) {
background: rgba(255, 255, 255, 0.03);
}

.post-body :deep(thead th) {
border-color: rgba(255, 140, 66, 0.25);
}

.post-footer {
margin-top: 64px;
padding-top: 32px;
Expand Down
Loading
Loading