diff --git a/src/Lib/Document/VivyDocument.cc b/src/Lib/Document/VivyDocument.cc
index e643e0ca283b03b2c9938fc10e335f111a84f012..e5e4302e0f68c8507803ce6b37ed885eeb64d2d0 100644
--- a/src/Lib/Document/VivyDocument.cc
+++ b/src/Lib/Document/VivyDocument.cc
@@ -12,6 +12,9 @@
 
 using namespace Vivy;
 
+// Runtime document version, don't set it in the header!!!
+QString VivyDocument::runtimeVersion = QStringLiteral("alpha");
+
 VivyDocument::VivyDocument(const QString &documentPath, Options opt)
     : AbstractDocument(AbstractDocument::Type::Vivy, documentPath)
     , documentOptions(opt)
@@ -54,21 +57,17 @@ VivyDocument::save() const
 }
 
 void
-VivyDocument::loadSaveJsonDocumentFile(const QJsonDocument &json)
+VivyDocument::loadSaveJsonDocumentFile_ALPHA(VivyDocument *const self, const QJsonDocument &json)
 {
-    if (json.isNull())
-        throw std::logic_error("Json is null, you can't pass a null json "
-                               "document to this function");
-
     // Init from the JSON
-    documentType = json[KeyCapabilities].toString().toULongLong() & possibleCapabilities;
-    if (json[KeyName].toString() != documentName)
+    self->documentType = json[KeyCapabilities].toString().toULongLong() & possibleCapabilities;
+    if (json[KeyName].toString() != self->documentName)
         throw std::runtime_error("The document was edited outside of Vivy");
 
     if (QJsonValue audio = json[KeySubDocuments][KeySubAudio]; !audio.isNull())
-        loadSubDocument(audio.toString(), Capabilities::AudioAble);
+        self->loadSubDocument(audio.toString(), Capabilities::AudioAble);
     if (QJsonValue video = json[KeySubDocuments][KeySubVideo]; !video.isNull())
-        loadSubDocument(video.toString(), Capabilities::VideoAble);
+        self->loadSubDocument(video.toString(), Capabilities::VideoAble);
 
     if (QJsonValue internalAssSource = json[KeySubDocuments][KeyInternalAssSource];
         !internalAssSource.isNull() && internalAssSource.toBool()) {
@@ -76,10 +75,31 @@ VivyDocument::loadSaveJsonDocumentFile(const QJsonDocument &json)
         throw std::runtime_error("The internal ASS feature is not supported for now");
     } else if (QJsonValue ass = json[KeySubDocuments][KeySubAss]; !ass.isNull()) {
         // ASS in its own ASS file
-        loadSubDocument(ass.toString(), Capabilities::AssAble);
+        self->loadSubDocument(ass.toString(), Capabilities::AssAble);
     }
 }
 
+void
+VivyDocument::loadSaveJsonDocumentFile(const QJsonDocument &json)
+{
+    if (json.isNull())
+        throw std::logic_error("Json is null, you can't pass a null json "
+                               "document to this function");
+
+    const QJsonValue savedVersionJson = json[KeyDocumentVersion];
+    if (savedVersionJson.isNull())
+        throw std::runtime_error("No version present in the saved VivyDocument");
+
+    const QString savedVersion = savedVersionJson.toString();
+    for (const auto &[version, callback] : loadFunctions) {
+        if (savedVersion == version)
+            return callback(this, json);
+    }
+
+    throw std::runtime_error("Version is undefined! No way has been "
+                             "found to load the document");
+}
+
 QJsonDocument
 VivyDocument::getSaveJsonDocumentFile() const
 {
@@ -87,25 +107,29 @@ VivyDocument::getSaveJsonDocumentFile() const
     QJsonObject json;
     QJsonObject subDocumentJson;
 
-    json.insert(QString::number(KeyCapabilities),
-                QString::number(possibleCapabilities & documentType));
-    json.insert(QString::number(KeyName), documentName);
+    json.insert(KeyCapabilities, QString::number(possibleCapabilities & documentType));
+    json.insert(KeyName, documentName);
+    json.insert(KeyDocumentVersion, runtimeVersion);
 
     if (documentType & Capabilities::AudioAble)
-        subDocumentJson.insert(QString::number(KeySubAudio), audioDocument->getFilePath());
+        subDocumentJson.insert(KeySubAudio, audioDocument->getFilePath());
+
     if (documentType & Capabilities::VideoAble)
-        subDocumentJson.insert(QString::number(KeySubAudio), videoDocument->getFilePath());
+        subDocumentJson.insert(KeySubAudio, videoDocument->getFilePath());
+
     if (documentType & Capabilities::AssAble) {
         // ASS is inside Vivy document
-        if (assDocument->getFilePath() == getName())
+        if ((assDocument->getFilePath() == getName())) {
+            subDocumentJson.insert(KeyInternalAssSource, true);
             throw std::runtime_error("Unsupported save of internal ASS for now");
+        }
 
         // ASS is ints own ASS file
         else
-            subDocumentJson.insert(QString::number(KeySubAudio), assDocument->getFilePath());
+            subDocumentJson.insert(KeySubAudio, assDocument->getFilePath());
     }
 
-    json.insert(QString::number(KeySubDocuments), subDocumentJson);
+    json.insert(KeySubDocuments, subDocumentJson);
     ret.setObject(json);
     return ret;
 }
diff --git a/src/Lib/Document/VivyDocument.hh b/src/Lib/Document/VivyDocument.hh
index 692902f93f0daa20bb212ec5c17b88f6570983a3..42e40ca385f7e015040a5ee0f57ccb149431a08c 100644
--- a/src/Lib/Document/VivyDocument.hh
+++ b/src/Lib/Document/VivyDocument.hh
@@ -11,30 +11,38 @@
 #include "CRTPSubDocument.hh"
 
 #include <memory>
+#include <functional>
+#include <initializer_list>
 #include <QString>
 #include <QDir>
 #include <QJsonDocument>
 
+#define DCL_VIVY_SAVE_KEY(name) static const inline QString Key##name = QStringLiteral(#name);
+
 namespace Vivy
 {
 class VivyDocument final : public AbstractDocument {
     Q_OBJECT
     VIVY_UNMOVABLE_OBJECT(VivyDocument)
 
-    enum JsonKey {
-        KeyCapabilities,
-        KeyName,
-        KeySubDocuments,
-        KeySubAudio,
-        KeySubAss,
-        KeySubVideo,
-        KeyInternalAssSource
-    };
+    DCL_VIVY_SAVE_KEY(Capabilities)
+    DCL_VIVY_SAVE_KEY(Name)
+    DCL_VIVY_SAVE_KEY(SubDocuments)
+    DCL_VIVY_SAVE_KEY(SubAudio)
+    DCL_VIVY_SAVE_KEY(SubAss)
+    DCL_VIVY_SAVE_KEY(SubVideo)
+    DCL_VIVY_SAVE_KEY(InternalAssSource)
+    DCL_VIVY_SAVE_KEY(DocumentVersion)
+
+    using LoadFunctionForVersion =
+        std::pair<const char *, void (*)(VivyDocument *const, const QJsonDocument &)>;
 
 public:
     enum Capabilities : quint64 { AudioAble = (1 << 1), VideoAble = (1 << 2), AssAble = (1 << 3) };
     enum Options : quint64 { NoOption = 0, UntouchedByDefault = (1 << 1) };
 
+    static QString runtimeVersion;
+
     static inline const QString fileSuffix{ "vivy" };
     static inline constexpr Utils::DocumentType type     = Utils::DocumentType::Vivy;
     static constexpr inline quint64 possibleCapabilities = AudioAble | VideoAble | AssAble;
@@ -59,6 +67,11 @@ private:
     QJsonDocument getSaveJsonDocumentFile() const;
     void loadSaveJsonDocumentFile(const QJsonDocument &);
 
+    static void loadSaveJsonDocumentFile_ALPHA(VivyDocument *const, const QJsonDocument &);
+
+    static constexpr inline auto loadFunctions = { LoadFunctionForVersion{
+        "alpha", loadSaveJsonDocumentFile_ALPHA } };
+
 public:
     // Create an empty document
     explicit VivyDocument(const QString &name, Options opt = NoOption);