diff --git a/package.json b/package.json index 280efb0..c182540 100644 --- a/package.json +++ b/package.json @@ -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" diff --git a/public/ArticleImg/rmm-v3-5-blog.png b/public/ArticleImg/rmm-v3-5-blog.png new file mode 100644 index 0000000..f1f9c91 Binary files /dev/null and b/public/ArticleImg/rmm-v3-5-blog.png differ diff --git a/public/app-links-status.json b/public/app-links-status.json index 4d191d5..92156a0 100644 --- a/public/app-links-status.json +++ b/public/app-links-status.json @@ -1,5 +1,5 @@ { - "checkedAt": "2026-04-02T11:44:25.960Z", + "checkedAt": "2026-05-13T12:43:24.512Z", "total": 26, "links": [ { diff --git a/public/articles/en/understanding-rmm-version-3-5.md b/public/articles/en/understanding-rmm-version-3-5.md new file mode 100644 index 0000000..3efd02a --- /dev/null +++ b/public/articles/en/understanding-rmm-version-3-5.md @@ -0,0 +1,207 @@ +--- +title: "Understanding RMM version 3.5" +date: "2026-05-13" +description: "After RIP00040 and RIP00043, the RMM v3.5 roadmap advances: principles, development, and first voted parameters for Phase 1." +tags: ["rmm", "defi", "reusd", "governance"] +author: "Realtoken DAO Team" +imageHeader: "rmm-v3-5-blog.png" +--- + +# Understanding RMM version 3.5 + +This article **summarizes** the [proposal on the RealToken forum](https://forum.realtoken.community/d/122) (overall RMM v3.5 design), the [**RIP00040**](https://www.tally.xyz/gov/realtoken-ecosystem-governance/proposal/1401729377552517862159119104352447734711165592875340838992095449427178715814) vote that approved the **principles** and **development launch**, and the [**RIP00043 — First parameters of RMM v3.5**](https://www.tally.xyz/gov/realtoken-ecosystem-governance/proposal/640910280800835192023262285687656568134775170449659841348595080639880745966) vote described in the [proposal on the forum (Phase 1 parameters)](https://forum.realtoken.community/d/127). + +## Context: why it matters now + +**Indicative timeline**: + +- **16 January 2026**: debate on the RMM **liquidity crisis**. +- **5 March 2026**: publication of the v3.5 proposal. +- **17–18 March 2026**: [**RIP00040**](https://www.tally.xyz/gov/realtoken-ecosystem-governance/proposal/1401729377552517862159119104352447734711165592875340838992095449427178715814) vote on **starting development**. +- **From 28 March 2026**: forum discussion on parameters. +- **11 April 2026**: [**RIP00043**](https://www.tally.xyz/gov/realtoken-ecosystem-governance/proposal/640910280800835192023262285687656568134775170449659841348595080639880745966) vote opens on a first set of **Phase 1** parameters. + +**RMM v3 situation** (as framed in the debate): utilization near **100%**, stablecoin borrow rates **above 30%** APR, roughly **$14.4M borrowed** vs **~$48M TVL**, **depositors unable** to withdraw stablecoins. The DAO earns a **share of borrow interest** (protocol parameter), but saturation hurts borrowers, depositors, and growth. + +[**RIP00040**](https://www.tally.xyz/gov/realtoken-ecosystem-governance/proposal/1401729377552517862159119104352447734711165592875340838992095449427178715814): the community approved **RealT developing** **optional** features to ease RMM **over-use**, described in the **proposal on the forum**, rolled out **in phases**. That vote **green-lights development** and sets the **overall framework** for RMM v3.5. + +## One-liner: what is RMM v3.5? + +**RMM v3.5** is mainly an **option**: you can **move part of your** stablecoin **debt** (USDC, xDAI) into **REUSD** (**dREUSD**) if you want to, without replacing normal RMM behavior. **At first**, how much you can migrate per wallet is **capped low** (on the order of **$100** equivalent), then that **cap rises over time** so more participants can use the program. To qualify, you **lock REG** in the protocol’s **vault**: each locked REG unlocks up to **2 dREUSD** of migration headroom. In parallel, the **DAO** brings its **treasury** into the trade: it **matches your repayment dollar-for-dollar** (**100%** participation), as an **incentive** to shift debt into dREUSD instead of keeping it only in stablecoins. + +## [RIP00043](https://www.tally.xyz/gov/realtoken-ecosystem-governance/proposal/640910280800835192023262285687656568134775170449659841348595080639880745966) vote: first Phase 1 parameters + +After [**RIP00040**](https://www.tally.xyz/gov/realtoken-ecosystem-governance/proposal/1401729377552517862159119104352447734711165592875340838992095449427178715814), the DAO voted an **initial parameter set** for **Phase 1** of the RMM v3.5 rollout, detailed in the [proposal on the forum](https://forum.realtoken.community/d/127). + +The Phase 1 parameters were approved by the DAO. They may be updated in future votes as the program progresses. + + + + + + + + + + + + +
ParameterValueDescription
GlobalMintCap~57,865 armmUSDC / ~48,330 armmXDAICap on mintable dREUSD — ~50% of DAO treasury per stablecoin
reusdFactor50%DAO top-up rate — 1:1 match
regFactor50%REG lock rate — 50 REG per $100 converted
userMintCap100 → 1,600 REUSDPer-wallet cap, doubling every 15 days over ~2.5 months
Phases 1+2 durationMinimum 5 monthsActive migration window from launch
+ +### DAO budget (global envelope) + +The DAO allocates up to **50%** of its treasury in **armmv3USDC** and **armmv3WXDAI** to the migration program. For reference, the proposal cites treasury holdings of about **116k** armmv3USDC and **97k** armmv3WXDAI; using half balances **scale** with **headroom** for other DAO work. The team also publishes the **mapping** to on-chain caps (e.g. **GlobalMintCap**-style limits, with illustrative figures on the order of **57,865** armmUSDC and **48,330** armmXDAI at proposal drafting time) for technical readers. + +### 100% participation rate + +The DAO **participation rate** is **100%**: for every **$100** the borrower repays in stablecoins through the mechanism, the DAO adds **another $100** to fund migration of stablecoin debt into **dREUSD**. The stated goal is to **avoid** leftover stablecoin dust being **sniped by bots** instead of cleanly feeding migration. + +### Per-wallet participation cap (stepped ramp) + +The per-**wallet** cap starts at **100 REUSD** (equivalent), then **doubles every fifteen days** versus the prior period’s cap, up to a maximum of **1,600 REUSD** (a 100 → 200 → 400 → 800 → 1,600 pattern). Over roughly **two and a half months**, each borrower’s **individual cap** rises progressively—intended as a compromise between **attractiveness**, **fair access**, and **DAO budget** control. + +### REG lock and dREUSD ratio + +**REG** must be **locked**; each locked REG unlocks at most **2 dREUSD** of migration headroom (**2 dREUSD per REG**). If the **REG price** moves a lot, governance can **vote again** to adjust the cap. + +### Minimum Phase 1 duration + +**Minimum** Phase 1 length is **five months** from **launch**. During that phase the migration program stays active, the **dREUSD borrow rate is 0%**, and **USDC / xDAI rates** follow values **voted separately** (see **RIP00042** for stablecoin rates). **Loans stay locked** in Phase 1: only **repayments** are allowed. + +### Why five months on the calendar + +The proposal explains that after about **2.5 months** the per-wallet cap reaches its **maximum** (1,600 REUSD), then about **2.5 more months** can allow **stablecoin rates** to **rise again** and **lock in** migration benefits—hence the **five-month minimum** for Phase 1. + +### What borrowers gain + +In Phase 1, borrowers can **choose** DAO-assisted repayment: part of **stablecoin** debt shifts to **dREUSD** at **0%** for that phase, instead of staying entirely on variable-rate **stablecoins** (with the **rate ceiling** set in a **different vote**). The voted parameters aim for a **balance** between DAO resources, program **appeal**, and **broad access**; they also build on a **forum poll**. + +## Motivation + +- **Immediate**: address RMM **over-use**. +- **Short term**: kick off **REUSD phase 2** via **incentivized migration** (stage 1). +- **Medium term**: prepare **RMM v4** infrastructure. +- **Long term**: grow **DAO revenue** on REUSD borrowing (the proposal uses an illustrative **~10×** multiple on the same interest volume because the DAO would capture a far larger share on REUSD debt than on classic external-supplier stablecoin pools—see the full economics section in the proposal). +- **Design themes**: optional, **progressive** (3 stages), **incentives**, **REG utility**, **modular votes**. + +## The three RMM v3.5 stages + +The program rolls out in **three stages** (incentivized migration → stabilization → full RMM). On-chain, **phases** 1–3 toggle specific capabilities (migration, dREUSD repayment, REUSD borrowing). The table below summarizes **what each phase allows**; the paragraphs after it spell out the **user journey** and how that maps to the REUSD roadmap. + + + + + + + + + + +
PhaseWhat happens
Phase 1 (active now)Stablecoin debt migration + REG lock. dREUSD at 0%. No dREUSD repayment yet.
Phase 2Migration continues. dREUSD repayment enabled (stablecoin or REUSD). Proportional REG unlock.
Phase 3End of migration. Direct REUSD borrowing against collateral. Full RMM v3.5.
+ +Phases 1 and 2 together define the **active migration window**—a **minimum of five months** from launch. Phase 3 turns on when **REUSD ecosystem phase 2** is **mature**. + +**Stage 1 — incentivized migration.** Repay stablecoins with an optional **Manager** path: DAO-funded top-up at the **voted participation rate** (**100%** in the first Phase 1 package under [**RIP00043**](https://www.tally.xyz/gov/realtoken-ecosystem-governance/proposal/640910280800835192023262285687656568134775170449659841348595080639880745966)), **0% dREUSD** for that phase, and **REG locks** for caps. This matches **Phase 1** in the table and starts the transition toward **REUSD phase 2** in roadmap terms. + +**Stage 2 — liquidity and stabilization.** Pools, arbitrage, a target peg near **1 REUSD ≈ 1 USD**, **voted** dREUSD rates, and **REUSD-denominated repayment** when the stack is ready: **Phase 2** in the table and **active REUSD phase 2** in the proposal. + +**Stage 3 — full RMM v3.5.** **Direct REUSD borrowing**, minting for **new use cases**, and **deeper markets**: **Phase 3** in the table, once REUSD phase 2 is **mature**. If stages 1 and 2 succeed, stage 3 is the **natural** next step. + +## Benefits of RMM v3.5 + +**Help repaying on the RMM.** The design aims to **make it easier** to pay down stablecoin debt through a **structured**, **incentivized** path—rather than leaving each borrower alone against high rates or stuck liquidity. + +**Cheaper repayment thanks to the DAO treasury.** The DAO **puts treasury funds to work** (per voted parameters, e.g. **100%** participation in Phase 1), which can **lower the effective cost** of repayment for users who use the Manager route. There are also **secondary markets** where people sometimes **repay RMM exposure at a discount**, e.g. by buying **armm** below par; one tool to spot offers is [Scappa](https://scappa.battistu.com/). It is important to stress that such venues **usually do not offer deep liquidity** and are **not** a **sustainable** way to deleverage the whole ecosystem at scale—RMM v3.5 instead targets a **lasting**, governance-led framework. + +**Seeing who repays.** On-chain flows and the migration program make it easier to **identify** users who **actively repay**, which supports **monitoring**, **communication**, and **parameter updates** by the DAO. + +**Preparing the ecosystem for what comes next.** v3.5 **lays groundwork** for **later projects**, especially **RMM v4** and **support for additional currencies** or markets, by proving debt, treasury, and iterative voting mechanics in production. + +**More DAO revenue on REUSD.** As **REUSD** / **dREUSD** debt grows and accrues interest under voted terms, the DAO can **capture a larger share of interest** on that leg than on classic stablecoin pools (see the original proposal economics, on the order of **~10×** on the same illustrative interest volume). + +## Step by step: How to migrate your debt + +### 1. Open the Dashboard + +Go to the **Dashboard** tab on [rmm.realtoken.network](https://rmm.realtoken.network/). A new **“REUSD program”** panel appears. + +The panel shows: + +- Your available REUSD debt quota (decreases as you convert) +- Your REG balance in the wallet (available to lock) +- REG already locked in the program +- A **Convert stablecoin debt** button +- A **Withdraw REG** button *(inactive in Phase 1)* + +### 2. Set up your conversion + +Click **Convert stablecoin debt** and fill in: + +- **Asset** — the stablecoin for your loan (e.g. USDC, xDAI) +- **Repayment amount** — the total including the DAO top-up + +The UI shows a breakdown of what will be taken from your wallet: + + + + + + + + + + +
ItemAmount
Stablecoins taken from your walletTotal ÷ 2
REG lockedStablecoins repaid ÷ 2
DAO contribution (stablecoin)Total ÷ 2
+ +> If a limit is hit (quota, budget, REG balance), an explanatory message appears in the interface. + +### 3. Approve and execute + +Approve REG and stablecoin spending from your wallet, then confirm the transaction. + +## For technical readers + +### REUSDPoolManager smart contract + +The core of the program is the `REUSDPoolManager` contract, deployed on Gnosis Chain: + +[0x371a02f425cfa011969085ff6ec4f8e53bd77360](https://gnosisscan.io/address/0x371a02f425cfa011969085ff6ec4f8e53bd77360) + +Four main functions, each active depending on the phase: + + + + + + + + + + + +
FunctionDescriptionActive phases
repayDebtWithStableRepay stablecoin debt with DAO subsidy + REG lock1 & 2
repayReusdWithStableRepay dREUSD (in stablecoin or REUSD) + proportional REG unlock2 & 3
borrowReusdBorrow REUSD against collateralPhase 3 only
withdrawRegWithdraw locked REG1, 2 & 3
+ +### REUSD reserve and related tokens + + + + + + + + + + + + +
TokenAddressNotes
REUSD reserve0x3390742Ac0DCe14EA6Fcbd5Ae02e2303C5D62Ad9Main reserve
aToken REUSD (deposit)0xd04C3b20F08B1D51F7429b2205491183A7b3583FDeposits and withdrawals blocked
variableDebtToken (dREUSD)0x00EDDAE5C334bfe4E929c775Aaa7aee1A116E077Mint reserved to REUSDManager; active burn for repayment and liquidation
stableDebtToken0xF4c85940709aF241316D806b7B07729e9de31071Disabled
InterestRate contract0x134340085739211A56fC467092058c79B3475F8BInitialized at 0%
+ +## Resources + +- [**RIP00040** on Tally](https://www.tally.xyz/gov/realtoken-ecosystem-governance/proposal/1401729377552517862159119104352447734711165592875340838992095449427178715814) +- [**RIP00043** on Tally](https://www.tally.xyz/gov/realtoken-ecosystem-governance/proposal/640910280800835192023262285687656568134775170449659841348595080639880745966) +- [Proposal on the forum (RMM v3.5 framework)](https://forum.realtoken.community/d/122) +- [Proposal on the forum (Phase 1 parameters, RIP00043)](https://forum.realtoken.community/d/127) +- [REUSD FAQ](https://faq.realt.co/en/article/what-is-the-reusd-1qotto0/) +- [Community REUSD tutorial](https://community-realt.gitbook.io/tuto-community/site-realt/bon-dachat-voucher-reusd) +- [RMM documentation](https://community-realt.gitbook.io/tuto-community/defi-realt/rmm) diff --git a/public/articles/fr/avenir-rwa-diversification-communautaire.md b/public/articles/fr/avenir-rwa-diversification-communautaire.md index a92a77d..64453c3 100644 --- a/public/articles/fr/avenir-rwa-diversification-communautaire.md +++ b/public/articles/fr/avenir-rwa-diversification-communautaire.md @@ -1,5 +1,5 @@ --- -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"] @@ -7,7 +7,7 @@ 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 diff --git a/public/articles/fr/comprendre-version-3-5-rmm.md b/public/articles/fr/comprendre-version-3-5-rmm.md new file mode 100644 index 0000000..05995b1 --- /dev/null +++ b/public/articles/fr/comprendre-version-3-5-rmm.md @@ -0,0 +1,207 @@ +--- +title: "Comprendre la version 3.5 du RMM" +date: "2026-05-13" +description: "Suite aux votes RIP00040 et RIP00043, la feuille de route RMM v3.5 avance : principes, développement et premiers paramètres votés pour la phase 1." +tags: ["rmm", "defi", "reusd", "gouvernance"] +author: "Equipe Realtoken DAO" +imageHeader: "rmm-v3-5-blog.png" +--- + +# Comprendre la version 3.5 du RMM + +Cet article **condense** la [proposition sur le forum RealToken](https://forum.realtoken.community/d/122) (cadre général du RMM v3.5), le vote [**RIP00040**](https://www.tally.xyz/gov/realtoken-ecosystem-governance/proposal/1401729377552517862159119104352447734711165592875340838992095449427178715814) qui a validé les **principes** et le **lancement du développement**, puis le vote [**RIP00043 — First parameters of RMM v3.5**](https://www.tally.xyz/gov/realtoken-ecosystem-governance/proposal/640910280800835192023262285687656568134775170449659841348595080639880745966) exposé dans la [proposition sur le forum (paramètres phase 1)](https://forum.realtoken.community/d/127). + +## Contexte : pourquoi en parler maintenant ? + +**Chronologie indicative** : + +- **16 janvier 2026** : débat sur la **crise de liquidité** du RMM. +- **5 mars 2026** : publication de la proposition v3.5. +- **17–18 mars 2026** : vote [**RIP00040**](https://www.tally.xyz/gov/realtoken-ecosystem-governance/proposal/1401729377552517862159119104352447734711165592875340838992095449427178715814) sur le lancement du développement. +- **Depuis le 28 mars 2026** : discussions sur le forum autour des paramètres. +- **11 avril 2026** : ouverture du vote [**RIP00043**](https://www.tally.xyz/gov/realtoken-ecosystem-governance/proposal/640910280800835192023262285687656568134775170449659841348595080639880745966) sur une première mouture des paramètres de **phase 1**. + +**Situation du RMM v3** (à la date des débats) : utilisation **~100 %**, taux d’emprunt en stablecoins **supérieurs à 30 %** annuel, ordre de grandeur **~14,4 M$ empruntés** pour **~48 M$ de TVL**, **déposants bloqués** sur les retraits en stablecoins. La DAO capte une **part des intérêts** sur les emprunts (paramètre de protocole), mais la saturation pénalise emprunteurs, déposants et croissance. + +**Objet du vote** [**RIP00040**](https://www.tally.xyz/gov/realtoken-ecosystem-governance/proposal/1401729377552517862159119104352447734711165592875340838992095449427178715814) : la communauté a validé le principe que **RealT développe** des **fonctionnalités optionnelles** pour **réduire la surutilisation** du RMM, décrites dans la **proposition sur le forum**, avec **mise en œuvre par phases**. Ce vote **autorise le développement** ; il pose le **cadre** du RMM v3.5. + +## En une phrase : qu’est-ce que le RMM v3.5 ? + +Le **RMM v3.5**, c’est d’abord une **option** : vous pouvez **déplacer une partie de votre dette** en stablecoins (USDC, xDAI) vers une dette en **REUSD** (**dREUSD**), si vous le souhaitez, sans remplacer le fonctionnement habituel du RMM. Au **début**, le montant migrable par portefeuille est **plafonné bas** (autour de **100 dollars** d’équivalent), puis ce **plafond monte dans le temps** pour laisser plus de place à ceux qui participent au programme. Pour en bénéficier, il faut **verrouiller des REG** dans un **coffre-fort** prévu par le protocole : chaque REG verrouillé ouvre jusqu’à **2 dREUSD** de capacité de migration. En parallèle, la **DAO** met sa **trésorerie** dans la balance : elle **double l’effet** de votre remboursement (**100 %** de participation), comme une **incitation** à migrer la dette vers la dREUSD plutôt que de la laisser uniquement en stablecoins. + +## Vote [RIP00043](https://www.tally.xyz/gov/realtoken-ecosystem-governance/proposal/640910280800835192023262285687656568134775170449659841348595080639880745966) : premiers paramètres pour la phase 1 + +Après le [**RIP00040**](https://www.tally.xyz/gov/realtoken-ecosystem-governance/proposal/1401729377552517862159119104352447734711165592875340838992095449427178715814), la DAO a voté une **première version** des paramètres applicables à la **phase 1** du déploiement du RMM v3.5, détaillée sur la [proposition sur le forum](https://forum.realtoken.community/d/127). + +Les paramètres de phase 1 ont été votés par la DAO. Ils pourront être ajustés par de futurs votes selon l’avancement du programme. + + + + + + + + + + + + +
ParamètreValeurDescription
GlobalMintCap~57 865 armmUSDC / ~48 330 armmXDAIPlafond de dREUSD mintable — ~50 % de la trésorerie DAO par stablecoin
reusdFactor50 %Taux d’abondement DAO — match à 1:1
regFactor50 %Taux de blocage REG — 50 REG pour 100 $ convertis
userMintCap100 → 1 600 REUSDPlafond par wallet, doublement toutes les 15 jours sur ~2,5 mois
Durée phases 1+2Minimum 5 moisFenêtre de migration active depuis le lancement
+ +### Budget alloué par la DAO (enveloppe globale) + +La DAO consacre jusqu’à **50 %** de sa trésorerie en **armmv3USDC** et **armmv3WXDAI** au programme de migration. À titre indicatif, la proposition mentionne une trésorerie d’environ **116 k** armmv3USDC et **97 k** armmv3WXDAI ; mobiliser la moitié allie **ampleur du dispositif** et **réserve** pour d’autres actions de la DAO. Les équipes publient en parallèle la **traduction** de ces choix en paramètres de contrat (par exemple des plafonds d’émission globaux du type **GlobalMintCap**, avec des ordres de grandeur du type **57 865** armmUSDC et **48 330** armmXDAI au moment de la rédaction de la proposition) pour les lecteurs techniques. + +### Taux de participation à 100 % + +Le taux de **participation DAO** est fixé à **100 %** : pour **100 $** remboursés par l’emprunteur en stablecoins via le mécanisme, la DAO apporte **100 $** supplémentaires pour financer la migration de la dette stablecoin vers la **dREUSD**. L’objectif affiché est d’**éviter** qu’il reste des fractions de stablecoins **récupérables par des bots** au lieu d’alimenter proprement la migration. + +### Plafond de participation par portefeuille (rampe dans le temps) + +Le plafond par **wallet** commence à **100 REUSD** (équivalent), puis **double tous les quinze jours** par rapport au plafond de la période précédente, jusqu’à un maximum de **1 600 REUSD** (séquence du type 100, 200, 400, 800 puis 1 600). Sur environ **deux mois et demi**, chaque emprunteur voit ainsi son **plafond individuel** monter progressivement, ce qui cherche un compromis entre **attractivité**, **équité** entre participants et **maîtrise** du budget DAO. + +### Verrouillage du REG et ratio dREUSD + +Les **REG** doivent être **verrouillés** ; chaque REG verrouillé ouvre un plafond de migration d’au plus **2 dREUSD** (ratio **2 dREUSD par REG**). Si le **prix du REG** évolue fortement, la gouvernance pourra **revoter** pour adapter ce plafond. + +### Durée minimale de la phase 1 + +La **durée minimale** de la phase 1 est fixée à **cinq mois** à compter de son **lancement**. Pendant cette phase, le programme de migration reste actif, le **taux d’emprunt sur la dREUSD est à 0 %**, et les **taux des stablecoins** USDC et xDAI suivent des **valeurs votées à part** (piste **RIP00042** pour les taux stablecoins). Les **emprunts restent verrouillés** pendant la phase 1 : seuls les **remboursements** sont possibles. + +### Logique de calendrier sur cinq mois + +La proposition explique qu’après environ **2,5 mois** le plafond individuel atteint son **maximum** (1 600 REUSD), puis qu’environ **2,5 mois supplémentaires** peuvent permettre une **remontée** des taux stablecoins pour **consolider** les effets du programme de migration, d’où l’horizon **minimal** de **cinq mois** pour la phase 1. + +### Ce que cela change pour l’emprunteur + +Pendant la phase 1, l’emprunteur peut **opter** pour un remboursement avec **contribution DAO** : une partie de la dette en **stablecoins** migre vers une dette en **dREUSD** portée à **0 %** pendant cette phase, au lieu de rester entièrement sur des stablecoins à taux **variable** (dont le **plafond** de taux fait l’objet d’un **vote distinct**). Les paramètres votés cherchent un **compromis** entre ressources de la DAO, attractivité du programme et accessibilité pour tous ; ils s’appuient aussi sur une **consultation** menée sur le forum. + +## Motivation + +- **Immédiat** : alternative à la surutilisation du RMM. +- **Court terme** : amorcer la **phase 2 du REUSD** via une migration **incitative** (étape 1). +- **Moyen terme** : préparer l’**infrastructure RMM v4**. +- **Long terme** : accroître les **revenus DAO** sur l’emprunt en REUSD (cadrage économique détaillé dans la proposition — ordre de grandeur **×10** sur un même volume d’intérêts illustratif, car la DAO capterait une part bien plus large sur la dette REUSD que sur les pools stablecoins classiques). +- **Principes mis en avant** : optionnel, progressif (3 étapes), incitatif, **valorisation du REG**, votes **modulaires**. + +## Les trois étapes du RMM v3.5 + +Le programme se déploie en **trois étapes** (migration incitative → stabilisation → RMM complet). Sur le protocole, on parle aussi de **phases** 1 à 3 : chacune active ou désactive des fonctions précises (migration, remboursement de la dREUSD, emprunt en REUSD). Le tableau ci-dessous résume **ce qui est permis à chaque phase** ; les paragraphes suivants détaillent le **parcours utilisateur** et le lien avec la feuille de route REUSD. + + + + + + + + + + +
PhaseCe qui se passe
Phase 1 (active maintenant)Migration de dette stablecoin + blocage REG. dREUSD à 0 %. Pas de remboursement de dREUSD encore.
Phase 2Migration continue. Remboursement de dREUSD activé (en stablecoin ou REUSD). Déblocage de REG proportionnel.
Phase 3Fin de la migration. Emprunt direct de REUSD contre collatéral. RMM v3.5 complet.
+ +Les phases 1 et 2 définissent ensemble la **fenêtre de migration active** — **durée minimale de cinq mois** depuis le lancement. La phase 3 s’active lorsque la **phase 2 de l’écosystème REUSD** est **mature**. + +**Étape 1 — migration incitative.** Remboursement en stablecoins avec une option via le **Manager** : complément financé par la DAO selon le **taux de participation voté** (**100 %** pour la première mouture de phase 1, [**RIP00043**](https://www.tally.xyz/gov/realtoken-ecosystem-governance/proposal/640910280800835192023262285687656568134775170449659841348595080639880745966)), **dREUSD sans intérêt** pendant cette phase et **REG verrouillés** pour les plafonds. Cela correspond à la **phase 1** du tableau et amorce la transition vers la **phase 2 du REUSD** au sens roadmap. + +**Étape 2 — liquidité et stabilisation.** Pools, arbitrage, parité cible d’environ **1 REUSD pour 1 $**, **intérêts sur la dREUSD** fixés par vote et **remboursement en REUSD** lorsque le dispositif est prêt : c’est la **phase 2** du tableau et la **phase 2 active du REUSD** dans la proposition. + +**Étape 3 — RMM v3.5 complet.** **Emprunt direct en REUSD**, émissions pour de **nouveaux cas d’usage** et **marché plus profond** : la **phase 3** du tableau, une fois la phase 2 REUSD **mature**. Si les étapes 1 et 2 réussissent, l’étape 3 est le prolongement **naturel** du programme. + +## Les bénéfices du RMM v3.5 + +**Une aide pour rembourser le RMM.** Le dispositif vise à **faciliter** le remboursement de la dette en stablecoins en proposant un parcours **encadré** et **incitatif**, plutôt que de laisser chaque emprunteur seul face à des taux élevés ou à une liquidité bloquée. + +**Un remboursement moins cher grâce à la trésorerie DAO.** La DAO **participe avec sa trésorerie** (selon les paramètres votés, par exemple une **participation à 100 %** en phase 1), ce qui peut **réduire le coût** effectif du remboursement pour ceux qui empruntent le chemin du Manager. Il existe aussi, en parallèle, des **marchés** où l’on peut parfois **rembourser le RMM avec une décote**, par exemple en achetant des **armm** moins chers que la valeur nominale ; un outil pour repérer des offres est [Scappa](https://scappa.battistu.com/). Il faut toutefois souligner que ce type de marché **n’a en général pas une très forte liquidité** et **n’est pas** une façon **durable** de désendetter tout l’écosystème : le RMM v3.5 vise au contraire un cadre **pérenne**, piloté par la gouvernance. + +**Mieux repérer qui rembourse.** Les flux et le dispositif de migration permettent d’**identifier plus clairement** les utilisateurs qui **remboursent** leur dette, ce qui aide le **suivi** du programme, la **communication** et l’**ajustement** des paramètres par la DAO. + +**Préparer l’écosystème pour la suite.** La v3.5 **prépare le terrain** pour des **projets ultérieurs**, en particulier **RMM v4** et l’**inclusion d’autres devises** ou marchés, en validant dans la pratique des mécaniques de dette, de trésorerie et de votes successifs. + +**Plus de revenus pour la DAO sur le REUSD.** Lorsque la dette en **REUSD** / **dREUSD** sera plus active et rémunérée selon les paramètres votés, la DAO peut **capturer une part plus élevée des intérêts** sur cette composante que sur les pools stablecoins classiques (voir le cadrage économique de la proposition d’origine, avec l’ordre de grandeur d’un facteur d’environ **×10** sur un même volume d’intérêts illustratif). + +## Étape par étape : Comment migrer votre dette + +### 1. Ouvrir le Dashboard + +Rendez-vous sur l’onglet **Dashboard** de [rmm.realtoken.network](https://rmm.realtoken.network/). Un nouveau panneau **« Programme REUSD »** apparaît. + +Le panneau affiche : + +- Votre quota de dette REUSD disponible (diminue au fil des conversions) +- Votre solde de REG dans le wallet (disponibles pour le blocage) +- Les REG déjà bloqués dans le programme +- Un bouton **Convertir la dette stablecoin** +- Un bouton **Retirer les REG** *(inactif en Phase 1)* + +### 2. Configurer votre conversion + +Cliquez sur **Convertir la dette stablecoin** et renseignez : + +- **L’actif** — le stablecoin de votre emprunt (ex. USDC, xDAI) +- **Le montant remboursé** — le total incluant l’abondement DAO + +L’interface affiche une décomposition de ce qui sera prélevé sur votre wallet : + + + + + + + + + + +
QuoiMontant
Stablecoins prélevés sur votre walletTotal ÷ 2
REG bloquésStablecoins remboursés ÷ 2
Contribution DAO (stablecoin)Total ÷ 2
+ +> Si une limite est atteinte (quota, budget, solde REG), un message explicatif apparaît dans l’interface. + +### 3. Approuver et exécuter + +Approuvez le prélèvement de REG et de stablecoins sur votre wallet, puis confirmez la transaction. + +## Pour les plus techniques + +### Smart Contract REUSDPoolManager + +Le cœur du programme est le contrat `REUSDPoolManager`, déployé sur Gnosis Chain : + +[0x371a02f425cfa011969085ff6ec4f8e53bd77360](https://gnosisscan.io/address/0x371a02f425cfa011969085ff6ec4f8e53bd77360) + +Quatre fonctions principales, chacune active selon les phases : + + + + + + + + + + + +
FonctionDescriptionPhases actives
repayDebtWithStableRemboursement de dette stablecoin avec subvention DAO + blocage REG1 & 2
repayReusdWithStableRemboursement de dREUSD (en stablecoin ou REUSD) + déblocage REG proportionnel2 & 3
borrowReusdEmprunt de REUSD contre collatéral3 uniquement
withdrawRegRetrait des REG bloqués1, 2 & 3
+ +### Réserve REUSD et tokens associés + + + + + + + + + + + + +
TokenAdresseNotes
Réserve REUSD0x3390742Ac0DCe14EA6Fcbd5Ae02e2303C5D62Ad9Réserve principale
aToken REUSD (dépôt)0xd04C3b20F08B1D51F7429b2205491183A7b3583FDépôts et retraits bloqués
variableDebtToken (dREUSD)0x00EDDAE5C334bfe4E929c775Aaa7aee1A116E077Mint réservé au REUSDManager ; burn actif pour remboursement et liquidation
stableDebtToken0xF4c85940709aF241316D806b7B07729e9de31071Désactivé
Contrat InterestRate0x134340085739211A56fC467092058c79B3475F8BInitialisé à 0 %
+ +## Ressources + +- [Vote **RIP00040** sur Tally](https://www.tally.xyz/gov/realtoken-ecosystem-governance/proposal/1401729377552517862159119104352447734711165592875340838992095449427178715814) +- [Vote **RIP00043** sur Tally](https://www.tally.xyz/gov/realtoken-ecosystem-governance/proposal/640910280800835192023262285687656568134775170449659841348595080639880745966) +- [Proposition sur le forum (cadre RMM v3.5)](https://forum.realtoken.community/d/122) +- [Proposition sur le forum (paramètres phase 1, RIP00043)](https://forum.realtoken.community/d/127) +- [FAQ REUSD](https://faq.realt.co/en/article/what-is-the-reusd-1qotto0/) +- [Tuto communautaire REUSD](https://community-realt.gitbook.io/tuto-community/site-realt/bon-dachat-voucher-reusd) +- [Documentation RMM](https://community-realt.gitbook.io/tuto-community/defi-realt/rmm) diff --git a/public/sitemap.xml b/public/sitemap.xml index ffa67a9..2ff52fe 100644 --- a/public/sitemap.xml +++ b/public/sitemap.xml @@ -81,4 +81,10 @@ 0.7 monthly + + https://realtoken.community/ressource/blog/understanding-rmm-version-3-5 + 2026-05-13 + 0.7 + monthly + diff --git a/scripts/blog-article-meta-shared.js b/scripts/blog-article-meta-shared.js new file mode 100644 index 0000000..3409695 --- /dev/null +++ b/scripts/blog-article-meta-shared.js @@ -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, '&') + .replace(/"/g, '"') + .replace(/. */ +export function escapeHtmlText(s) { + return String(s ?? '') + .replace(/&/g, '&') + .replace(/`, + ``, + ``, + ``, + ``, + ``, + ``, + `` + ] + if (imageUrl) { + const iu = escapeHtmlAttr(imageUrl) + lines.push(``) + lines.push(``) + lines.push(``) + } else { + lines.push(``) + } + 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(/]*>/i, '') + .replace(/[^<]*<\/title>/i, `<title>${escapeHtmlText(title)}`) + outHtml = outHtml.replace('', `\n ${metaBlock}\n `) + return outHtml +} diff --git a/scripts/inject-blog-social-meta.js b/scripts/inject-blog-social-meta.js new file mode 100644 index 0000000..d3ea585 --- /dev/null +++ b/scripts/inject-blog-social-meta.js @@ -0,0 +1,51 @@ +/** + * Après `vite build`, duplique dist/index.html vers dist/ressource/blog//index.html + * en injectant og:* et twitter:* dans le (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('')) { + console.error('inject-blog-social-meta: balise 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() diff --git a/src/data/blog-slugs.js b/src/data/blog-slugs.js index ee0ad00..04d5ee1 100644 --- a/src/data/blog-slugs.js +++ b/src/data/blog-slugs.js @@ -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' ] diff --git a/src/locales/en.json b/src/locales/en.json index fe2b39b..2dce195 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -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" }, @@ -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." diff --git a/src/locales/fr.json b/src/locales/fr.json index 3cc1309..e3d3680 100644 --- a/src/locales/fr.json +++ b/src/locales/fr.json @@ -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" }, @@ -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", diff --git a/src/utils/blog.js b/src/utils/blog.js index 2c65a65..819a4b1 100644 --- a/src/utils/blog.js +++ b/src/utils/blog.js @@ -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) */ diff --git a/src/views/BlogPost.vue b/src/views/BlogPost.vue index f4d3d99..378ebb7 100644 --- a/src/views/BlogPost.vue +++ b/src/views/BlogPost.vue @@ -32,7 +32,7 @@ diff --git a/src/views/MentionsLegales.vue b/src/views/MentionsLegales.vue index 6c7ed0f..b84987d 100644 --- a/src/views/MentionsLegales.vue +++ b/src/views/MentionsLegales.vue @@ -33,6 +33,11 @@ const blocks = computed(() => { { type: 'h2', textKey: 'mentions.s1Title' }, { type: 'p', textKey: 'mentions.s1Intro' }, { type: 'ul', listKey: 'mentions.s1List' }, + { type: 'h2', textKey: 'mentions.s1bTitle' }, + { type: 'p', textKey: 'mentions.s1bContent' }, + { type: 'p', textKey: 'mentions.s1bContent2' }, + { type: 'p', textKey: 'mentions.s1bContent3' }, + { type: 'p', textKey: 'mentions.s1bContent4' }, { type: 'h2', textKey: 'mentions.s2Title' }, { type: 'p', textKey: 'mentions.s2Content' }, { type: 'h2', textKey: 'mentions.s3Title' }, diff --git a/vite-plugin-blog-social-dev.js b/vite-plugin-blog-social-dev.js new file mode 100644 index 0000000..fdde356 --- /dev/null +++ b/vite-plugin-blog-social-dev.js @@ -0,0 +1,88 @@ +/** + * En développement, sert index.html déjà transformé par Vite avec les meta og/twitter + * pour /ressource/blog/ (crawlers et validateurs de cartes sans build). + */ + +import { readFileSync, existsSync } from 'node:fs' +import { join } from 'node:path' +import { getArticleSocialMeta, applyBlogMetaToHtmlTemplate } from './scripts/blog-article-meta-shared.js' + +/** Déduit l’URL de base (http/https + host) depuis la requête. */ +function requestBaseUrl(req, server) { + const host = (req.headers['x-forwarded-host'] || req.headers.host || '').toString().split(',')[0].trim() + if (!host) return 'http://localhost:5173' + const xfProto = req.headers['x-forwarded-proto'] + const proto = xfProto + ? String(xfProto).split(',')[0].trim() + : server.config.server?.https + ? 'https' + : 'http' + return `${proto}://${host}`.replace(/\/$/, '') +} + +export function blogSocialDevPlugin() { + return { + name: 'blog-social-dev-html', + enforce: 'pre', + configureServer(server) { + server.middlewares.use(async (req, res, next) => { + if (req.method !== 'GET' && req.method !== 'HEAD') { + next() + return + } + const rawUrl = req.originalUrl || req.url || '' + const pathOnly = rawUrl.split('?')[0].replace(/\/$/, '') || '/' + const m = pathOnly.match(/^\/ressource\/blog\/([^/]+)$/) + if (!m) { + next() + return + } + const slug = m[1] + if (slug.includes('.')) { + next() + return + } + + const root = server.config.root + const articlesDir = join(root, 'public', 'articles', 'en') + const mdPath = join(articlesDir, `${slug}.md`) + if (!existsSync(mdPath)) { + next() + return + } + + const baseUrl = requestBaseUrl(req, server) + const meta = getArticleSocialMeta(slug, articlesDir, baseUrl) + if (!meta) { + next() + return + } + + const indexPath = join(root, 'index.html') + if (!existsSync(indexPath)) { + next() + return + } + + const rawHtml = readFileSync(indexPath, 'utf-8') + let html + try { + html = await server.transformIndexHtml(rawUrl, rawHtml) + } catch (e) { + console.warn('[blog-social-dev] transformIndexHtml:', e?.message || e) + next() + return + } + + const finalHtml = applyBlogMetaToHtmlTemplate(html, meta) + res.statusCode = 200 + res.setHeader('Content-Type', 'text/html; charset=utf-8') + if (req.method === 'HEAD') { + res.end() + return + } + res.end(finalHtml) + }) + } + } +} diff --git a/vite.config.js b/vite.config.js index 077044d..b682b1c 100644 --- a/vite.config.js +++ b/vite.config.js @@ -1,13 +1,14 @@ import { fileURLToPath, URL } from 'node:url' -import { copyFileSync } from 'fs' import { resolve } from 'path' import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' +import { blogSocialDevPlugin } from './vite-plugin-blog-social-dev.js' // https://vite.dev/config/ export default defineConfig({ plugins: [ + blogSocialDevPlugin(), vue(), ], resolve: {