diff --git a/data/gui.xml b/data/gui.xml
index c1e9a4287..f3d4d9058 100644
--- a/data/gui.xml
+++ b/data/gui.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!-- Aseprite -->
-<!-- Copyright (C) 2018-2019  Igara Studio S.A. -->
+<!-- Copyright (C) 2018-2020  Igara Studio S.A. -->
 <!-- Copyright (C) 2001-2018  David Capello -->
-<gui version="1.3-dev">
+<gui>
   <!-- Keyboard shortcuts -->
   <keyboard version="1">
 
diff --git a/laf b/laf
index 287e30976..e48a236a9 160000
--- a/laf
+++ b/laf
@@ -1 +1 @@
-Subproject commit 287e30976e201f99e20884afea1f4a3a1d78cbdb
+Subproject commit e48a236a9fa56dffc11749ebac7a2eb75699efe7
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 0ea38fca5..c785bc62f 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -37,13 +37,6 @@ if(WIN32)
   include_directories(..)
 endif()
 
-######################################################################
-# Custom Aseprite website (for testing server-side)
-
-if(NOT "${CUSTOM_WEBSITE_URL}" STREQUAL "")
-  add_definitions(-DCUSTOM_WEBSITE_URL="${CUSTOM_WEBSITE_URL}")
-endif()
-
 ######################################################################
 # With static libcurl
 
@@ -106,6 +99,7 @@ add_subdirectory(flic)
 add_subdirectory(render)
 add_subdirectory(dio)
 add_subdirectory(ui)
+add_subdirectory(ver)
 
 if(REQUIRE_CURL)
   add_subdirectory(net)
diff --git a/src/app/CMakeLists.txt b/src/app/CMakeLists.txt
index 7c7a242a1..2708e3329 100644
--- a/src/app/CMakeLists.txt
+++ b/src/app/CMakeLists.txt
@@ -615,6 +615,10 @@ add_library(app-lib
   ${scripting_files}
   ${generated_files})
 
+if(TARGET generated_version)
+  add_dependencies(app-lib generated_version)
+endif()
+
 target_link_libraries(app-lib
   laf-base
   cfg-lib
@@ -629,6 +633,7 @@ target_link_libraries(app-lib
   laf-ft
   laf-os
   ui-lib
+  ver-lib
   undo
   ${CMARK_LIBRARIES}
   ${TINYXML_LIBRARY}
diff --git a/src/app/app.cpp b/src/app/app.cpp
index 620d8a851..e4980cfcd 100644
--- a/src/app/app.cpp
+++ b/src/app/app.cpp
@@ -67,6 +67,7 @@
 #include "render/render.h"
 #include "ui/intern.h"
 #include "ui/ui.h"
+#include "ver/info.h"
 
 #include <iostream>
 #include <memory>
@@ -514,7 +515,7 @@ App::~App()
     // no re-throw
   }
   catch (...) {
-    os::error_message("Error closing " PACKAGE ".\n(uncaught exception)");
+    os::error_message("Error closing the program.\n(uncaught exception)");
 
     // no re-throw
   }
@@ -626,7 +627,7 @@ void App::showBackupNotification(bool state)
 
 void App::updateDisplayTitleBar()
 {
-  std::string defaultTitle = PACKAGE " v" VERSION;
+  std::string defaultTitle = fmt::format("{} v{}", get_app_name(), get_app_version());
   std::string title;
 
   DocView* docView = UIContext::instance()->activeView();
diff --git a/src/app/app_menus.cpp b/src/app/app_menus.cpp
index a58a11628..0ea6e8f0b 100644
--- a/src/app/app_menus.cpp
+++ b/src/app/app_menus.cpp
@@ -1,5 +1,5 @@
 // Aseprite
-// Copyright (C) 2019  Igara Studio S.A.
+// Copyright (C) 2019-2020  Igara Studio S.A.
 // Copyright (C) 2001-2018  David Capello
 //
 // This program is distributed under the terms of
@@ -29,9 +29,11 @@
 #include "base/bind.h"
 #include "base/fs.h"
 #include "base/string.h"
+#include "fmt/format.h"
 #include "os/menus.h"
 #include "os/system.h"
 #include "ui/ui.h"
+#include "ver/info.h"
 
 #include "tinyxml.h"
 
@@ -329,12 +331,6 @@ void AppMenus::reload()
 
   m_rootMenu.reset(loadMenuById(handle, "main_menu"));
 
-#if _DEBUG
-  // Add a warning element because the user is not using the last well-known gui.xml file.
-  if (GuiXml::instance()->version() != VERSION)
-    m_rootMenu->insertChild(0, createInvalidVersionMenuitem());
-#endif
-
   LOG("MENU: Main menu loaded.\n");
 
   m_tabPopupMenu.reset(loadMenuById(handle, "tab_popup_menu"));
@@ -625,20 +621,6 @@ Widget* AppMenus::convertXmlelemToMenuitem(TiXmlElement* elem)
   return menuitem;
 }
 
-Widget* AppMenus::createInvalidVersionMenuitem()
-{
-  AppMenuItem* menuitem = new AppMenuItem("WARNING!");
-  Menu* subMenu = new Menu();
-  subMenu->addChild(new AppMenuItem(PACKAGE " is using a customized gui.xml (maybe from your HOME directory)."));
-  subMenu->addChild(new AppMenuItem("You should update your customized gui.xml file to the new version to get"));
-  subMenu->addChild(new AppMenuItem("the latest commands available."));
-  subMenu->addChild(new MenuSeparator);
-  subMenu->addChild(new AppMenuItem("You can bypass this validation adding the correct version"));
-  subMenu->addChild(new AppMenuItem("number in <gui version=\"" VERSION "\"> element."));
-  menuitem->setSubmenu(subMenu);
-  return menuitem;
-}
-
 void AppMenus::applyShortcutToMenuitemsWithCommand(Command* command,
                                                    const Params& params,
                                                    const KeyPtr& key)
@@ -724,7 +706,7 @@ void AppMenus::createNativeMenus()
 
 #ifdef __APPLE__ // Create default macOS app menus (App ... Window)
   {
-    os::MenuItemInfo about("About " PACKAGE);
+    os::MenuItemInfo about(fmt::format("About {}", get_app_name()));
     auto native = get_native_shortcut_for_command(CommandId::About());
     about.shortcut = native.shortcut;
     about.execute = [native]{
@@ -750,10 +732,10 @@ void AppMenus::createNativeMenus()
       item->setEnabled(can_call_global_shortcut(&native));
     };
 
-    os::MenuItemInfo hide("Hide " PACKAGE, os::MenuItemInfo::Hide);
+    os::MenuItemInfo hide(fmt::format("Hide {}", get_app_name()), os::MenuItemInfo::Hide);
     hide.shortcut = os::Shortcut('h', os::kKeyCmdModifier);
 
-    os::MenuItemInfo quit("Quit " PACKAGE, os::MenuItemInfo::Quit);
+    os::MenuItemInfo quit(fmt::format("Quit {}", get_app_name()), os::MenuItemInfo::Quit);
     quit.shortcut = os::Shortcut('q', os::kKeyCmdModifier);
 
     os::Menu* appMenu = menus->createMenu();
diff --git a/src/app/app_menus.h b/src/app/app_menus.h
index 929204491..d59230f58 100644
--- a/src/app/app_menus.h
+++ b/src/app/app_menus.h
@@ -1,5 +1,5 @@
 // Aseprite
-// Copyright (C) 2019  Igara Studio S.A.
+// Copyright (C) 2019-2020  Igara Studio S.A.
 // Copyright (C) 2001-2018  David Capello
 //
 // This program is distributed under the terms of
@@ -69,7 +69,6 @@ namespace app {
     Menu* loadMenuById(TiXmlHandle& handle, const char *id);
     Menu* convertXmlelemToMenu(TiXmlElement* elem);
     Widget* convertXmlelemToMenuitem(TiXmlElement* elem);
-    Widget* createInvalidVersionMenuitem();
     void applyShortcutToMenuitemsWithCommand(Menu* menu, Command* command, const Params& params,
                                              const KeyPtr& key);
     void syncNativeMenuItemKeyShortcuts(Menu* menu);
diff --git a/src/app/check_update.cpp b/src/app/check_update.cpp
index df8723103..d5a575fd7 100644
--- a/src/app/check_update.cpp
+++ b/src/app/check_update.cpp
@@ -1,4 +1,5 @@
 // Aseprite
+// Copyright (C) 2020  Igara Studio S.A.
 // Copyright (C) 2001-2017  David Capello
 //
 // This program is distributed under the terms of
@@ -19,6 +20,7 @@
 #include "base/launcher.h"
 #include "base/replace_string.h"
 #include "base/version.h"
+#include "ver/info.h"
 
 #include <ctime>
 #include <sstream>
@@ -202,7 +204,7 @@ void CheckUpdateThreadLauncher::checkForUpdates()
 
 void CheckUpdateThreadLauncher::showUI()
 {
-  std::string localVersionStr = VERSION;
+  std::string localVersionStr = get_app_version();
   base::replace_string(localVersionStr, "-x64", "");
   bool newVer = false;
 
diff --git a/src/app/cli/default_cli_delegate.cpp b/src/app/cli/default_cli_delegate.cpp
index 527a4eceb..95a6fa77d 100644
--- a/src/app/cli/default_cli_delegate.cpp
+++ b/src/app/cli/default_cli_delegate.cpp
@@ -1,5 +1,5 @@
 // Aseprite
-// Copyright (C) 2018-2019  Igara Studio S.A.
+// Copyright (C) 2018-2020  Igara Studio S.A.
 // Copyright (C) 2016-2018  David Capello
 //
 // This program is distributed under the terms of
@@ -26,6 +26,7 @@
 #include "doc/slice.h"
 #include "doc/sprite.h"
 #include "doc/tag.h"
+#include "ver/info.h"
 
 #ifdef ENABLE_SCRIPTING
   #include "app/app.h"
@@ -40,18 +41,20 @@ namespace app {
 void DefaultCliDelegate::showHelp(const AppOptions& options)
 {
   std::cout
-    << PACKAGE << " v" << VERSION << " | A pixel art program\n" << COPYRIGHT
+    << get_app_name() << " v" << get_app_version()
+    << " | A pixel art program\n"
+    << get_app_copyright()
     << "\n\nUsage:\n"
     << "  " << options.exeName() << " [OPTIONS] [FILES]...\n\n"
     << "Options:\n"
     << options.programOptions()
-    << "\nFind more information in " << PACKAGE
-    << " web site: " << WEBSITE << "\n\n";
+    << "\nFind more information in " << get_app_name()
+    << " web site: " << get_app_url() << "\n\n";
 }
 
 void DefaultCliDelegate::showVersion()
 {
-  std::cout << PACKAGE << ' ' << VERSION << '\n';
+  std::cout << get_app_name() << ' ' << get_app_version() << '\n';
 }
 
 void DefaultCliDelegate::afterOpenFile(const CliOpenFile& cof)
diff --git a/src/app/cli/preview_cli_delegate.cpp b/src/app/cli/preview_cli_delegate.cpp
index 0098ccdfb..13ef53ce0 100644
--- a/src/app/cli/preview_cli_delegate.cpp
+++ b/src/app/cli/preview_cli_delegate.cpp
@@ -1,5 +1,5 @@
 // Aseprite
-// Copyright (C) 2018-2019  Igara Studio S.A.
+// Copyright (C) 2018-2020  Igara Studio S.A.
 // Copyright (C) 2016-2018  David Capello
 //
 // This program is distributed under the terms of
@@ -19,6 +19,8 @@
 #include "base/fs.h"
 #include "doc/layer.h"
 #include "doc/sprite.h"
+#include "fmt/format.h"
+#include "ver/info.h"
 
 #include <iostream>
 #include <memory>
@@ -27,12 +29,12 @@ namespace app {
 
 void PreviewCliDelegate::showHelp(const AppOptions& options)
 {
-  std::cout << "- Show " PACKAGE " CLI usage\n";
+  std::cout << fmt::format("- Show {} CLI usage\n", get_app_name());
 }
 
 void PreviewCliDelegate::showVersion()
 {
-  std::cout << "- Show " PACKAGE " version\n";
+  std::cout << fmt::format("- Show {} version\n", get_app_name());
 }
 
 void PreviewCliDelegate::uiMode()
diff --git a/src/app/commands/cmd_about.cpp b/src/app/commands/cmd_about.cpp
index ce9c715b0..e4e46ee82 100644
--- a/src/app/commands/cmd_about.cpp
+++ b/src/app/commands/cmd_about.cpp
@@ -1,4 +1,5 @@
 // Aseprite
+// Copyright (C) 2020  Igara Studio S.A.
 // Copyright (C) 2001-2018  David Capello
 //
 // This program is distributed under the terms of
@@ -13,6 +14,8 @@
 #include "app/modules/gui.h"
 #include "app/ui/main_window.h"
 #include "base/bind.h"
+#include "fmt/format.h"
+#include "ver/info.h"
 
 #include "about.xml.h"
 
@@ -36,7 +39,7 @@ AboutCommand::AboutCommand()
 void AboutCommand::onExecute(Context* context)
 {
   gen::About window;
-  window.title()->setText(PACKAGE " v" VERSION);
+  window.title()->setText(fmt::format("{} v{}", get_app_name(), get_app_version()));
   window.licenses()->Click.connect(
     [&window]{
       window.closeWindow(nullptr);
diff --git a/src/app/commands/cmd_launch.cpp b/src/app/commands/cmd_launch.cpp
index 5401c49e5..7ddb429e7 100644
--- a/src/app/commands/cmd_launch.cpp
+++ b/src/app/commands/cmd_launch.cpp
@@ -1,4 +1,5 @@
 // Aseprite
+// Copyright (C) 2020  Igara Studio S.A.
 // Copyright (C) 2001-2017  David Capello
 //
 // This program is distributed under the terms of
@@ -12,6 +13,7 @@
 #include "app/commands/params.h"
 #include "app/launcher.h"
 #include "base/fs.h"
+#include "ver/info.h"
 
 namespace app {
 
@@ -42,7 +44,7 @@ void LaunchCommand::onLoadParams(const Params& params)
   m_path = params.get("path");
 
   if (m_type == Url && !m_path.empty() && m_path[0] == '/') {
-    m_path = WEBSITE + m_path.substr(1);
+    m_path = std::string(get_app_url()) + m_path.substr(1);
   }
 }
 
diff --git a/src/app/crash/session.cpp b/src/app/crash/session.cpp
index 9edd6ad32..210c8bd29 100644
--- a/src/app/crash/session.cpp
+++ b/src/app/crash/session.cpp
@@ -1,5 +1,5 @@
 // Aseprite
-// Copyright (C) 2019  Igara Studio S.A.
+// Copyright (C) 2019-2020  Igara Studio S.A.
 // Copyright (C) 2001-2018  David Capello
 //
 // This program is distributed under the terms of
@@ -31,6 +31,7 @@
 #include "base/time.h"
 #include "doc/cancel_io.h"
 #include "fmt/format.h"
+#include "ver/info.h"
 
 namespace app {
 namespace crash {
@@ -170,7 +171,7 @@ void Session::create(base::pid pid)
   std::ofstream verf(FSTREAM_PATH(verFilename()));
 
   pidf << m_pid;
-  verf << VERSION;
+  verf << get_app_version();
 }
 
 void Session::close()
diff --git a/src/app/doc_exporter.cpp b/src/app/doc_exporter.cpp
index af024326e..bbb25a9b8 100644
--- a/src/app/doc_exporter.cpp
+++ b/src/app/doc_exporter.cpp
@@ -44,6 +44,7 @@
 #include "render/dithering.h"
 #include "render/ordered_dither.h"
 #include "render/render.h"
+#include "ver/info.h"
 
 #include <cstdio>
 #include <fstream>
@@ -1299,8 +1300,8 @@ void DocExporter::createDataFile(const Samples& samples,
   // "meta" property
   os << ",\n"
      << " \"meta\": {\n"
-     << "  \"app\": \"" << WEBSITE << "\",\n"
-     << "  \"version\": \"" << VERSION << "\",\n";
+     << "  \"app\": \"" << get_app_url() << "\",\n"
+     << "  \"version\": \"" << get_app_version() << "\",\n";
 
   if (!m_textureFilename.empty())
     os << "  \"image\": \""
diff --git a/src/app/file/ase_format.cpp b/src/app/file/ase_format.cpp
index f674249c9..6ea09c5bd 100644
--- a/src/app/file/ase_format.cpp
+++ b/src/app/file/ase_format.cpp
@@ -1,5 +1,5 @@
 // Aseprite
-// Copyright (C) 2018-2019  Igara Studio S.A.
+// Copyright (C) 2018-2020  Igara Studio S.A.
 // Copyright (C) 2001-2018  David Capello
 //
 // This program is distributed under the terms of
@@ -27,6 +27,7 @@
 #include "fixmath/fixmath.h"
 #include "fmt/format.h"
 #include "ui/alert.h"
+#include "ver/info.h"
 #include "zlib.h"
 
 #include <cstdio>
@@ -223,7 +224,7 @@ bool AseFormat::onPostLoad(FileOp* fop)
 
   // Forward Compatibility: In 1.1 we convert a file with layer groups
   // (saved with 1.2) as top level layers
-  std::string ver = VERSION;
+  std::string ver = get_app_version();
   bool flat = (ver[0] == '1' &&
                ver[1] == '.' &&
                ver[2] == '1');
@@ -240,7 +241,7 @@ bool AseFormat::onPostLoad(FileOp* fop)
             "<<Note: Layers inside groups will be converted to top level layers."
             "||&Yes||&No",
             base::get_file_name(fop->filename()),
-            PACKAGE, ver)) != 1) {
+            get_app_name(), ver)) != 1) {
       return false;
     }
     ase_ungroup_all(group);
diff --git a/src/app/file/file.cpp b/src/app/file/file.cpp
index 1059adaeb..e400752d4 100644
--- a/src/app/file/file.cpp
+++ b/src/app/file/file.cpp
@@ -1,5 +1,5 @@
 // Aseprite
-// Copyright (C) 2018-2019  Igara Studio S.A.
+// Copyright (C) 2018-2020  Igara Studio S.A.
 // Copyright (C) 2001-2018  David Capello
 //
 // This program is distributed under the terms of
@@ -41,6 +41,7 @@
 #include "ui/alert.h"
 #include "ui/listitem.h"
 #include "ui/system.h"
+#include "ver/info.h"
 
 #include "ask_for_color_profile.xml.h"
 #include "open_sequence.xml.h"
@@ -200,7 +201,7 @@ FileOp* FileOp::createLoadDocumentOperation(Context* context,
     dio::detect_format(filename));
   if (!fop->m_format ||
       !fop->m_format->support(FILE_SUPPORT_LOAD)) {
-    fop->setError("%s can't load \"%s\" file (\"%s\")\n", PACKAGE,
+    fop->setError("%s can't load \"%s\" file (\"%s\")\n", get_app_name(),
                   filename.c_str(), base::get_file_extension(filename).c_str());
     goto done;
   }
@@ -354,7 +355,7 @@ FileOp* FileOp::createSaveDocumentOperation(const Context* context,
     dio::detect_format_by_file_extension(filename));
   if (!fop->m_format ||
       !fop->m_format->support(FILE_SUPPORT_SAVE)) {
-    fop->setError("%s can't save \"%s\" file (\"%s\")\n", PACKAGE,
+    fop->setError("%s can't save \"%s\" file (\"%s\")\n", get_app_name(),
                   filename.c_str(), base::get_file_extension(filename).c_str());
     return fop.release();
   }
@@ -834,8 +835,9 @@ void FileOp::operate(IFileOpProgress* progress)
     }
 #else
     setError(
-      "Save operation is not supported in trial version.\n"
-      "Go to " WEBSITE_DOWNLOAD " and get the full-version.");
+      fmt::format("Save operation is not supported in trial version.\n"
+                  "Go to {} and get the full-version.",
+                  get_app_download_url()));
 #endif
   }
 
diff --git a/src/app/gui_xml.cpp b/src/app/gui_xml.cpp
index ca0e7771e..0e17d49b5 100644
--- a/src/app/gui_xml.cpp
+++ b/src/app/gui_xml.cpp
@@ -1,4 +1,5 @@
 // Aseprite
+// Copyright (C) 2020  Igara Studio S.A.
 // Copyright (C) 2001-2016  David Capello
 //
 // This program is distributed under the terms of
@@ -40,17 +41,4 @@ GuiXml::GuiXml()
   m_doc = app::open_xml(rf.filename());
 }
 
-std::string GuiXml::version()
-{
-  TiXmlHandle handle(m_doc.get());
-  TiXmlElement* xmlKey = handle.FirstChild("gui").ToElement();
-
-  if (xmlKey && xmlKey->Attribute("version")) {
-    const char* guixml_version = xmlKey->Attribute("version");
-    return guixml_version;
-  }
-  else
-    return "";
-}
-
 } // namespace app
diff --git a/src/app/gui_xml.h b/src/app/gui_xml.h
index c06c1a967..dde09790e 100644
--- a/src/app/gui_xml.h
+++ b/src/app/gui_xml.h
@@ -1,4 +1,5 @@
 // Aseprite
+// Copyright (C) 2020  Igara Studio S.A.
 // Copyright (C) 2001-2015  David Capello
 //
 // This program is distributed under the terms of
@@ -32,8 +33,6 @@ namespace app {
       return m_doc->Value();
     }
 
-    std::string version();
-
   private:
     GuiXml();
 
diff --git a/src/app/log.cpp b/src/app/log.cpp
index e690093d1..25af7bf47 100644
--- a/src/app/log.cpp
+++ b/src/app/log.cpp
@@ -1,4 +1,5 @@
 // Aseprite
+// Copyright (C) 2020  Igara Studio S.A.
 // Copyright (C) 2001-2016  David Capello
 //
 // This program is distributed under the terms of
@@ -13,6 +14,8 @@
 #include "app/app.h"
 #include "app/resource_finder.h"
 #include "base/log.h"
+#include "fmt/format.h"
+#include "ver/info.h"
 
 namespace app {
 
@@ -20,10 +23,14 @@ LoggerModule::LoggerModule(bool createLogInDesktop)
 {
   app::ResourceFinder rf(false);
 
-  if (createLogInDesktop)
-    rf.includeDesktopDir(PACKAGE "-v" VERSION "-DebugOutput.txt");
-  else
-    rf.includeUserDir("aseprite.log");
+  if (createLogInDesktop) {
+    rf.includeDesktopDir(fmt::format("{}-v{}-DebugOutput.txt",
+                                     get_app_name(),
+                                     get_app_version()).c_str());
+  }
+  else {
+    rf.includeUserDir(fmt::format("{}.log", get_app_name()).c_str());
+  }
 
   auto filename = rf.defaultFilename();
   base::set_log_filename(filename.c_str());
diff --git a/src/app/res/http_loader.cpp b/src/app/res/http_loader.cpp
index dc39d4be6..576886542 100644
--- a/src/app/res/http_loader.cpp
+++ b/src/app/res/http_loader.cpp
@@ -1,4 +1,5 @@
 // Aseprite
+// Copyright (C) 2020  Igara Studio S.A.
 // Copyright (C) 2001-2016  David Capello
 //
 // This program is distributed under the terms of
@@ -18,6 +19,7 @@
 #include "base/string.h"
 #include "net/http_request.h"
 #include "net/http_response.h"
+#include "ver/info.h"
 
 #include <fstream>
 
@@ -49,7 +51,7 @@ void HttpLoader::threadHttpRequest()
 
     LOG("HTTP: Sending http request to %s\n", m_url.c_str());
 
-    std::string dir = base::join_path(base::get_temp_path(), PACKAGE);
+    std::string dir = base::join_path(base::get_temp_path(), get_app_name());
     base::make_all_directories(dir);
 
     std::string fn = m_url;
diff --git a/src/app/resource_finder.cpp b/src/app/resource_finder.cpp
index 4c20eb929..67e366a1f 100644
--- a/src/app/resource_finder.cpp
+++ b/src/app/resource_finder.cpp
@@ -1,5 +1,5 @@
 // Aseprite
-// Copyright (C) 2019  Igara Studio S.A.
+// Copyright (C) 2019-2020  Igara Studio S.A.
 // Copyright (C) 2001-2016  David Capello
 //
 // This program is distributed under the terms of
@@ -14,6 +14,7 @@
 #include "app/app.h"
 #include "base/fs.h"
 #include "base/string.h"
+#include "ver/info.h"
 
 #include <cstdio>
 #include <cstdlib>
@@ -178,7 +179,7 @@ void ResourceFinder::includeUserDir(const char* filename)
     // $HOME/Library/Application Support/Aseprite/filename
     addPath(
       base::join_path(
-        base::join_path(base::get_lib_app_support_path(), PACKAGE),
+        base::join_path(base::get_lib_app_support_path(), get_app_name()),
         filename).c_str());
 
   #else  // !__APPLE__
diff --git a/src/app/script/app_object.cpp b/src/app/script/app_object.cpp
index f44338727..96786e651 100644
--- a/src/app/script/app_object.cpp
+++ b/src/app/script/app_object.cpp
@@ -44,6 +44,7 @@
 #include "doc/tag.h"
 #include "render/render.h"
 #include "ui/alert.h"
+#include "ver/info.h"
 
 #include <iostream>
 
@@ -483,7 +484,7 @@ int App_get_isUIAvailable(lua_State* L)
 
 int App_get_version(lua_State* L)
 {
-  std::string ver = VERSION;
+  std::string ver = get_app_version();
   base::replace_string(ver, "-x64", ""); // Remove "-x64" suffix
   push_version(L, base::Version(ver));
   return 1;
diff --git a/src/app/send_crash.cpp b/src/app/send_crash.cpp
index 904b66de7..39a0d1402 100644
--- a/src/app/send_crash.cpp
+++ b/src/app/send_crash.cpp
@@ -19,8 +19,10 @@
 #include "base/bind.h"
 #include "base/fs.h"
 #include "base/launcher.h"
+#include "fmt/format.h"
 #include "ui/alert.h"
 #include "ui/system.h"
+#include "ver/info.h"
 
 #include "send_crash.xml.h"
 
@@ -30,9 +32,11 @@ namespace app {
 std::string SendCrash::DefaultMemoryDumpFilename()
 {
 #ifdef _WIN32
-  const char* kDefaultCrashName = PACKAGE "-crash-" VERSION ".dmp";
+  std::string kDefaultCrashName = fmt::format("{}-crash-{}.dmp",
+                                              get_app_name(),
+                                              get_app_version());
   ResourceFinder rf;
-  rf.includeUserDir(kDefaultCrashName);
+  rf.includeUserDir(kDefaultCrashName.c_str());
   return rf.getFirstOrCreateDefault();
 #else
   return std::string();
@@ -76,13 +80,13 @@ void SendCrash::search()
       std::string dir = rf.defaultFilename();
       if (base::is_directory(dir)) {
         std::vector<std::string> candidates;
-        int n = std::strlen(PACKAGE);
+        int n = std::strlen(get_app_name());
         for (const auto& fn : base::list_files(dir)) {
           // Cancel everything
           if (m_task.canceled())
             return;
 
-          if (base::utf8_icmp(PACKAGE, fn, n) == 0) {
+          if (base::utf8_icmp(get_app_name(), fn, n) == 0) {
             candidates.push_back(fn);
           }
         }
@@ -125,13 +129,13 @@ void SendCrash::notificationClick()
   app::gen::SendCrash dlg;
 
 #if _WIN32
-  // Only on Windows, if the current version is a "development"
-  // version (i.e. the VERSION macro contains the "dev" word), the
-  // .dmp file is useless for us. This is because we need the .exe +
-  // .pdb + source code used in the compilation process to make some
-  // sense of the .dmp file.
+  // Only on Windows, if the current version is a development version
+  // (i.e. the get_app_version() contains "-dev"), the .dmp
+  // file is useless for us. This is because we need the .exe + .pdb +
+  // source code used in the compilation process to make some sense of
+  // the .dmp file.
 
-  bool isDev = (std::string(VERSION).find("dev") != std::string::npos);
+  bool isDev = (std::string(get_app_version()).find("-dev") != std::string::npos);
   if (isDev) {
     dlg.official()->setVisible(false);
     dlg.devFilename()->setText(m_dumpFilename);
@@ -139,8 +143,8 @@ void SendCrash::notificationClick()
   }
   else
 #endif  // On other platforms the crash file might be useful even in
-        // the -dev version (e.g. on macOS it's a text file with stack
-        // traces).
+        // the "-dev" version (e.g. on macOS it's a text file with
+        // stack traces).
   {
     dlg.dev()->setVisible(false);
     dlg.filename()->setText(m_dumpFilename);
diff --git a/src/app/shell.cpp b/src/app/shell.cpp
index a0d5f0ca9..825d489cd 100644
--- a/src/app/shell.cpp
+++ b/src/app/shell.cpp
@@ -1,4 +1,5 @@
 // Aseprite
+// Copyright (C) 2020  Igara Studio S.A.
 // Copyright (C) 2001-2016  David Capello
 //
 // This program is distributed under the terms of
@@ -14,7 +15,9 @@
 
 #include "app/shell.h"
 
+#include "fmt/format.h"
 #include "script/engine.h"
+#include "ver/info.h"
 
 #include <iostream>
 #include <string>
@@ -31,7 +34,8 @@ Shell::~Shell()
 
 void Shell::run(script::Engine& engine)
 {
-  std::cout << "Welcome to " PACKAGE " v" VERSION " Interactive Console" << std::endl;
+  std::cout << fmt::format("Welcome to {} v{} Interactive Console",
+                           get_app_name(), get_app_version()) << std::endl;
   std::string line;
   while (std::getline(std::cin, line)) {
     engine.evalCode(line);
diff --git a/src/app/ui/data_recovery_view.cpp b/src/app/ui/data_recovery_view.cpp
index 185c6431f..f46075c7f 100644
--- a/src/app/ui/data_recovery_view.cpp
+++ b/src/app/ui/data_recovery_view.cpp
@@ -1,5 +1,5 @@
 // Aseprite
-// Copyright (C) 2019  Igara Studio S.A.
+// Copyright (C) 2019-2020  Igara Studio S.A.
 // Copyright (C) 2001-2017  David Capello
 //
 // This program is distributed under the terms of
@@ -40,6 +40,7 @@
 #include "ui/size_hint_event.h"
 #include "ui/system.h"
 #include "ui/view.h"
+#include "ver/info.h"
 
 #include <algorithm>
 
@@ -314,7 +315,7 @@ void DataRecoveryView::fillListWith(const bool crashes)
     }
 
     std::string title = session->name();
-    if (session->version() != VERSION)
+    if (session->version() != get_app_version())
       title =
         fmt::format(Strings::recover_files_incompatible(),
                     title, session->version());
diff --git a/src/app/ui/devconsole_view.cpp b/src/app/ui/devconsole_view.cpp
index a6fb6be70..d5626947a 100644
--- a/src/app/ui/devconsole_view.cpp
+++ b/src/app/ui/devconsole_view.cpp
@@ -1,4 +1,5 @@
 // Aseprite
+// Copyright (C) 2020  Igara Studio S.A.
 // Copyright (C) 2001-2018  David Capello
 //
 // This program is distributed under the terms of
@@ -18,11 +19,13 @@
 #include "app/app_menus.h"
 #include "app/ui/skin/skin_theme.h"
 #include "app/ui/workspace.h"
+#include "fmt/format.h"
 #include "ui/entry.h"
 #include "ui/message.h"
 #include "ui/system.h"
 #include "ui/textbox.h"
 #include "ui/view.h"
+#include "ver/info.h"
 
 namespace app {
 
@@ -64,7 +67,8 @@ protected:
 
 DevConsoleView::DevConsoleView()
   : Box(VERTICAL)
-  , m_textBox("Welcome to " PACKAGE " v" VERSION " Console\n(Experimental)", LEFT)
+  , m_textBox(fmt::format("Welcome to {} v{} Console\n(Experimental)",
+                          get_app_name(), get_app_version()), LEFT)
   , m_label(">")
   , m_entry(new CommmandEntry)
   , m_engine(App::instance()->scriptEngine())
diff --git a/src/app/ui/home_view.cpp b/src/app/ui/home_view.cpp
index 2db7c7c63..c8cc5c974 100644
--- a/src/app/ui/home_view.cpp
+++ b/src/app/ui/home_view.cpp
@@ -1,5 +1,5 @@
 // Aseprite
-// Copyright (C) 2019  Igara Studio S.A.
+// Copyright (C) 2019-2020  Igara Studio S.A.
 // Copyright (C) 2001-2018  David Capello
 //
 // This program is distributed under the terms of
@@ -33,6 +33,7 @@
 #include "ui/system.h"
 #include "ui/textbox.h"
 #include "ui/view.h"
+#include "ver/info.h"
 
 #ifdef ENABLE_NEWS
 #include "app/ui/news_listbox.h"
@@ -177,7 +178,7 @@ void HomeView::onCheckingUpdates()
 void HomeView::onUpToDate()
 {
   checkUpdate()->setText(
-    fmt::format(Strings::home_view_is_up_to_date(), PACKAGE));
+    fmt::format(Strings::home_view_is_up_to_date(), get_app_name()));
   checkUpdate()->setVisible(true);
 
   layout();
@@ -186,7 +187,8 @@ void HomeView::onUpToDate()
 void HomeView::onNewUpdate(const std::string& url, const std::string& version)
 {
   checkUpdate()->setText(
-    fmt::format(Strings::home_view_new_version_available(), PACKAGE, version));
+    fmt::format(Strings::home_view_new_version_available(),
+                get_app_name(), version));
   checkUpdate()->setUrl(url);
   checkUpdate()->setVisible(true);
   checkUpdate()->InitTheme.connect(
diff --git a/src/app/ui/news_listbox.cpp b/src/app/ui/news_listbox.cpp
index 348720b2c..63012bf8c 100644
--- a/src/app/ui/news_listbox.cpp
+++ b/src/app/ui/news_listbox.cpp
@@ -1,4 +1,5 @@
 // Aseprite
+// Copyright (C) 2020  Igara Studio S.A.
 // Copyright (C) 2001-2017  David Capello
 //
 // This program is distributed under the terms of
@@ -23,6 +24,7 @@
 #include "ui/paint_event.h"
 #include "ui/size_hint_event.h"
 #include "ui/view.h"
+#include "ver/info.h"
 
 #include "tinyxml.h"
 
@@ -209,7 +211,7 @@ void NewsListBox::reload()
   if (view)
     view->updateView();
 
-  m_loader = new HttpLoader(WEBSITE_NEWS_RSS);
+  m_loader = new HttpLoader(get_app_news_rss_url());
   m_timer.start();
 }
 
diff --git a/src/app/ui/status_bar.cpp b/src/app/ui/status_bar.cpp
index ec93e7e14..28059dcfb 100644
--- a/src/app/ui/status_bar.cpp
+++ b/src/app/ui/status_bar.cpp
@@ -1,5 +1,5 @@
 // Aseprite
-// Copyright (C) 2018-2019  Igara Studio S.A.
+// Copyright (C) 2018-2020  Igara Studio S.A.
 // Copyright (C) 2001-2018  David Capello
 //
 // This program is distributed under the terms of
@@ -46,6 +46,7 @@
 #include "os/font.h"
 #include "os/surface.h"
 #include "ui/ui.h"
+#include "ver/info.h"
 
 #include <algorithm>
 #include <cstdarg>
@@ -621,7 +622,7 @@ void StatusBar::showDefaultText()
   }
   else if (App::instance()->mainWindow()->isHomeSelected()) {
     setStatusText(0, "-- %s %s by David & Gaspar Capello -- Igara Studio --",
-                  PACKAGE, VERSION);
+                  get_app_name(), get_app_version());
   }
   else {
     clearText();
diff --git a/src/config.h b/src/config.h
index 5a592a985..900148c05 100644
--- a/src/config.h
+++ b/src/config.h
@@ -1,15 +1,15 @@
 // Aseprite
-// Copyright (C) 2018-2019  Igara Studio S.A.
+// Copyright (C) 2018-2020  Igara Studio S.A.
 // Copyright (C) 2001-2018  David Capello
 //
 // This program is distributed under the terms of
 // the End-User License Agreement for Aseprite.
 
-#ifdef __ASE_CONFIG_H
+#ifdef __ASEPRITE_CONFIG_H
 #error You cannot use config.h two times
 #endif
 
-#define __ASE_CONFIG_H
+#define __ASEPRITE_CONFIG_H
 
 // In MSVC
 #ifdef _MSC_VER
@@ -26,21 +26,6 @@
   #pragma warning(disable:4710)
 #endif
 
-// General information
-#define PACKAGE "Aseprite"
-#define VERSION "1.3-dev"
-
-#ifdef CUSTOM_WEBSITE_URL
-#define WEBSITE                 CUSTOM_WEBSITE_URL // To test web server
-#else
-#define WEBSITE                 "http://www.aseprite.org/"
-#endif
-#define WEBSITE_DOWNLOAD        WEBSITE "download/"
-#define WEBSITE_CONTRIBUTORS    WEBSITE "contributors/"
-#define WEBSITE_NEWS_RSS        "http://blog.aseprite.org/rss"
-#define UPDATE_URL              WEBSITE "update/?xml=1"
-#define COPYRIGHT               "Copyright (C) 2001-2019 Igara Studio S.A."
-
 #include "base/base.h"
 #include "base/debug.h"
 #include "base/log.h"
diff --git a/src/ui/menu.cpp b/src/ui/menu.cpp
index 0e060055c..5feef096b 100644
--- a/src/ui/menu.cpp
+++ b/src/ui/menu.cpp
@@ -1,5 +1,5 @@
 // Aseprite UI Library
-// Copyright (C) 2018-2019  Igara Studio S.A.
+// Copyright (C) 2018-2020  Igara Studio S.A.
 // Copyright (C) 2001-2018  David Capello
 //
 // This file is released under the terms of the MIT license.
@@ -302,10 +302,11 @@ Widget* Menu::findItemById(const char* id)
     return result;
   for (auto child : children()) {
     if (child->type() == kMenuItemWidget) {
-      result = static_cast<MenuItem*>(child)
-        ->getSubmenu()->findItemById(id);
-      if (result)
-        return result;
+      if (Menu* submenu = static_cast<MenuItem*>(child)->getSubmenu()) {
+        result = submenu->findItemById(id);
+        if (result)
+          return result;
+      }
     }
   }
   return nullptr;
diff --git a/src/updater/CMakeLists.txt b/src/updater/CMakeLists.txt
index 8e704e1c0..4a77c7099 100644
--- a/src/updater/CMakeLists.txt
+++ b/src/updater/CMakeLists.txt
@@ -1,4 +1,5 @@
 # ASEPRITE
+# Copyright (C) 2020  Igara Studio S.A.
 # Copyright (C) 2001-2017  David Capello
 
 set(UPDATER_LIB_SOURCES
@@ -16,4 +17,5 @@ add_library(updater-lib ${UPDATER_LIB_SOURCES})
 target_link_libraries(updater-lib
   net-lib
   cfg-lib
+  ver-lib
   ${TINYXML_LIBRARY})
diff --git a/src/updater/check_update.cpp b/src/updater/check_update.cpp
index 0f1efe73c..af168fe1d 100644
--- a/src/updater/check_update.cpp
+++ b/src/updater/check_update.cpp
@@ -1,4 +1,5 @@
 // Aseprite
+// Copyright (C) 2020  Igara Studio S.A.
 // Copyright (C) 2001-2018  David Capello
 //
 // This program is distributed under the terms of
@@ -18,6 +19,7 @@
 #include "net/http_response.h"
 #include "tinyxml.h"
 #include "updater/user_agent.h"
+#include "ver/info.h"
 
 #include <iostream>
 #include <memory>
@@ -97,12 +99,7 @@ public:
 
   bool checkNewVersion(const Uuid& uuid, const std::string& extraParams, CheckUpdateDelegate* delegate)
   {
-#ifndef UPDATE_URL
-#define UPDATE_URL ""
-#pragma message("warning: Define UPDATE_URL macro")
-#endif
-
-    std::string url = UPDATE_URL;
+    std::string url = get_app_update_url();
     if (!uuid.empty()) {
       url += "&uuid=";
       url += uuid;
diff --git a/src/updater/user_agent.cpp b/src/updater/user_agent.cpp
index 3efbb30e1..70e55e4f2 100644
--- a/src/updater/user_agent.cpp
+++ b/src/updater/user_agent.cpp
@@ -1,5 +1,5 @@
 // Aseprite
-// Copyright (C) 2019  Igara Studio S.A.
+// Copyright (C) 2019-2020  Igara Studio S.A.
 // Copyright (C) 2001-2017  David Capello
 //
 // This program is distributed under the terms of
@@ -9,6 +9,9 @@
 #include "config.h"
 #endif
 
+#include "updater/user_agent.h"
+#include "ver/info.h"
+
 #include <string>
 #include <sstream>
 
@@ -39,18 +42,7 @@ std::string getUserAgent()
   std::stringstream userAgent;
 
   // App name and version
-
-#ifndef PACKAGE
-#define PACKAGE ""
-#pragma message("warning: Define PACKAGE macro")
-#endif
-
-#ifndef VERSION
-#define VERSION ""
-#pragma message("warning: Define VERSION macro")
-#endif
-
-  userAgent << PACKAGE << "/" << VERSION << " (";
+  userAgent << get_app_name() << "/" << get_app_version() << " (";
 
 #if _WIN32
 
diff --git a/src/ver/CMakeLists.txt b/src/ver/CMakeLists.txt
new file mode 100644
index 000000000..238b3cfd4
--- /dev/null
+++ b/src/ver/CMakeLists.txt
@@ -0,0 +1,18 @@
+# ASEPRITE
+# Copyright (C) 2020  Igara Studio S.A.
+
+# Version of Aseprite
+set(VERSION "1.x-dev")
+
+configure_file(
+  "${CMAKE_CURRENT_SOURCE_DIR}/generated_version.h.in"
+  "${CMAKE_CURRENT_BINARY_DIR}/generated_version.h")
+
+# Custom Aseprite website (for testing server-side)
+if(NOT "${CUSTOM_WEBSITE_URL}" STREQUAL "")
+  add_definitions(-DCUSTOM_WEBSITE_URL="${CUSTOM_WEBSITE_URL}")
+endif()
+
+add_library(ver-lib info.c ${gen_ver_fn})
+add_dependencies(ver-lib generated_version_h)
+target_include_directories(ver-lib PRIVATE "${CMAKE_CURRENT_BINARY_DIR}")
diff --git a/src/ver/generated_version.h.in b/src/ver/generated_version.h.in
new file mode 100644
index 000000000..a8661610b
--- /dev/null
+++ b/src/ver/generated_version.h.in
@@ -0,0 +1 @@
+#cmakedefine VERSION "@VERSION@"
diff --git a/src/ver/info.c b/src/ver/info.c
new file mode 100644
index 000000000..cbca0734f
--- /dev/null
+++ b/src/ver/info.c
@@ -0,0 +1,31 @@
+/* Aseprite
+   Copyright (C) 2020  Igara Studio S.A.
+
+   This program is distributed under the terms of
+   the End-User License Agreement for Aseprite.  */
+
+#include "ver/info.h"
+#include "generated_version.h"  /* It defines the VERSION macro */
+
+#define PACKAGE                 "Aseprite"
+#define COPYRIGHT               "Copyright (C) 2001-2020 Igara Studio S.A."
+
+#ifdef CUSTOM_WEBSITE_URL
+#define WEBSITE                 CUSTOM_WEBSITE_URL /* To test web server */
+#else
+#define WEBSITE                 "http://www.aseprite.org/"
+#endif
+#define WEBSITE_DOWNLOAD        WEBSITE "download/"
+#define WEBSITE_CONTRIBUTORS    WEBSITE "contributors/"
+#define WEBSITE_NEWS_RSS        "http://blog.aseprite.org/rss"
+#define WEBSITE_UPDATE          WEBSITE "update/?xml=1"
+
+const char* get_app_name() { return PACKAGE; }
+const char* get_app_version() { return VERSION; }
+const char* get_app_copyright() { return COPYRIGHT; }
+
+const char* get_app_url() { return WEBSITE; }
+const char* get_app_download_url() { return WEBSITE_DOWNLOAD; }
+const char* get_app_contributors_url() { return WEBSITE_CONTRIBUTORS; }
+const char* get_app_news_rss_url() { return WEBSITE_NEWS_RSS; }
+const char* get_app_update_url() { return WEBSITE_UPDATE; }
diff --git a/src/ver/info.h b/src/ver/info.h
new file mode 100644
index 000000000..c78221ae5
--- /dev/null
+++ b/src/ver/info.h
@@ -0,0 +1,29 @@
+/* Aseprite
+   Copyright (C) 2020  Igara Studio S.A.
+
+   This program is distributed under the terms of
+   the End-User License Agreement for Aseprite.  */
+
+#ifndef VER_INFO_H_INCLUDED
+#define VER_INFO_H_INCLUDED
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+const char* get_app_name();
+const char* get_app_version();
+const char* get_app_copyright();
+
+const char* get_app_url();
+const char* get_app_download_url();
+const char* get_app_contributors_url();
+const char* get_app_news_rss_url();
+const char* get_app_update_url();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* VER_INFO_H_INCLUDED */