@@ -1,25 +1,22 @@
<!doctype html> < html class = html lang = en-us dir = ltr > < head > < meta charset = utf-8 > < meta name = viewport content = "width=device-width" > < title > Changelog | Freedoms4< / title > < link rel = stylesheet href = /css/style.min.34d0accb85f8ec23ceee8c29eef5907823b531d8acb9e6bdf45a3b37ad028d30.css integrity = "sha256-NNCsy4X47CPO7owp7vWQeCO1Mdisuea99Fo7N60CjTA=" crossorigin = anonymous > < link rel = icon href = /favicon.ico > < meta name = description content = "[1 0-06-2026]
Comments on blogposts. [08-06-2026]
<!doctype html> < html class = html lang = en-us dir = ltr > < head > < meta charset = utf-8 > < meta name = viewport content = "width=device-width" > < title > Changelog | Freedoms4< / title > < link rel = stylesheet href = /css/style.min.34d0accb85f8ec23ceee8c29eef5907823b531d8acb9e6bdf45a3b37ad028d30.css integrity = "sha256-NNCsy4X47CPO7owp7vWQeCO1Mdisuea99Fo7N60CjTA=" crossorigin = anonymous > < link rel = icon href = /favicon.ico > < meta name = description content = "[08 -06-2026]
Email registration on the website. [07-06-2026]
XMPP registration on the website. [06-06-2026]
OTP verification during sign up. [05-06-2026]
Buttons restructure. [04-06-2026]
Login/Log Out. [14-04-2026]
Changelog page. Remove year from footer copyright. " > < meta property = "og:url" content = "https://freedoms4.org/changelog/" > < meta property = "og:site_name" content = "Freedoms4" > < meta property = "og:title" content = "Changelog" > < meta property = "og:description" content = "[1 0-06-2026]
Comments on blogposts. [08-06-2026]
Changelog page. Remove year from footer copyright. " > < meta property = "og:url" content = "https://freedoms4.org/changelog/" > < meta property = "og:site_name" content = "Freedoms4" > < meta property = "og:title" content = "Changelog" > < meta property = "og:description" content = "[08 -06-2026]
Email registration on the website. [07-06-2026]
XMPP registration on the website. [06-06-2026]
OTP verification during sign up. [05-06-2026]
Buttons restructure. [04-06-2026]
Login/Log Out. [14-04-2026]
Changelog page. Remove year from footer copyright." > < meta property = "og:locale" content = "en_us" > < meta property = "og:type" content = "website" > < meta itemprop = name content = "Changelog" > < meta itemprop = description content = "[1 0-06-2026]
Comments on blogposts. [08-06-2026]
Changelog page. Remove year from footer copyright." > < meta property = "og:locale" content = "en_us" > < meta property = "og:type" content = "website" > < meta itemprop = name content = "Changelog" > < meta itemprop = description content = "[08 -06-2026]
Email registration on the website. [07-06-2026]
XMPP registration on the website. [06-06-2026]
OTP verification during sign up. [05-06-2026]
Buttons restructure. [04-06-2026]
Login/Log Out. [14-04-2026]
Changelog page. Remove year from footer copyright." > < meta itemprop = wordCount content = "36 " > < link rel = alternate type = application/rss+xml href = /changelog/index.xml title = Freedoms4 > < link rel = stylesheet href = /css/custom.css > < script > ( function ( ) { var e = localStorage . getItem ( "theme" ) ; e && document . documentElement . setAttribute ( "data-theme" , e ) , localStorage . getItem ( "f4_username" ) === "hyzen" && document . documentElement . classList . add ( "hyzen-user" ) } ) ( ) < / script > < script async src = https://plausible.freedoms4.org/js/pa-5BKl0z0RLzwrclKq4y-qk.js > < / script > < script > ( window . plausible = window . plausible || function ( ) { ( plausible . q = plausible . q || [ ] ) . push ( arguments ) } , plausible . init = plausible . init || function ( e ) { plausible . o = e || { } } ) , plausible . init ( ) < / script > < / head > < body class = body > < header class = header > < div class = brand > < img src = /logo.png alt = "Freedoms4 logo" > < h1 > Freedoms4< / h1 > < div class = brand__actions > < button class = theme-toggle id = theme-toggle aria-label = "Toggle theme" title = "Toggle dark/light mode" >
Changelog page. Remove year from footer copyright." > < meta itemprop = wordCount content = "32 " > < link rel = alternate type = application/rss+xml href = /changelog/index.xml title = Freedoms4 > < link rel = stylesheet href = /css/custom.css > < script > ( function ( ) { var e = localStorage . getItem ( "theme" ) ; e && document . documentElement . setAttribute ( "data-theme" , e ) , localStorage . getItem ( "f4_username" ) === "hyzen" && document . documentElement . classList . add ( "hyzen-user" ) } ) ( ) < / script > < script async src = https://plausible.freedoms4.org/js/pa-5BKl0z0RLzwrclKq4y-qk.js > < / script > < script > ( window . plausible = window . plausible || function ( ) { ( plausible . q = plausible . q || [ ] ) . push ( arguments ) } , plausible . init = plausible . init || function ( e ) { plausible . o = e || { } } ) , plausible . init ( ) < / script > < / head > < body class = body > < header class = header > < div class = brand > < img src = /logo.png alt = "Freedoms4 logo" > < h1 > Freedoms4< / h1 > < div class = brand__actions > < button class = theme-toggle id = theme-toggle aria-label = "Toggle theme" title = "Toggle dark/light mode" >
< svg class = "theme-toggle__sun" viewBox = "0 0 24 24" width = "16" height = "16" fill = "currentColor" > < path d = "M12 7c-2.76.0-5 2.24-5 5s2.24 5 5 5 5-2.24 5-5-2.24-5-5-5zM2 13h2c.55.0 1-.45 1-1s-.45-1-1-1H2c-.55.0-1 .45-1 1s.45 1 1 1zm18 0h2c.55.0 1-.45 1-1s-.45-1-1-1h-2c-.55.0-1 .45-1 1s.45 1 1 1zM11 2v2c0 .55.45 1 1 1s1-.45 1-1V2c0-.55-.45-1-1-1s-1 .45-1 1zm0 18v2c0 .55.45 1 1 1s1-.45 1-1v-2c0-.55-.45-1-1-1s-1 .45-1 1zM5.99 4.58c-.39-.39-1.03-.39-1.41.0-.39.39-.39 1.03.0 1.41l1.06 1.06c.39.39 1.03.39 1.41.0s.39-1.03.0-1.41L5.99 4.58zm12.37 12.37c-.39-.39-1.03-.39-1.41.0-.39.39-.39 1.03.0 1.41l1.06 1.06c.39.39 1.03.39 1.41.0.39-.39.39-1.03.0-1.41l-1.06-1.06zm1.06-12.37-1.06 1.06c-.39.39-.39 1.03.0 1.41s1.03.39 1.41.0l1.06-1.06c.39-.39.39-1.03.0-1.41s-1.03-.39-1.41.0zM7.05 18.36l-1.06 1.06c-.39.39-.39 1.03.0 1.41s1.03.39 1.41.0l1.06-1.06c.39-.39.39-1.03.0-1.41s-1.03-.39-1.41.0z" / > < / svg >
< svg class = "theme-toggle__moon" viewBox = "0 0 24 24" width = "16" height = "16" fill = "currentColor" > < path d = "M21 12.79A9 9 0 1111.21 3 7 7 0 0021 12.79z" / > < / svg > < / button > < div class = brand__auth > < input type = checkbox id = auth-dropdown class = brand__auth-check >
< label class = brand__auth-toggle for = auth-dropdown tabindex = 0 aria-label = "Account options" > < svg viewBox = "0 0 24 24" width = "12" height = "12" fill = "currentColor" > < path d = "M12 12c2.7.0 4.8-2.1 4.8-4.8S14.7 2.4 12 2.4 7.2 4.5 7.2 7.2 9.3 12 12 12zm0 2.4c-3.2.0-9.6 1.6-9.6 4.8v2.4h19.2v-2.4c0-3.2-6.4-4.8-9.6-4.8z" / > < / svg > < / label > < div class = brand__auth-links > < a href = /login/ class = "auth-link auth-link--login" > Login< / a >
@@ -29,4 +26,4 @@ Changelog page. Remove year from footer copyright."><meta itemprop=wordCount con
All updates
< / button >
< button class = rss-subscribe__item data-rss-url = https://freedoms4.org/blog/index.xml >
Blog posts< / button > < / div > < / div > < / div > < / div > < nav class = "menu language" > < ul class = "menu__list language__list" > < li class = menu__item > < a class = menu__link href = / > Home< / a > < / li > < li class = menu__item > < a class = menu__link href = /blog/ > Blog< / a > < / li > < li class = menu__item > < a class = menu__link href = /services/ > Services< / a > < / li > < li class = menu__item > < a class = menu__link href = /uninotes/ > UniNotes< / a > < / li > < li class = menu__item > < a class = menu__link href = /contact/ > Contact< / a > < / li > < / ul > < / nav > < / header > < main class = main > < h1 > Changelog< / h1 > < p > [10-06-2026]< / p > < ul > < li > < em > < strong > Comments on blogposts.< / strong > < / em > < / li > < / ul > < p > [ 08-06-2026]< / p > < ul > < li > < em > < strong > Email registration on the website.< / strong > < / em > < / li > < / ul > < p > [07-06-2026]< / p > < ul > < li > < em > < strong > XMPP registration on the website.< / strong > < / em > < / li > < / ul > < p > [06-06-2026]< / p > < ul > < li > < em > < strong > OTP verification during sign up.< / strong > < / em > < / li > < / ul > < p > [05-06-2026]< / p > < ul > < li > < em > < strong > Buttons restructure.< / strong > < / em > < / li > < / ul > < p > [04-06-2026]< / p > < ul > < li > < em > < strong > Login/Log Out.< / strong > < / em > < / li > < / ul > < p > [14-04-2026]< / p > < ul > < li > < em > < strong > Changelog page.< / strong > < / em > < / li > < li > < em > < strong > Remove year from footer copyright.< / strong > < / em > < / li > < / ul > < / main > < footer class = footer > < p class = footer__copyright-notice > © < a href = https://freedoms4.org > freedoms4.org< / a > < a href = /changelog/ > Changelog< / a > < / p > < p class = footer__theme-info > Built with < a href = https://gohugo.io > Hugo< / a > and based on < a href = https://github.com/CyrusYip/hugo-theme-yue > Yue< / a > theme< / p > < / footer > < script > ( function ( ) { document . querySelectorAll ( ".menu__item" ) . forEach ( function ( e ) { var t = e . querySelector ( "a" ) ; t && t . getAttribute ( "href" ) === "/uninotes/" && e . classList . add ( "menu__item--uninotes" ) } ) } ) ( ) < / script > < script > ( function ( ) { var e = document . getElementById ( "theme-toggle" ) ; if ( ! e ) return ; function t ( ) { var e = localStorage . getItem ( "theme" ) ; return e ? e : window . matchMedia ( "(prefers-color-scheme: light)" ) . matches ? "light" : "dark" } function n ( e ) { document . documentElement . setAttribute ( "data-theme" , e ) , localStorage . setItem ( "theme" , e ) } n ( t ( ) ) , e . addEventListener ( "click" , function ( ) { var e = document . documentElement . getAttribute ( "data-theme" ) || t ( ) ; n ( e === "dark" ? "light" : "dark" ) } ) } ) ( ) < / script > < script > ( function ( ) { var t = "https://backend.freedoms4.org/auth.php" , e = localStorage . getItem ( "f4_username" ) ; if ( ! e ) return ; function n ( e ) { var t , n , o , i , a , c , r = document . querySelector ( ".brand__auth" ) ; r && ! r . querySelector ( ".brand__auth-user" ) && ( r . classList . add ( "brand__auth--loggedin" ) , t = document . createElement ( "div" ) , t . className = "brand__auth-user" , n = document . createElement ( "button" ) , n . className = "brand__auth-user-btn" , n . setAttribute ( "aria-label" , "Account menu" ) , c = document . createElement ( "span" ) , c . innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="12" height="12" fill="currentColor"><path d="M12 12c2.7 0 4.8-2.1 4.8-4.8S14.7 2.4 12 2.4 7.2 4.5 7.2 7.2 9.3 12 12 12zm0 2.4c-3.2 0-9.6 1.6-9.6 4.8v2.4h19.2v-2.4c0-3.2-6.4-4.8-9.6-4.8z"/></svg>' , n . appendChild ( c . firstChild ) , n . appendChild ( document . createTextNode ( " " + e ) ) , o = document . createElement ( "div" ) , o . className = "brand__auth-user-dropdown" , i = document . createElement ( "button" ) , i . className = "brand__auth-user-logout" , i . textContent = "Log Out" , i . addEventListener ( "click" , s ) , e === "hyzen" && ( a = document . createElement ( "a" ) , a . className = "brand__auth-user-admin" , a . href = "/admin/" , a . textContent = "User Management" , o . appendChild ( a ) ) , o . appendChild ( i ) , o . appendChild ( i ) , t . appendChild ( n ) , t . appendChild ( o ) , r . appendChild ( t ) , n . addEventListener ( "click" , function ( e ) { e . stopPropagation ( ) , t . classList . toggle ( "is-open" ) } ) , document . addEventListener ( "click" , function ( ) { t . classList . remove ( "is-open" ) } ) ) } function s ( ) { fetch ( t , { method : "POST" , headers : { "Content-Type" : "application/json" } , credentials : "include" , body : JSON . stringify ( { action : "logout" } ) } ) . finally ( function ( ) { localStorage . removeItem ( "f4_username" ) , localStorage . removeItem ( "f4_login_time" ) , localStorage . removeItem ( "f4_session_fails" ) , window . location . reload ( ) } ) } n ( e ) } ) ( ) < / script > < script > ( function ( ) { var t , e = document . querySelector ( ".rss-subscribe" ) ; if ( ! e ) return ; t = e . querySelector ( ".rss-subscribe__btn" ) , t . addEventListener ( "click" , function ( t ) { t . stopPropagation ( ) , e . classList . toggle ( "is-open" ) } ) , document . addEventListener ( "click" , function ( t ) { e . contains ( t . target ) || e . classList . remove ( "is-open" ) } ) , e . querySelectorAll ( ".rss-subscribe__item" ) . forEach ( function ( t ) { t . addEventListener ( "click" , function ( n ) { n . stopPropagation ( ) ; var s , o = t . getAttribute ( "data-rss-url" ) , a = t . textContent ; function i ( ) { t . textContent = "Copied!" , setTimeout ( function ( ) { t . textContent = a , e . classList . remove ( "is-open" ) } , 1200 ) } try { s = document . createElement ( "textarea" ) , s . value = o , s . style . cssText = "position:fixed;top:0;left:0;opacity:0;pointer-events:none;" , document . body . appendChild ( s ) , s . focus ( ) , s . select ( ) , document . execCommand ( "copy" ) , document . body . removeChild ( s ) , i ( ) } catch { navigator . clipboard && navigator . clipboard . writeText ( o ) . then ( i ) . catch ( function ( ) { t . textContent = o } ) } } ) } ) } ) ( ) < / script > < script src = /js/session-check.js > < / script > < / body > < / html >
Blog posts< / button > < / div > < / div > < / div > < / div > < nav class = "menu language" > < ul class = "menu__list language__list" > < li class = menu__item > < a class = menu__link href = / > Home< / a > < / li > < li class = menu__item > < a class = menu__link href = /blog/ > Blog< / a > < / li > < li class = menu__item > < a class = menu__link href = /services/ > Services< / a > < / li > < li class = menu__item > < a class = menu__link href = /uninotes/ > UniNotes< / a > < / li > < li class = menu__item > < a class = menu__link href = /contact/ > Contact< / a > < / li > < / ul > < / nav > < / header > < main class = main > < h1 > Changelog< / h1 > < p > [08-06-2026]< / p > < ul > < li > < em > < strong > Email registration on the website.< / strong > < / em > < / li > < / ul > < p > [07-06-2026]< / p > < ul > < li > < em > < strong > XMPP registration on the website.< / strong > < / em > < / li > < / ul > < p > [06-06-2026]< / p > < ul > < li > < em > < strong > OTP verification during sign up.< / strong > < / em > < / li > < / ul > < p > [05-06-2026]< / p > < ul > < li > < em > < strong > Buttons restructure.< / strong > < / em > < / li > < / ul > < p > [04-06-2026]< / p > < ul > < li > < em > < strong > Login/Log Out.< / strong > < / em > < / li > < / ul > < p > [14-04-2026]< / p > < ul > < li > < em > < strong > Changelog page.< / strong > < / em > < / li > < li > < em > < strong > Remove year from footer copyright.< / strong > < / em > < / li > < / ul > < / main > < footer class = footer > < p class = footer__copyright-notice > © < a href = https://freedoms4.org > freedoms4.org< / a > < a href = /changelog/ > Changelog< / a > < / p > < p class = footer__theme-info > Built with < a href = https://gohugo.io > Hugo< / a > and based on < a href = https://github.com/CyrusYip/hugo-theme-yue > Yue< / a > theme< / p > < / footer > < script > ( function ( ) { document . querySelectorAll ( ".menu__item" ) . forEach ( function ( e ) { var t = e . querySelector ( "a" ) ; t && t . getAttribute ( "href" ) === "/uninotes/" && e . classList . add ( "menu__item--uninotes" ) } ) } ) ( ) < / script > < script > ( function ( ) { var e = document . getElementById ( "theme-toggle" ) ; if ( ! e ) return ; function t ( ) { var e = localStorage . getItem ( "theme" ) ; return e ? e : window . matchMedia ( "(prefers-color-scheme: light)" ) . matches ? "light" : "dark" } function n ( e ) { document . documentElement . setAttribute ( "data-theme" , e ) , localStorage . setItem ( "theme" , e ) } n ( t ( ) ) , e . addEventListener ( "click" , function ( ) { var e = document . documentElement . getAttribute ( "data-theme" ) || t ( ) ; n ( e === "dark" ? "light" : "dark" ) } ) } ) ( ) < / script > < script > ( function ( ) { var t = "https://backend.freedoms4.org/auth.php" , e = localStorage . getItem ( "f4_username" ) ; if ( ! e ) return ; function n ( e ) { var t , n , o , i , a , c , r = document . querySelector ( ".brand__auth" ) ; r && ! r . querySelector ( ".brand__auth-user" ) && ( r . classList . add ( "brand__auth--loggedin" ) , t = document . createElement ( "div" ) , t . className = "brand__auth-user" , n = document . createElement ( "button" ) , n . className = "brand__auth-user-btn" , n . setAttribute ( "aria-label" , "Account menu" ) , c = document . createElement ( "span" ) , c . innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="12" height="12" fill="currentColor"><path d="M12 12c2.7 0 4.8-2.1 4.8-4.8S14.7 2.4 12 2.4 7.2 4.5 7.2 7.2 9.3 12 12 12zm0 2.4c-3.2 0-9.6 1.6-9.6 4.8v2.4h19.2v-2.4c0-3.2-6.4-4.8-9.6-4.8z"/></svg>' , n . appendChild ( c . firstChild ) , n . appendChild ( document . createTextNode ( " " + e ) ) , o = document . createElement ( "div" ) , o . className = "brand__auth-user-dropdown" , i = document . createElement ( "button" ) , i . className = "brand__auth-user-logout" , i . textContent = "Log Out" , i . addEventListener ( "click" , s ) , e === "hyzen" && ( a = document . createElement ( "a" ) , a . className = "brand__auth-user-admin" , a . href = "/admin/" , a . textContent = "User Management" , o . appendChild ( a ) ) , o . appendChild ( i ) , o . appendChild ( i ) , t . appendChild ( n ) , t . appendChild ( o ) , r . appendChild ( t ) , n . addEventListener ( "click" , function ( e ) { e . stopPropagation ( ) , t . classList . toggle ( "is-open" ) } ) , document . addEventListener ( "click" , function ( ) { t . classList . remove ( "is-open" ) } ) ) } function s ( ) { fetch ( t , { method : "POST" , headers : { "Content-Type" : "application/json" } , credentials : "include" , body : JSON . stringify ( { action : "logout" } ) } ) . finally ( function ( ) { localStorage . removeItem ( "f4_username" ) , localStorage . removeItem ( "f4_login_time" ) , localStorage . removeItem ( "f4_session_fails" ) , window . location . reload ( ) } ) } n ( e ) } ) ( ) < / script > < script > ( function ( ) { var t , e = document . querySelector ( ".rss-subscribe" ) ; if ( ! e ) return ; t = e . querySelector ( ".rss-subscribe__btn" ) , t . addEventListener ( "click" , function ( t ) { t . stopPropagation ( ) , e . classList . toggle ( "is-open" ) } ) , document . addEventListener ( "click" , function ( t ) { e . contains ( t . target ) || e . classList . remove ( "is-open" ) } ) , e . querySelectorAll ( ".rss-subscribe__item" ) . forEach ( function ( t ) { t . addEventListener ( "click" , function ( n ) { n . stopPropagation ( ) ; var s , o = t . getAttribute ( "data-rss-url" ) , a = t . textContent ; function i ( ) { t . textContent = "Copied!" , setTimeout ( function ( ) { t . textContent = a , e . classList . remove ( "is-open" ) } , 1200 ) } try { s = document . createElement ( "textarea" ) , s . value = o , s . style . cssText = "position:fixed;top:0;left:0;opacity:0;pointer-events:none;" , document . body . appendChild ( s ) , s . focus ( ) , s . select ( ) , document . execCommand ( "copy" ) , document . body . removeChild ( s ) , i ( ) } catch { navigator . clipboard && navigator . clipboard . writeText ( o ) . then ( i ) . catch ( function ( ) { t . textContent = o } ) } } ) } ) } ) ( ) < / script > < script src = /js/session-check.js > < / script > < / body > < / html >