diff --git a/doc/developer_manual.md b/doc/developer_manual.md
index 4567a56b5c42da34e0c17117999656a92ae6d1f4..569adb52236e6886780582c0084849d577e9ea75 100644
--- a/doc/developer_manual.md
+++ b/doc/developer_manual.md
@@ -57,3 +57,16 @@ They are handled in Tinaweb.MultipleSelection2.
 For any node `n` the relevant flags at selection are:
   - `n.active` iff node is selected
   - `n.customAttrs.highlight` if  node is a neighbor of a selected node
+
+
+## Variae
+
+#### Facets: node attributes as colors/clusters
+
+At parsing time, every node attributes are indexed by values.
+
+This indexes are stored in TW.Clusters and provide an access to sets of nodes that have a given value or range of values.
+  - if discrete attrvalues with <= 30 classes (colorsBy, clustersBy), the storage structure is: `TW.Clusters[nodeType][clusterType].classes.[possibleValue]`
+     (the content is a list of ids with the value `possibleValue`)
+  - if continuous or many possible values (>30) (clustersBy, colorsRelByBins), the storage uses ordered ranges ("bins"):
+     `TW.Clusters[nodeType][clusterType].ranges.[interval]`
diff --git a/extras_explorerjs.js b/extras_explorerjs.js
index 5088069f8fef5c9a722179069fb91c5ceb0f45f7..115e95f1f714a36bd885fbd66eecca8f3ad151f7 100755
--- a/extras_explorerjs.js
+++ b/extras_explorerjs.js
@@ -336,18 +336,18 @@ function set_ClustersLegend ( daclass, groupedByTicks ) {
 //         jsonparams = jsonparams.split('&').join('__and__');
 //         //dbsPaths.push(getGlobalDBs());
 //         thisgexf=JSON.stringify(decodeURIComponent(getUrlParam.file));
-//         image='<img style="display:block; margin: 0px auto;" src="'+TW.APINAME+'img/ajax-loader.gif"></img>';
+//         image='<img style="display:block; margin: 0px auto;" src="'+TW.companionAPI+'img/ajax-loader.gif"></img>';
 //         $("#tab-container-top").show();
 //         $("#topPapers").show();
 //         $("#topPapers").html(image);
 //         $.ajax({
 //             type: 'GET',
-//             url: TW.APINAME+'info_div.php',
+//             url: TW.companionAPI+'info_div.php',
 //             data: "type="+type+"&bi="+bi+"&query="+jsonparams+"&gexf="+thisgexf+"&index="+TW.field[getUrlParam.file],
 //             //contentType: "application/json",
 //             //dataType: 'json',
 //             success : function(data){
-//                 console.log(TW.APINAME+'info_div.php?'+"type="+type+"&bi="+bi+"&query="+jsonparams+"&gexf="+thisgexf+"&index="+TW.field[getUrlParam.file]);
+//                 console.log(TW.companionAPI+'info_div.php?'+"type="+type+"&bi="+bi+"&query="+jsonparams+"&gexf="+thisgexf+"&index="+TW.field[getUrlParam.file]);
 //                 $("#topPapers").html(data);
 //             },
 //             error: function(){
@@ -370,7 +370,7 @@ function getTopPapers(type){
         //
         $.ajax({
             type: 'GET',
-            url: TW.APINAME,
+            url: TW.companionAPI,
             data: {'query': joined_q},
             contentType: "application/json",
             success : function(data){
@@ -506,7 +506,7 @@ function RenderTweet( tweet) {
 //FOR UNI-PARTITE
 // function selectionUni(currentNode){
 //     console.log("\tin selectionUni:"+currentNode.id);
-//     if(checkBox==false && cursor_size==0) {
+//     if(checkBox==false && TW.circleSize==0) {
 //         highlightSelectedNodes(false);
 //         opossites = [];
 //         selections = [];
@@ -683,7 +683,7 @@ function circleTrackMouse(e) {
       //   }
       // }
 
-  ctx.arc(x, y, cursor_size, 0, Math.PI * 2, true);
+  ctx.arc(x, y, TW.circleSize, 0, Math.PI * 2, true);
   ctx.closePath();
   ctx.fill();
   ctx.stroke();
@@ -694,7 +694,7 @@ function circleTrackMouse(e) {
 // exact subset of nodes under circle
 function circleGetAreaNodes(camX0, camY0) {
 
-  var cursor_ray = cursor_size * TW.cam.ratio // cursor_size to cam units
+  var cursor_ray = TW.circleSize * TW.cam.ratio // converting TW.circleSize to cam units
 
   // prepare an approximate neighborhood
   var slightlyLargerNodeset = circleLocalSubset(
@@ -799,8 +799,8 @@ function flashNodesArray (nodesArray) {
 //   - the dirname of the submodule's files (with a mandatory init.js)
 //   - the css class of all html elements added by the submodule
 function ProcessDivsFlags() {
-    for(var key in TW.DivsFlags) {
-        if(TW.DivsFlags[key]===false) {
+    for(var key in TW.conf.DivsFlags) {
+        if(TW.conf.DivsFlags[key]===false) {
             $("."+key).remove() ; // hide elements of module's class
         }
         else {
diff --git a/settings_explorerjs.js b/settings_explorerjs.js
index ec7353474a0d2b855d2ec69149f241c535f28f80..123985a6d6b631ad34b14b22f91b773192aadfdc 100644
--- a/settings_explorerjs.js
+++ b/settings_explorerjs.js
@@ -2,248 +2,199 @@
 
 var TW = {}
 
+TW.conf = (function(TW){
 
-// £TODO separate files for TW.vars and TW.settings (configfile)
-
-    TW.geomap = false;
-    TW.colorByAtt = false;
-    TW.twittertimeline = false;
-    TW.minimap=false;
-    TW.getAdditionalInfo = true;// True: Activate TopPapers feature.
-    TW.filemenu = 'db.json'
-    // TW.mainfile = "data/mysuperproject/my.gexf"
-    TW.mainfile = "data/politoscope/ProgrammeDesCandidats.enrichi.gexf"
-    TW.APINAME = "http://127.0.0.1:5000/twitter_search";
-    TW.tagcloud_limit = 50;
-    TW.bridge={};
-    TW.bridge["forFilteredQuery"] = "services/api/graph";
-    TW.bridge["forNormalQuery"] = "services/api/graph";
-    TW.gexfPaths={};
-    TW.Relations = {}
-
-    //  module_names to load
-    // ----------------------
-    TW.DivsFlags = {} ;
-    // flag name is div class to be removed if false
-    //        *and* subdirectory to import if true
-    // see also ProcessDivsFlags()
-    TW.DivsFlags["histogramModule"] = false ;
-    TW.DivsFlags["histogramDailyVariantModule"] = false ;
-    // TODO more generic module integrating the variants cf. experiments/histogramModule_STUB_GENERIQUE
-    TW.DivsFlags["crowdsourcingModule"] = false ;
-
-    TW.SystemState = {}
-    TW.SystemState.level = true;
-    TW.SystemState.type = [ true, false ] // usually overridden by initialActivetypes
-    TW.SystemState.selections = [];
-    TW.SystemState.opposites = [];
-    TW.catSoc = "Document";
-    TW.catSem = "NGram";
-
-    TW.strSearchBar = "Select or suggest topics";
+  let TWConf = {}
 
-var ParseCustom = function () {};
-var SigmaUtils = function () {};
-var TinaWebJS = function () {};
+  TWConf.branding = 'test bipart'        // <----- the name displayed in upper left
 
 
-// node sizes
-// ----------
-var sizeMult = [];
-    sizeMult[TW.catSoc] = 0.0;
-    sizeMult[TW.catSem] = 0.0;
+  // ==========================
+  // TINA POSSIBLE DATA SOURCES
+  // ==========================
 
-var minLengthAutoComplete = 1;
-var maxSearchResults = 10;
+  // the graph input depends on TWConf.sourcemode (or manual url arg 'sourcemode')
+  TWConf.sourcemode = "api"   // accepted: "api" | "serverfile" | "servermenu" | "localfile"
 
-var cursor_size_min= 0;
-var cursor_size= 0;
-var cursor_size_max= 100;
+  // server-side gexf default source
+  TWConf.sourceFile = "data/politoscope/ProgrammeDesCandidats.enrichi.gexf"
 
-var desirableTagCloudFont_MIN=12;
-var desirableTagCloudFont_MAX=20;
-var desirableNodeSizeMIN=1;
-var desirableNodeSizeMAX=12;
+  // or remote bridge to default source api ajax queries
+  TWConf.sourceAPI={};
+  TWConf.sourceAPI["forNormalQuery"] = "services/api/graph";
+  TWConf.sourceAPI["forFilteredQuery"] = "services/api/graph";
 
 
-// layouts
-// -------
-// just a simple flag on this one
-TW.disperseAvailable=false;               // disperseButton hidden at start, disperse stopped forever
-TW.fa2Available=false;                    // fa2Button hidden at start, fa2 stopped forever
-// if fa2Button:
-  TW.fa2enabled=0;                 // fa2 auto-running at start ?
-  TW.minNodesForAutoFA2 = 5        // fa2 not run if graph has less nodes than this threshold
+  // ===========
+  // DATA FACETS
+  // ===========
 
+  // to handle node attributes from data
+  //    => clusters (discrete numeric or str vars),
+  //    => colors   (continuous numeric vars)
 
-// ============ < / DEVELOPER OPTIONS > ============
-TW.branding = 'test bipart'
-TW.libspath = 'libs'                      // NB path vars should not be used after page load
+  // for continuous attrvalues/colors (cf. clustersBy), how many levels in legend?
+  TWConf.legendsBins = 7 ;
 
-TW.nodeClusAtt = "modularity_class"
+  // some specific attributes may have other number of levels
+  TWConf.customLegendsBins = {
+    'age': 8,
+    'growth_rate': 12
+  }
 
 
-TW.filterSliders = true
+  // ===================
+  // TINA ACTIVE MODULES
+  // ===================
+  TWConf.DivsFlags = {} ;
+  // flag name is div class to be removed if false
+  //        *and* subdirectory to import if true
+  // see also ProcessDivsFlags()
+  TWConf.DivsFlags["histogramModule"] = false ;
+  TWConf.DivsFlags["histogramDailyVariantModule"] = false ;
+  // TODO more generic module integrating the variants cf. experiments/histogramModule_STUB_GENERIQUE
+  TWConf.DivsFlags["crowdsourcingModule"] = false ;
 
-TW.histogramStartThreshold = 10 ;
+  TWConf.libspath = 'libs'    // FIXME path vars should not be used after page load !
 
-TW.defaultNodeColor = "rgb(40,40,40)"
-TW.edgeDefaultOpacity = 0.4  // opacity when true_color
-TW.edgeGreyColor = "rgba(150, 150, 150, 0.5)";
-TW.nodesGreyBorderColor = "rgba(100, 100, 100, 0.5)";
-TW.selectedColor = "default"  // "node" for a background like the node's color,
-                           // "default" for note-like yellow
+  // =============
+  // TINA BEHAVIOR
+  // =============
 
-TW.overSampling = false    // costly hi-def rendering (true => pixelRatio x 2)
+  // Node typology
+  TWConf.catSoc = "Document";
+  TWConf.catSem = "NGram";
 
-TW.deselectOnclickStage = true // will a click on the background remove selection ? (except when dragging)
-var showLabelsIfZoom=1.0;
+  // Events handling
+  TWConf.deselectOnclickStage = true // will a click on the background remove selection ? (except when dragging)
 
-// for continuous attrvalues/colors (cf. clustersBy), how many levels in legend?
-TW.legendsBins = 7 ;
 
-// some specific attributes may have other number of levels
-TW.customLegendsBins = {
-  'age': 8,
-  'growth_rate': 12
-}
+  // debug flags & log levels
+  TWConf.debug = {
+    initialShowAll: false,           // show all nodes on bipartite case init (docs + terms in one view)
 
+    // show verbose console logs...
+    logFetchers: false,              // ...about ajax/fetching of graph data
+    logParsers: false,               // ...about parsing said data
+    logFacets: false,                // ...about parsing node attribute:value facets
+    logSettings: false,              // ...about settings at Tina and Sigma init time
+    logSelections: false
+  }
 
-TW.debugFlags = {
-  initialShowAll: false,           // show all nodes on bipartite case init (docs + terms in one view)
 
-  // show verbose console logs...
-  logFetchers: false,              // ...about ajax/fetching of graph data
-  logParsers: false,               // ...about parsing said data
-  logFacets: false,                // ...about parsing node attribute:value facets
-  logSettings: false,              // ...about settings at Tina and Sigma init time
-  logSelections: true
-}
+  // Layouts
+  // -------
+  TWConf.fa2Available=true;        // show/hide fa2Button
+  TWConf.disperseAvailable=true;   // show/hide disperseButton
 
-// triggers overriding sigma.canvas renderers: nodes.def, labels.def, edges.def
-TW.ourRendering = true ;
+  // if fa2Available, the auto-run config:
 
-// ============ < / DEVELOPER OPTIONS > ============
+    TWConf.fa2Enabled= true;       // fa2 auto-run at start and after graph modified ?
+    TWConf.fa2Milliseconds=5000;   // duration of auto-run
+    TWConf.minNodesForAutoFA2 = 5  // graph size threshold to auto-run
 
 
-// ============ < SIGMA.JS PROPERTIES > ============
+  // Full-text search
+  // ----------------
+  TWConf.minLengthAutoComplete = 1;
+  TWConf.maxSearchResults = 10;
 
-var sigmaJsDrawingProperties = {
-    defaultLabelColor: 'black',
-    defaultLabelSize: 30, // in fact usually overridden by node data...
-    labelSizeRatio: 1,   // ...but this ratio allows truly adjusting the sizes
 
-    labelThreshold: 5,
-    defaultEdgeType: 'curve',  // 'curve' or 'line'
+  // SIGMA BEHAVIOR SETTINGS
 
-    defaultBorderView: "always",
+  // SIGMA RENDERING SETTINGS
+  // triggers overriding sigma.canvas renderers: nodes.def, labels.def, edges.def
+  TWConf.ourRendering = true ;
 
-    // new sigma.js only for hover + new settingnames
-    defaultHoverLabelBGColor: '#fff',
-    defaultHoverLabelColor: '#000',
-    borderSize: 2.5, // (only for hovered nodes)
-    defaultNodeBorderColor: "black",
-    nodeBorderColor: "default",  // vs. node
 
-    // for custom TW node renderer with borders
-    twNodeRendBorderSize: 1,   // (for all normal nodes, iff TW.nodeRendBorder)
-    twNodeRendBorderColor: "#222",
-    // twNodeRendBorderColor: "#eee",
+  TWConf.sigmaJsDrawingProperties = {
+      defaultLabelColor: 'black',
+      defaultLabelSize: 30, // in fact usually overridden by node data...
+      labelSizeRatio: 1,   // ...but this ratio allows truly adjusting the sizes
 
-    font: "Droid Sans",
-    // font: "Crete Round",
-    // font: "Ubuntu Condensed",
-    fontStyle: "bold",
-};
-var sigmaJsGraphProperties = {
-    minEdgeSize: 3,
-    // maxEdgeSize: 10
-};
-var sigmaJsMouseProperties = {
-    minRatio: .03125,  // 1/32  pour permettre zoom x32
-    maxRatio: 2
-};
-// ============ < / SIGMA.JS PROPERTIES > ============
+      labelThreshold: 5,   // <- replaces deprecated showLabelsIfZoom
 
+      defaultEdgeType: 'curve',  // 'curve' or 'line'
 
+      defaultBorderView: "always",
 
+      // new sigma.js only for hover + new settingnames
+      defaultHoverLabelBGColor: '#fff',
+      defaultHoverLabelColor: '#000',
+      borderSize: 2.5, // (only for hovered nodes)
+      defaultNodeBorderColor: "black",
+      nodeBorderColor: "default",  // vs. node
 
-// ============ < VARIABLES.JS > ============
+      // for custom TW node renderer with borders
+      twNodeRendBorderSize: 1,   // (for all normal nodes, iff TWConf.nodeRendBorder)
+      twNodeRendBorderColor: "#222",
+      // twNodeRendBorderColor: "#eee",
 
-var twjs="tinawebJS/";
+      font: "Droid Sans",
+      // font: "Crete Round",
+      // font: "Ubuntu Condensed",
+      fontStyle: "bold",
+  };
 
-// possible node types and their inverted map
-TW.categories = [];
-TW.catDict = {};
+  TWConf.sigmaJsGraphProperties = {
+      minEdgeSize: 3,
+      // maxEdgeSize: 10
+  };
 
-var gexfFile;
-//var zoom=0;
+  TWConf.sigmaJsMouseProperties = {
+      minRatio: .03125,  // 1/32  pour permettre zoom x32
+      maxRatio: 2
+  };
 
-var checkBox=false;
-var manuallyChecked = false;
-var overNodes=false;
-var shift_key=false;
 
-var NOW="A";
-var PAST="--";
+  // =======================
+  // TINA RENDERING SETTINGS
+  // =======================
+  TWConf.overSampling = false    // costly hi-def rendering (true => pixelRatio x 2)
 
-var swclickActual="";
-var swclickPrev="";
-var swMacro=true;
+  TWConf.sizeMult = [];
 
-var socsemFlag=false;
-var constantNGramFilter;
+  TWConf.sizeMult[0] = 1.0;    // ie for node type 0
+  TWConf.sizeMult[1] = 1.0;    // ie for node type 1
 
+  TWConf.circleSizeMin= 0;
+  TWConf.circleSizeMax= 100;
 
-var lastFilter = []
-    lastFilter["#slidercat0nodesweight"] = {"orig":"-" , "last":"-"}
-    lastFilter["#slidercat1nodesweight"] =  {"orig":"-" , "last":"-"}
-    lastFilter["#slidercat0edgesweight"] =  {"orig":"-" , "last":"-"}
-    lastFilter["#slidercat1edgesweight"] =  {"orig":"-" , "last":"-"}
 
+  // ========
+  // A RANGER £TODO
+  // ========
 
-//
-// var overviewWidth = 200;
-// var overviewHeight = 175;
-// var overviewScale = 0.25;
-// var overviewHover=false;
-var moveDelay = 80, zoomDelay = 2;
-//var Vecindad;
-TW.partialGraph;
-var otherGraph;
-TW.Nodes = [];
-TW.Edges = [];
-TW.Clusters = [];
+  TWConf.nodeClusAtt = "modularity_class"
 
 
-// new dev properties
-TW.scanClusters = true   // build TW.Clusters in an (attr+val => nodes) reverse index (aka facets)
-TW.maxDiscreteValues = 40  // max discrete levels in facet legend (aka bins)
-// new TW.Clusters structure
-// --------------------------
-// was: built in separate loop from read of all attr values
-//      TW.Clusters[nodeType][clusterType][possibleValue] = clst_idx_of_possible_value
+  TWConf.filterSliders = true
 
-// from now on:
-//      still built in ChangeGraphAppearanceByAtt
-//      POSS: build in parseCustom (when reading all nodes attributes anyway)
-//      if discrete attrvalues with <= 30 classes (colorsBy, clustersBy)
-//         => TW.Clusters[nodeType][clusterType].classes.[possibleValue] = list of ids with the value
-//      if continuous or many possible values (>30) (clustersBy, colorsRelByBins)
-//         => TW.Clusters[nodeType][clusterType].ranges.[interval] = list of ids in the interval
+  TWConf.histogramStartThreshold = 10 ;
 
+  TWConf.defaultNodeColor = "rgb(40,40,40)"
+  TWConf.edgeDefaultOpacity = 0.4  // opacity when true_color
+  TWConf.edgeGreyColor = "rgba(150, 150, 150, 0.5)";
+  TWConf.nodesGreyBorderColor = "rgba(100, 100, 100, 0.5)";
+  TWConf.selectedColor = "default"  // "node" for a background like the node's color,
+                             // "default" for note-like yellow
 
-TW.fa2milliseconds=5000;   // for initial auto-run if fa2enabled and any
-                           // subsequent auto-runs if graph modified
+  console.warn("current conf:", TWConf)
 
+  return TWConf
+})()
 
 
-var nodeslength=0;
 
-var labels = [];
+// INITIALIZED VARS (£TODO move to main or Tina)
+// ================
+TW.Nodes = [];
+TW.Edges = [];
+TW.Relations = {}
+TW.Clusters = [];  // A "by value" index, built in parseCustom, (aka facets)
 
-var numberOfDocs=0;    // not used!
-var numberOfNGrams=0;  // not used, but cf TW.nNodes TW.nEdges
+TW.gexfPaths={};
+TW.labels=[];
 
 // FIXME should become TW.*
 var selections = [];
@@ -259,44 +210,50 @@ var nodes2 = {};
 var bipartiteD2N = {};
 var bipartiteN2D = {};
 
-var flag=0;
-var firstime=0;
-var leftright=true;
-var edgesTF=false;
-
-//This variables will be updated in sigma.parseCustom.js
-var minNodeSize=10000000;
-var maxNodeSize=0;
-// var minEdgeWeight=5.0;  // in fact never used...
-// var maxEdgeWeight=0.0;
-//---------------------------------------------------
-
-var bipartite=false;
-
-var colorList = ["#000000", "#FFFF00", "#1CE6FF", "#FF34FF", "#FF4A46", "#008941", "#006FA6", "#A30059", "#FFDBE5", "#7A4900", "#0000A6", "#63FFAC", "#B79762", "#004D43", "#8FB0FF", "#997D87", "#5A0007", "#809693", "#FEFFE6", "#1B4400", "#4FC601", "#3B5DFF", "#4A3B53", "#FF2F80", "#61615A", "#BA0900", "#6B7900", "#00C2A0", "#FFAA92", "#FF90C9", "#B903AA", "#D16100", "#DDEFFF", "#000035", "#7B4F4B", "#A1C299", "#300018", "#0AA6D8", "#013349", "#00846F", "#372101", "#FFB500", "#C2FFED", "#A079BF", "#CC0744", "#C0B9B2", "#C2FF99", "#001E09", "#00489C", "#6F0062", "#0CBD66", "#EEC3FF", "#456D75", "#B77B68", "#7A87A1", "#788D66", "#885578", "#FAD09F", "#FF8A9A", "#D157A0", "#BEC459", "#456648", "#0086ED", "#886F4C","#34362D", "#B4A8BD", "#00A6AA", "#452C2C", "#636375", "#A3C8C9", "#FF913F", "#938A81", "#575329", "#00FECF", "#B05B6F", "#8CD0FF", "#3B9700", "#04F757", "#C8A1A1", "#1E6E00", "#7900D7", "#A77500", "#6367A9", "#A05837", "#6B002C", "#772600", "#D790FF", "#9B9700", "#549E79", "#FFF69F", "#201625", "#72418F", "#BC23FF", "#99ADC0", "#3A2465", "#922329", "#5B4534", "#FDE8DC", "#404E55", "#0089A3", "#CB7E98", "#A4E804", "#324E72", "#6A3A4C", "#83AB58", "#001C1E", "#D1F7CE", "#004B28", "#C8D0F6", "#A3A489", "#806C66", "#222800", "#BF5650", "#E83000", "#66796D", "#DA007C", "#FF1A59", "#8ADBB4", "#1E0200", "#5B4E51", "#C895C5", "#320033", "#FF6832", "#66E1D3", "#CFCDAC", "#D0AC94", "#7ED379", "#012C58"];
-
-var RVUniformC = function(seed){
-    this.a=16807;
-    this.b=0;
-    this.m=2147483647;
-    this.u;
-    this.seed=seed;
-    this.x = this.seed;
-    //    this.generar = function(n){
-    //        uniforme = [];
-    //        x = 0.0;
-    //        x = this.seed;
-    //        for(i = 1; i < n ; i++){
-    //            x = ((x*this.a)+this.b)%this.m;
-    //            uniforme[i] = x/this.m;
-    //        }
-    //        return uniforme;
-    //    };
-    this.getRandom = function(){
-        x = ((this.x*this.a)+this.b)%this.m;
-        this.x = x;
-        this.u = this.x/this.m;
-        return this.u;
-    };
-}
-//unifCont = new RVUniformC(100000000)
+// possible node types and their inverted map
+TW.categories = [];
+TW.catDict = {};
+
+
+TW.nodeslength = 0  // <=== £TODO harmonize use with TW.partialGraph.graph.nNodes()
+
+var gexfFile;
+//var zoom=0;
+TW.checkBox=false;
+TW.shiftKey=false;
+TW.manuallyChecked = false;
+
+TW.SystemState = {}
+TW.SystemState.level = true;
+TW.SystemState.type = [ true, false ] // usually overridden by initialActivetypes
+TW.SystemState.selections = [];
+TW.SystemState.opposites = [];
+
+
+TW.colorList = ["#000000", "#FFFF00", "#1CE6FF", "#FF34FF", "#FF4A46", "#008941", "#006FA6", "#A30059", "#FFDBE5", "#7A4900", "#0000A6", "#63FFAC", "#B79762", "#004D43", "#8FB0FF", "#997D87", "#5A0007", "#809693", "#FEFFE6", "#1B4400", "#4FC601", "#3B5DFF", "#4A3B53", "#FF2F80", "#61615A", "#BA0900", "#6B7900", "#00C2A0", "#FFAA92", "#FF90C9", "#B903AA", "#D16100", "#DDEFFF", "#000035", "#7B4F4B", "#A1C299", "#300018", "#0AA6D8", "#013349", "#00846F", "#372101", "#FFB500", "#C2FFED", "#A079BF", "#CC0744", "#C0B9B2", "#C2FF99", "#001E09", "#00489C", "#6F0062", "#0CBD66", "#EEC3FF", "#456D75", "#B77B68", "#7A87A1", "#788D66", "#885578", "#FAD09F", "#FF8A9A", "#D157A0", "#BEC459", "#456648", "#0086ED", "#886F4C","#34362D", "#B4A8BD", "#00A6AA", "#452C2C", "#636375", "#A3C8C9", "#FF913F", "#938A81", "#575329", "#00FECF", "#B05B6F", "#8CD0FF", "#3B9700", "#04F757", "#C8A1A1", "#1E6E00", "#7900D7", "#A77500", "#6367A9", "#A05837", "#6B002C", "#772600", "#D790FF", "#9B9700", "#549E79", "#FFF69F", "#201625", "#72418F", "#BC23FF", "#99ADC0", "#3A2465", "#922329", "#5B4534", "#FDE8DC", "#404E55", "#0089A3", "#CB7E98", "#A4E804", "#324E72", "#6A3A4C", "#83AB58", "#001C1E", "#D1F7CE", "#004B28", "#C8D0F6", "#A3A489", "#806C66", "#222800", "#BF5650", "#E83000", "#66796D", "#DA007C", "#FF1A59", "#8ADBB4", "#1E0200", "#5B4E51", "#C895C5", "#320033", "#FF6832", "#66E1D3", "#CFCDAC", "#D0AC94", "#7ED379", "#012C58"];
+
+
+
+var ParseCustom = function () {};
+var SigmaUtils = function () {};
+var TinaWebJS = function () {};
+
+
+
+// £TODO à ranger
+TW.circleSize= 0;
+var lastFilter = []
+    lastFilter["#slidercat0nodesweight"] = {"orig":"-" , "last":"-"}
+    lastFilter["#slidercat1nodesweight"] =  {"orig":"-" , "last":"-"}
+    lastFilter["#slidercat0edgesweight"] =  {"orig":"-" , "last":"-"}
+    lastFilter["#slidercat1edgesweight"] =  {"orig":"-" , "last":"-"}
+
+var desirableTagCloudFont_MIN=12;
+var desirableTagCloudFont_MAX=20;
+var desirableNodeSizeMIN=1;
+var desirableNodeSizeMAX=12;
+
+
+// These variables will be updated in sigma.parseCustom.js
+var minNodeSize
+var maxNodeSize
diff --git a/tinawebJS/Tinaweb.js b/tinawebJS/Tinaweb.js
index ea51e126ef61daa4398b155c5faee0e4993bcdbb..d07a87e8671cc901cd64b32826be797b8cb775bc 100644
--- a/tinawebJS/Tinaweb.js
+++ b/tinawebJS/Tinaweb.js
@@ -83,7 +83,7 @@ function SelectionEngine() {
                 coincd.push(results[i].id)
             }
             var targeted = this.SelectorEngine( {
-                            addvalue:checkBox,
+                            addvalue:TW.checkBox,
                             prevsels:selections,
                             currsels:coincd
                         } )
@@ -147,7 +147,7 @@ function SelectionEngine() {
      // ====================
     this.MultipleSelection2 = (function(nodes,nodesDict,edgesDict) {
 
-      if (TW.debugFlags.selections) {
+      if (TW.conf.debug.selections) {
         var tMS2_deb = performance.now()
 
         console.log("IN SelectionEngine.MultipleSelection2:")
@@ -273,9 +273,6 @@ function SelectionEngine() {
 
         // alert("MultipleSelection2=======\nthe_new_sels:" + JSON.stringify(the_new_sels))
 
-        // global flag
-        TW.selectionActive = true
-
         // we send our "gotNodeSet" event
         // (signal for plugins that a search-selection was done or a new hand picked selection)
         $('#searchinput').trigger({
@@ -315,19 +312,20 @@ function SelectionEngine() {
             return b-a
         });
 
-        if (TW.debugFlags.selections) {
+        if (TW.conf.debug.selections) {
           console.debug('selections', selections)
           console.debug('oppos', oppos)
           console.debug('same', same)
         }
 
-        overNodes=true;
+        // global flag
+        TW.selectionActive = true
 
         TW.partialGraph.render();
 
         updateRelatedNodesPanel( selections , same, oppos );
 
-        if (TW.debugFlags.selections) {
+        if (TW.conf.debug.selections) {
           var tMS2_fin = performance.now()
           console.log("end MultipleSelection2, own time:", tMS2_fin-tMS2_deb)
         }
@@ -344,7 +342,7 @@ TinaWebJS = function ( sigmacanvas ) {
     // functions that modify the sigma module (not sigma instance!)
     this.init = function () {
 
-        if (TW.debugFlags.logSettings)    console.info("TW settings", TW)
+        if (TW.conf.debug.logSettings)    console.info("TW settings", TW)
 
         let initErrMsg = null
 
@@ -354,12 +352,12 @@ TinaWebJS = function ( sigmacanvas ) {
         else {
           this.prepareSigmaCustomIndices(sigma)
 
-          if (TW.ourRendering)
+          if (TW.conf.ourRendering)
             this.prepareSigmaCustomRenderers(sigma)
         }
 
         // overriding pixelRatio is possible if we need high definition
-        if (TW.overSampling) {
+        if (TW.conf.overSampling) {
           var realRatio = sigma.utils.getPixelRatio
           sigma.utils.getPixelRatio = function() {
             return 2 * realRatio()
@@ -476,7 +474,7 @@ TinaWebJS = function ( sigmacanvas ) {
       //  - additionnaly supports 'active/forcelabel' node property (magnify x 3)
       sigmaModule.canvas.hovers.def = tempo.twRender.canvas.hovers.largerall
 
-      if (TW.debugFlags.logSettings) console.log('tw renderers registered in sigma module')
+      if (TW.conf.debug.logSettings) console.log('tw renderers registered in sigma module')
     }
 
     this.initSearchListeners = function () {
@@ -487,10 +485,10 @@ TinaWebJS = function ( sigmacanvas ) {
             source: function(request, response) {
                 // labels initialized in settings, filled in updateSearchLabels
                 // console.log(labels.length)
-                matches = [];
+                var matches = [];
                 var matcher = new RegExp($.ui.autocomplete.escapeRegex(request.term), "i");
                 // grep at heart
-                var results = $.grep(labels, function(e) {
+                var results = $.grep(TW.labels, function(e) {
                     return matcher.test(e.label); //|| matcher.test(e.desc);
                 });
 
@@ -499,11 +497,11 @@ TinaWebJS = function ( sigmacanvas ) {
                 } else {
                     $("#noresults").empty();
                 }
-                matches = results.slice(0, maxSearchResults);
+                matches = results.slice(0, TW.conf.minLengthAutoComplete);
                 response(matches);
 
             },
-            minLength: minLengthAutoComplete,
+            minLength: TW.conf.minLengthAutoComplete,
 
 
             // ----------------------->8---------------------
@@ -574,7 +572,7 @@ TinaWebJS = function ( sigmacanvas ) {
                     setTimeout(
                       function (){
                           targeted = SelInst.SelectorEngine( {
-                                          addvalue:checkBox,
+                                          addvalue:TW.checkBox,
                                           clicktype:"double",
                                           prevsels:selections,
                                           currsels:coincidences
@@ -582,12 +580,12 @@ TinaWebJS = function ( sigmacanvas ) {
 
                           // tricky stuff for simulating a multiple selection D:
                           // ... to be improved in the future ...
-                          var prev_cursor_size = cursor_size;
+                          var prev_cursor_size = TW.circleSize;
                           if(targeted.length>0) {
-                              cursor_size = (cursor_size==0)? 1 : cursor_size;
+                              TW.circleSize = (TW.circleSize==0)? 1 : TW.circleSize;
                               cancelSelection(false);
                               SelInst.MultipleSelection2({nodes:targeted});
-                              cursor_size = prev_cursor_size;
+                              TW.circleSize = prev_cursor_size;
                           }
 
                           $("input#searchinput").val("");
@@ -621,7 +619,7 @@ TinaWebJS = function ( sigmacanvas ) {
                     setTimeout(
                       function() {
                         targeted = SelInst.SelectorEngine( {
-                                    addvalue:checkBox,
+                                    addvalue:TW.checkBox,
                                     clicktype:"double",
                                     prevsels:selections,
                                     currsels:[exfnd.id]
@@ -739,7 +737,7 @@ TinaWebJS = function ( sigmacanvas ) {
             TW.partialGraph.camera.goTo({x:0, y:0, ratio:1.2})
         });
 
-        if (TW.fa2Available) {
+        if (TW.conf.fa2Available) {
           $("#layoutButton").click(function () {
             sigma_utils.smartForceAtlas()
           });
@@ -748,7 +746,7 @@ TinaWebJS = function ( sigmacanvas ) {
           $("#layoutButton").hide()
         }
 
-        if (TW.disperseAvailable) {
+        if (TW.conf.disperseAvailable) {
           $("#noverlapButton").click(function () {
             if(! TW.partialGraph.isNoverlapRunning()) {
                 // show waiting cursor on page and button
@@ -785,12 +783,12 @@ TinaWebJS = function ( sigmacanvas ) {
         //Cursor Size slider
         var cursorSlider = $("#unranged-value").freshslider({
             step: 1,
-            min:cursor_size_min,
-            max:cursor_size_max,
-            value:cursor_size,
+            min:TW.conf.circleSizeMin,
+            max:TW.conf.circleSizeMax,
+            value:TW.circleSize,
             onchange:function(value){
                 // console.log("en cursorsize: "+value);
-                cursor_size=value;
+                TW.circleSize=value;
             }
         });
 
@@ -813,11 +811,11 @@ TinaWebJS = function ( sigmacanvas ) {
         //             console.log("init: slider resize")
         //             for(j=0 ; j<TW.partialGraph.nNodes ; j++){
         //                 if (nds[j]
-        //                  && nds[j].type == TW.catSem) {
+        //                  && nds[j].type == TW.conf.catSem) {
         //                      var n = nds[j]
         //                      var newval = parseFloat(TW.Nodes[n.id].size) + parseFloat((value-1))*0.3
         //                      n.size = (newval<1.0)?1:newval;
-        //                      sizeMult[TW.catSem] = parseFloat(value-1)*0.3;
+        //                      sizeMult[TW.conf.catSem] = parseFloat(value-1)*0.3;
         //                 }
         //             }
         //             partialGraph.render()
@@ -851,10 +849,10 @@ TinaWebJS = function ( sigmacanvas ) {
         // general listener: shift key in the window <=> add to selection
         $(document).on('keyup keydown', function(e){
           // changes the global boolean ("add node to selection" status) if keydown and SHIFT
-          checkBox = manuallyChecked || e.shiftKey
+          TW.checkBox = TW.manuallyChecked || e.shiftKey
 
-          // show it in the real checkbox too
-          $('#checkboxdiv').prop("checked", manuallyChecked || e.shiftKey)
+          // show it in the real TW.checkBox too
+          $('#checkboxdiv').prop("checked", TW.manuallyChecked || e.shiftKey)
         } );
 
     } // finish envListeners
@@ -873,7 +871,7 @@ TinaWebJS = function ( sigmacanvas ) {
 
       // cases:
       // 'click'    - simple click, early event
-      //              used for area (with global: cursor_size)
+      //              used for area (with global: TW.circleSize)
       // 'clickNode'- simple click, second event if one node
 
       // POSS easy in new sigma.js:
@@ -887,7 +885,7 @@ TinaWebJS = function ( sigmacanvas ) {
         // console.log("sigma click event e", e)
 
         // case with a selector circle cursor handled here
-        if (cursor_size > 0) {
+        if (TW.circleSize > 0) {
           // actual click position, but in graph coords
           var x = e.data.x
           var y = e.data.y
@@ -895,19 +893,19 @@ TinaWebJS = function ( sigmacanvas ) {
           // convert
           var camCoords = TW.cam.cameraPosition(x,y)
 
-          // retrieve area nodes, using indexed quadtree and global cursor_size
+          // retrieve area nodes, using indexed quadtree and global TW.circleSize
           var circleNodes = circleGetAreaNodes(
             camCoords.x,
             camCoords.y
           )
 
-          // 1) clear previous while keeping its list (useful iff 'Add' checkBox)
+          // 1) clear previous while keeping its list (useful iff 'Add' TW.checkBox)
           var previousSelection = selections
           cancelSelection(false)
 
           // 2) show selection + do all related effects
           var targeted = SelInst.SelectorEngine( {
-                              addvalue:checkBox,
+                              addvalue:TW.checkBox,
                               currsels:circleNodes,
                               prevsels:previousSelection
                           } )
@@ -929,9 +927,9 @@ TinaWebJS = function ( sigmacanvas ) {
         var previousSelection = selections
         cancelSelection(false, {norender:true}); // no need to render before MS2
 
-        if (cursor_size == 0) {
+        if (TW.circleSize == 0) {
           var targeted = SelInst.SelectorEngine( {
-                              addvalue:checkBox,
+                              addvalue:TW.checkBox,
                               currsels:[theNodeId],
                               prevsels:previousSelection
                           } )
@@ -945,13 +943,13 @@ TinaWebJS = function ( sigmacanvas ) {
 
       // when click in the empty background
       // ==================================
-      if (TW.deselectOnclickStage) {
+      if (TW.conf.deselectOnclickStage) {
         partialGraph.bind('clickStage', function(e) {
           // console.log("clickStage event e", e)
 
           if (! e.data.captor.isDragging
             && Object.keys(selections).length
-            && ! cursor_size) {
+            && ! TW.circleSize) {
 
             // we clear selections and all its effects
             cancelSelection(false);
@@ -982,7 +980,7 @@ TinaWebJS = function ( sigmacanvas ) {
           .mousemove(function(e){
               if(!isUndef(partialGraph)) {
                   // show/move selector circle cursor
-                  if(cursor_size>0) circleTrackMouse(e);
+                  if(TW.circleSize>0) circleTrackMouse(e);
               }
           })
 
@@ -998,8 +996,8 @@ TinaWebJS = function ( sigmacanvas ) {
 
           // new sigma.js current zoom ratio
           value: partialGraph.camera.ratio,
-          min: 1 / sigmaJsMouseProperties.maxRatio,   // ex x.5
-          max: 1 / sigmaJsMouseProperties.minRatio,   // ex x32
+          min: 1 / TW.conf.sigmaJsMouseProperties.maxRatio,   // ex x.5
+          max: 1 / TW.conf.sigmaJsMouseProperties.minRatio,   // ex x32
           // range: true,
           step: .2,
           value: 1,
@@ -1013,7 +1011,7 @@ TinaWebJS = function ( sigmacanvas ) {
 
       $("#zoomPlusButton").click(function () {
           var newRatio = TW.cam.ratio * .75
-          if (newRatio >= sigmaJsMouseProperties.minRatio) {
+          if (newRatio >= TW.conf.sigmaJsMouseProperties.minRatio) {
             // triggers coordinatesUpdated which sets the slider cursor
             partialGraph.camera.goTo({ratio: newRatio});
             return false;
@@ -1022,14 +1020,14 @@ TinaWebJS = function ( sigmacanvas ) {
 
       $("#zoomMinusButton").click(function () {
         var newRatio = TW.cam.ratio * 1.25
-        if (newRatio <= sigmaJsMouseProperties.maxRatio) {
+        if (newRatio <= TW.conf.sigmaJsMouseProperties.maxRatio) {
           // triggers coordinatesUpdated which sets the slider cursor
           partialGraph.camera.goTo({ratio: newRatio});
           return false;
         }
       });
 
-      if (TW.filterSliders) {
+      if (TW.conf.filterSliders) {
 
         // args: for display: target div ,
         //       for context: family/type prop value,
@@ -1051,7 +1049,7 @@ TinaWebJS = function ( sigmacanvas ) {
           step:.25,
           min:0,
           max:5,
-          value: sigmaJsDrawingProperties['labelSizeRatio'] || 1,
+          value: TW.conf.sigmaJsDrawingProperties['labelSizeRatio'] || 1,
           bgcolor:"#27c470",
           onchange:function(value){
             if (labelSizeTimeout) {
@@ -1097,7 +1095,7 @@ TinaWebJS = function ( sigmacanvas ) {
     }
 
     this.allPossibleActivetypes = function (cats) {
-        if (TW.debugFlags.logSettings) console.debug(`allPossibleActivetypes(cats=${cats})`)
+        if (TW.conf.debug.logSettings) console.debug(`allPossibleActivetypes(cats=${cats})`)
         var possibleActivetypes = {}
         var N=Math.pow(2 , cats.length);
 
diff --git a/tinawebJS/enviroment.js b/tinawebJS/enviroment.js
index 73ad51b83294f719704d93fa30a9b5bd8005a79a..462067a59bee28b90cb10e86b84490c4c14097b6 100755
--- a/tinawebJS/enviroment.js
+++ b/tinawebJS/enviroment.js
@@ -907,7 +907,7 @@ function showDisabledSlider(someDivId) {
 
 //============================= < SEARCH > =============================//
 function updateSearchLabels(id,name,type){
-    labels.push({
+    TW.labels.push({
         'id' : id,
         'label' : name,
         'desc': type
diff --git a/tinawebJS/main.js b/tinawebJS/main.js
index fbdc000f0aee76c382aba8f7a16990a389b3f248..95d2ada5a5e254bdfdef3b5e26cd29e093024174 100644
--- a/tinawebJS/main.js
+++ b/tinawebJS/main.js
@@ -37,7 +37,7 @@ var AjaxSync = (function(TYPE, URL, DATA, DT) {
     else DT = 'text'  // ie "if not json then raw xml string"
 
 
-    if (TW.debugFlags.logFetchers)
+    if (TW.conf.debug.logFetchers)
       console.log("---AjaxSync---\n", TYPE, URL, DATA, DT, "\n--------------")
 
     $.ajax({
@@ -60,7 +60,7 @@ var AjaxSync = (function(TYPE, URL, DATA, DT) {
                   format = "gexf" ;
                 }
                 else {
-                  if (TW.debugFlags.logFetchers)
+                  if (TW.conf.debug.logFetchers)
                     console.debug("after AjaxSync("+URL+") => response header="+header +"not xml => fallback on json");
                   format = "json" ;
                 }
@@ -101,7 +101,7 @@ TW.instance.initGUIListeners();
 TW.instance.initSearchListeners();
 
 // show the custom name of the app
-writeBrand(TW.branding)
+writeBrand(TW.conf.branding)
 
 console.log("Starting TWJS")
 
@@ -140,9 +140,15 @@ function syncRemoteGraphData () {
   var inFormat;            // = { db|api.json , somefile.json|gexf }
   var inData;              // = {nodes: [....], edges: [....], cats:...}
 
-  // case (1) read from DB => one ajax to api eg /services/api/graph?q=filters...
-  if (getUrlParam.type) {
-    console.warn("input case: @type [future: @sourcemode=api], using TW.bridge")
+  var mapLabel;            // user displayed label for this input dataset
+
+  // type of input
+  let sourcemode = isUndef(getUrlParam.sourcemode)?TW.sourcemode:getUrlParam.sourcemode
+
+  // case (1) read from remote DB via API bridge fetching
+  // ex: /services/api/graph?q=filters...
+  if (sourcemode == "api") {
+    console.log("input case: api, using TW.conf.sourceAPI")
 
     // the only API format, cf. inData
     inFormat = 'json'
@@ -151,29 +157,29 @@ function syncRemoteGraphData () {
     var sourceinfo = getUrlParam.nodeidparam
     var qtype = getUrlParam.type
     if(isUndef(sourceinfo) || isUndef(qtype)) {
-        console.warn("missing nodes filter/id param");
+        console.warn("missing nodes filter/id param to transmit to source api");
     }
     else {
         console.log("Received query of type:", qtype)
         if(qtype == "filter" || qtype == "uid"){
-          var theurl,thedata,thename;
+          var theurl,thedata
 
           // console.warn("===> PASSING ON QUERY (type "+qtype+") TO BRIDGE <===")
-          if(qtype=="uid") {
+          if (qtype=="uid") {
               // pr("bring the noise, case: unique_id");
               // pr(getClientTime()+" : DataExt Ini");
               // < === DATA EXTRACTION === >
-              theurl = TW.bridge["forNormalQuery"]
+              theurl = TW.conf.sourceAPI["forNormalQuery"]
 
               // NB before also passed it for Fa2 iterations (useless?)
               thedata = "qtype=uid&unique_id="+sourceinfo;
-              thename = "unique scholar";
+              mapLabel = "unique scholar";
           }
 
           if (qtype=="filter") {
               // pr("bring the noise, case: multipleQuery");
               // pr(getClientTime()+" : DataExt Ini");
-              theurl = TW.bridge["forFilteredQuery"];
+              theurl = TW.conf.sourceAPI["forFilteredQuery"];
 
               // json is twice URI encoded by whoswho to avoid both '"' and '%22'
               var json_constraints = decodeURIComponent(sourceinfo)
@@ -191,7 +197,7 @@ function syncRemoteGraphData () {
               // => thedata (for comexAPI):
               //   keywords[]="complex systems"&keywords[]="something"&countries="France"&countries[]="USA"
 
-              // => thename (for user display):
+              // => mapLabel (for user display):
               //   ("complex systems" or "something") and ("France" or "USA")
 
               // console.log("decoded filtering query", filteringKeyArrayPairs)
@@ -212,16 +218,16 @@ function syncRemoteGraphData () {
 
               if (restParams.length) {
                   thedata = "qtype=filters&" + restParams.join("&")
-                  thename = nameElts.join(" and ")
+                  mapLabel = nameElts.join(" and ")
               }
               else {
                   thedata = "qtype=filters&query=*"
-                  thename = "(ENTIRE NETWORK)"
+                  mapLabel = "(ENTIRE NETWORK)"
               }
           }
 
           // Assigning name for the network
-          if (! thename) {
+          if (! mapLabel) {
               elements = []
               queryarray = JSON.parse(ourGetUrlParam.nodeidparam)
               for(var i in queryarray) {
@@ -230,52 +236,47 @@ function syncRemoteGraphData () {
                       for(var j in item) elements.push(item[j])
                   }
               }
-              thename = '"'+elements.join('" , "')+'"';
+              mapLabel = '"'+elements.join('" , "')+'"';
           }
 
-          // £TODO restore thename
-          console.warn (thename, ":name not used anymore since refacto 10/05 could put on same level as inData as inMapname or smth")
-
           var bridgeRes = AjaxSync({ URL: theurl, DATA:thedata, TYPE:'GET', DT:'json' })
 
           // should be a js object with 'nodes' and 'edges' properties
           inData = bridgeRes.data
 
-          if (TW.debugFlags.logFetchers)   console.info("JSON input data", inData)
+          if (TW.conf.debug.logFetchers)   console.info("JSON input data", inData)
         }
         else {
             console.warn ("=> unsupported query type !")
         }
     }
   }
-  // case (2) gexf => in params or in preRes db.json, then 2nd ajax for a gexf file => covered here
-  // sourcemode == "serverfile"
+
+
+  // cases            (2)       and     (3) : we'll read a file from server
+  // sourcemode == "serverfile" or "servermenu" (several files with <select>)
   else {
-    console.warn("input case: @mode=db.json or @file=... [future: @sourcemode=serverfile], using server's gexf(s)")
-    // subcases:
-    // -> gexf file path is already specified in TW.mainfile
-    // -> gexf file path is in the urlparam @file
-    // -> @mode is db.json, files are listed in db.json file
-    //                  --> if @file also in url, choose the db.json one matching
-    //                  --> otherwise, choose the "first_file" from db.json list
+    console.log("input case: server-side file, using db.json or getUrlParam.file or TW.conf.sourceFile")
+
+    // -> @mode is servermenu, files are listed in db.json file (preRes ajax)
+    //      --> if @file also in url, choose the db.json one matching  <=== £TODO THIS CASE STILL TO FIX
+    //      --> otherwise, choose the "first_file" from db.json list
+
+    // -> @mode is serverfile
+    //      -> gexf file path is in the urlparam @file
+    //      -> gexf file path is already specified in TW.conf.sourceFile
 
     // ===================
     var the_file = "";
     // ===================
 
-
-    // TODO check if legacy apps use db.json name otherwise use mode == 'menufile'
-    //      and 'db.json' should be hardcoded (safer)
-    // if (!isUndef(getUrlParam.mode) && getUrlParam.mode == 'menufile') {
-
-
-    // menufile case comes before single file because it uses urlparam file too
-    if (!isUndef(getUrlParam.mode) && getUrlParam.mode == 'db.json') {
+    // menufile case : a list of source files in ./db.json
+    if (sourcemode == 'servermenu') {
         console.log("no @file arg nor TW.mainfile: trying FILEMENU db.json")
         // we'll first retrieve the menu of available files in db.json, then get the real data in a second ajax
         var infofile = "db.json"
 
-        if (TW.debugFlags.logFetchers)  console.info(`attempting to load infofile ${infofile}`)
+        if (TW.conf.debug.logFetchers)  console.info(`attempting to load infofile ${infofile}`)
         var preRES = AjaxSync({ URL: infofile, DT:"json" });
 
         if (preRES['OK'] && preRES.data) {
@@ -297,29 +298,30 @@ function syncRemoteGraphData () {
         if( isUndef(getUrlParam.file) ) {
             the_file = first_path+"/"+first_file
         } else {
+            // £POSS; match on the full paths from db.json
             the_file = first_path+"/"+getUrlParam.file
         }
 
         var files_selector = '<select onchange="jsActionOnGexfSelector(this.value);">'
 
         for( var path in preRES.data ) {
-            var the_gexfs = preRES.data[path]["gexfs"]
-            for(var aGexf in the_gexfs) {
+            var theGexfs = preRES.data[path]["gexfs"]
+            for(var aGexf in theGexfs) {
                 var gexfBasename = aGexf.replace(/\.gexf$/, "") // more human-readable in the menu
                 TW.gexfPaths[gexfBasename] = path+"/"+aGexf
                 // ex : "RiskV2PageRank1000.gexf":data/AXA/RiskV2PageRank1000.gexf
                 // (we assume there's no duplicate basenames)
 
 
-                if (TW.debugFlags.logFetchers)
-                  console.log("\t\t\t"+gexfBasename+ "   -> table:" +the_gexfs[aGexf]["semantic"]["table"] )
+                if (TW.conf.debug.logFetchers)
+                  console.log("\t\t\t"+gexfBasename+ "   -> table:" +theGexfs[aGexf]["semantic"]["table"] )
 
 
                 // -------------------------->8------------------------------------------
                 // £TODO this part is underspecified
                 // if used in some usecases, port it to nodetypes
                 // otherwise remove
-                // TW.field[path+"/"+aGexf] = the_gexfs[aGexf]["semantic"]["table"]
+                // TW.field[path+"/"+aGexf] = theGexfs[aGexf]["semantic"]["table"]
                 // ex : data/AXA/RiskV2PageRank5000.gexf:"ISItermsAxa_2015"
                 // -------------------------->8------------------------------------------
 
@@ -334,24 +336,25 @@ function syncRemoteGraphData () {
         console.log("files_selector HTML", files_selector)
         $("#network").html(files_selector)
     }
+
     // direct urlparam file case
     else if( !isUndef(getUrlParam.file)  ) {
       the_file = getUrlParam.file
     }
     // direct file fallback case: specified file in settings_explorer
-    else if (TW.mainfile && linkCheck(TW.mainfile)) {
+    else if (TW.conf.sourceFile && linkCheck(TW.conf.sourceFile)) {
       console.log("no @file arg: trying TW.mainfile from settings")
-      the_file = TW.mainfile;
+      the_file = TW.conf.sourceFile;
     }
     else {
-      console.warn("No specified input!")
+      console.error(`No specified input and neither db.json nor TW.conf.sourceFile ${TW.conf.sourceFile} are present`)
     }
 
     var finalRes = AjaxSync({ URL: the_file });
     inData = finalRes["data"]
     inFormat = finalRes["format"]
 
-    if (TW.debugFlags.logFetchers) {
+    if (TW.conf.debug.logFetchers) {
       console.warn('@the_file', finalRes["OK"], the_file)
       console.log('  fetch result: format', inFormat)
       console.log('  fetch result: typeof data', typeof inData)
@@ -359,7 +362,7 @@ function syncRemoteGraphData () {
     }
   }
 
-  return [inFormat, inData]
+  return [inFormat, inData, mapLabel]
 
 }
 
@@ -380,13 +383,13 @@ function mainStartGraph(inFormat, inData, twInstance) {
   }
   else {
 
-      if (TW.debugFlags.logParsers)   console.log("parsing the data")
+      if (TW.conf.debug.logParsers)   console.log("parsing the data")
 
       let start = new ParseCustom(  inFormat , inData );
       let catsInfos = start.scanFile();
 
       TW.categories = catsInfos.categories
-      if (TW.debugFlags.logParsers){
+      if (TW.conf.debug.logParsers){
         console.log(`Source scan found ${TW.categories.length} node categories: ${TW.categories}`)
       }
 
@@ -407,7 +410,7 @@ function mainStartGraph(inFormat, inData, twInstance) {
       // XML parsing from ParseCustom
       var dicts = start.makeDicts(TW.categories); // > parse json or gexf, dictfy
 
-      if (TW.debugFlags.logParsers)   console.info("parsing result:", dicts)
+      if (TW.conf.debug.logParsers)   console.info("parsing result:", dicts)
 
       TW.Nodes = dicts.nodes;
       TW.Edges = dicts.edges;
@@ -436,21 +439,21 @@ function mainStartGraph(inFormat, inData, twInstance) {
       // so we just need to handle mismatches here (when user-suggested cats were absent)
       if (TW.categories.length == 2) {
         console.info("== 'bipartite' case ==")
-        if (TW.catSoc != TW.categories[0]) {
-          console.warn(`Observed social category "${TW.categories[0]}" overwrites user-suggested TW.catSoc ("${TW.catSoc}")`)
-          TW.catSoc = TW.categories[0]
+        if (TW.conf.catSoc != TW.categories[0]) {
+          console.warn(`Observed social category "${TW.categories[0]}" overwrites user-suggested TW.conf.catSoc ("${TW.conf.catSoc}")`)
+          TW.conf.catSoc = TW.categories[0]
         }
-        if (TW.catSem != TW.categories[1]) {
-          console.warn(`Observed semantic category "${TW.categories[1]}" overwrites user-suggested TW.catSem "(${TW.catSem})"`)
-          TW.catSem = TW.categories[1]
+        if (TW.conf.catSem != TW.categories[1]) {
+          console.warn(`Observed semantic category "${TW.categories[1]}" overwrites user-suggested TW.conf.catSem "(${TW.conf.catSem})"`)
+          TW.conf.catSem = TW.categories[1]
         }
       }
       else if (TW.categories.length == 1) {
         console.info("== monopartite case ==")
         // FIXME it would be more coherent with all tina usecases (like gargantext or tweetoscope) for the default category to be catSem instead of Soc
-        if (TW.catSoc != TW.categories[0]) {
-          console.warn(`Observed unique category "${TW.categories[0]}" overwrites user-suggested TW.catSoc ("${TW.catSoc}")`)
-          TW.catSoc = TW.categories[0]
+        if (TW.conf.catSoc != TW.categories[0]) {
+          console.warn(`Observed unique category "${TW.categories[0]}" overwrites user-suggested TW.conf.catSoc ("${TW.conf.catSoc}")`)
+          TW.conf.catSoc = TW.categories[0]
         }
       }
       else {
@@ -528,13 +531,13 @@ function mainStartGraph(inFormat, inData, twInstance) {
           },
 
           // 2) settings_explorer values
-          sigmaJsDrawingProperties,
-          sigmaJsGraphProperties,
-          sigmaJsMouseProperties
+          TW.conf.sigmaJsDrawingProperties,
+          TW.conf.sigmaJsGraphProperties,
+          TW.conf.sigmaJsMouseProperties
       )
 
 
-      if (TW.debugFlags.logSettings) console.info("sigma settings", TW.customSettings)
+      if (TW.conf.debug.logSettings) console.info("sigma settings", TW.customSettings)
 
 
       // ==================================================================
@@ -629,7 +632,7 @@ function mainStartGraph(inFormat, inData, twInstance) {
               LevelButtonDisable(true)
 
           // recreate sliders after activetype or level changes
-          if (TW.filterSliders
+          if (TW.conf.filterSliders
               && (present.level != past.level
                   || present.activetypes.map(Number).join("|") != past.activetypes.map(Number).join("|"))) {
 
@@ -666,7 +669,7 @@ function mainStartGraph(inFormat, inData, twInstance) {
       };
 
 
-      if (!TW.filterSliders) {
+      if (!TW.conf.filterSliders) {
 
         var filterEls = document.getElementsByClassName('weight-selectors')
 
@@ -698,7 +701,7 @@ function mainStartGraph(inFormat, inData, twInstance) {
         outboundAttractionDistribution: false
       }
 
-      if (TW.debugFlags.logSettings) console.info("FA2 settings", TW.FA2Params)
+      if (TW.conf.debug.logSettings) console.info("FA2 settings", TW.FA2Params)
 
       // init FA2 for any future forceAtlas2 calls
       TW.partialGraph.configForceAtlas2(TW.FA2Params)
@@ -720,9 +723,9 @@ function mainStartGraph(inFormat, inData, twInstance) {
       TW.partialGraph.camera.goTo({x:0, y:0, ratio:0.9, angle: 0})
 
       // mostly json data are extracts provided by DB apis => no positions
-      if (inFormat == "json")  TW.fa2enabled = true
+      if (inFormat == "json")  TW.conf.fa2Enabled = true
 
-      // will run fa2 if enough nodes and TW.fa2enabled == true
+      // will run fa2 if enough nodes and TW.conf.fa2Enabled == true
       sigma_utils.smartForceAtlas()
 
 
@@ -731,7 +734,7 @@ function mainStartGraph(inFormat, inData, twInstance) {
           $("#changetype").hide();
           $("#taboppos").hide();
 
-          // if (TW.catSem && TW.catSoc) {
+          // if (TW.conf.catSem && TW.conf.catSoc) {
             setTimeout(function () {
                 // tabneigh: show "Related" tab
                 document.querySelector('.etabs a[href="#tabs2"]').click()
diff --git a/tinawebJS/methods.js b/tinawebJS/methods.js
index 20230c6a3d033b692a57d1f74ef0971484a9a4ac..7f35248544ca6f85a49fd87b754d219413fca2f0 100755
--- a/tinawebJS/methods.js
+++ b/tinawebJS/methods.js
@@ -3,7 +3,7 @@
 
 // settings: {norender: Bool}
 function cancelSelection (fromTagCloud, settings) {
-    if (TW.debugFlags.selections) { console.log("\t***in cancelSelection"); }
+    if (TW.conf.debug.selections) { console.log("\t***in cancelSelection"); }
     if (!settings) settings = {}
 
     highlightSelectedNodes(false); //Unselect the selected ones :D
@@ -14,8 +14,9 @@ function cancelSelection (fromTagCloud, settings) {
 
     TW.partialGraph.states.slice(-1)[0].selections=[]
 
-    //Nodes colors go back to normal
-    overNodes=false;
+    // global flag
+    TW.selectionActive = false
+
 
     //Edges colors go back to normal
     if (TW.partialGraph.settings('drawEdges')) {
@@ -77,9 +78,6 @@ function cancelSelection (fromTagCloud, settings) {
     if(TW.partialGraph.states.slice(-1)[0].level)
         LevelButtonDisable(true);
 
-    // global flag
-    TW.selectionActive = false
-
     if (!settings.norender) {
       // finally redraw
       TW.partialGraph.render();
@@ -115,7 +113,7 @@ function getActivetypesKey() {
 
 
 function highlightSelectedNodes(flag){
-    if (TW.debugFlags.logSelections)
+    if (TW.conf.debug.logSelections)
       console.log("\t***methods.js:highlightSelectedNodes(flag)"+flag+" selEmpty:"+is_empty(selections))
     if(!is_empty(selections)){
         for(var i in selections) {
@@ -126,11 +124,11 @@ function highlightSelectedNodes(flag){
 
 function alertCheckBox(eventCheck){
     // NB: we use 2 booleans to adapt to SHIFT checking
-    //      - var checkBox  ---------> has the real box state
-    //      - var manuallyChecked  --> remembers if it was changed here
+    //      - var TW.checkBox  ---------> has the real box state
+    //      - var TW.manuallyChecked  --> remembers if it was changed here
     if(!isUndef(eventCheck.checked)) {
-        checkBox=eventCheck.checked;
-        manuallyChecked = eventCheck.checked
+        TW.checkBox=eventCheck.checked;
+        TW.manuallyChecked = eventCheck.checked
     }
 }
 
@@ -174,7 +172,7 @@ function RefreshState(newNOW){
     	// N : number of nodes
     	// k : number of ( selected nodes + their neighbors )
     	// s : number of selections
-        var N=( Object.keys(TW.Nodes).filter(function(n){return TW.Nodes[n].type==TW.catSoc}) ).length
+        var N=( Object.keys(TW.Nodes).filter(function(n){return TW.Nodes[n].type==TW.conf.catSoc}) ).length
         var k=Object.keys(getNeighs(Object.keys(selections),nodes1)).length
         var s=Object.keys(selections).length
         console.log("in social N: "+N+" - k: "+k+" - s: "+s)
@@ -195,7 +193,7 @@ function RefreshState(newNOW){
 
     }
     if(NOW=="B" || NOW=="b") {
-        var N=( Object.keys(TW.Nodes).filter(function(n){return TW.Nodes[n].type==TW.catSem}) ).length
+        var N=( Object.keys(TW.Nodes).filter(function(n){return TW.Nodes[n].type==TW.conf.catSem}) ).length
         var k=Object.keys(getNeighs(Object.keys(selections),nodes2)).length
         var s=Object.keys(selections).length
         console.log("in semantic N: "+N+" - k: "+k+" - s: "+s)
@@ -357,7 +355,7 @@ function htmlfied_nodesatts(elems){
             }
             socnodes.push(information);
         } else {
-            if(node.type==TW.catSoc){
+            if(node.type==TW.conf.catSoc){
                 information += '<li><b>' + node.label + '</b></li>';
                 if(node.htmlCont==""){
                     if (!isUndef(node.level)) {
@@ -369,7 +367,7 @@ function htmlfied_nodesatts(elems){
                 socnodes.push(information)
             }
 
-            if(node.type==TW.catSem){
+            if(node.type==TW.conf.catSem){
                 information += '<li><b>' + node.label + '</b></li>';
                 google='<a href=http://www.google.com/#hl=en&source=hp&q=%20'+node.label.replace(" ","+")+'%20><img src="'+'img/google.png"></img></a>';
                 wiki = '<a href=http://en.wikipedia.org/wiki/'+node.label.replace(" ","_")+'><img src="'+'img/wikipedia.png"></img></a>';
@@ -606,7 +604,7 @@ function graphTagCloudElem(nodes) {
     TW.partialGraph.camera.goTo({x:0, y:0, ratio:0.9, angle: 0})
     TW.partialGraph.refresh({skipIndexation:true});
 
-    sigma_utils.smartForceAtlas(TW.fa2milliseconds/2)
+    sigma_utils.smartForceAtlas(TW.conf.fa2Milliseconds/2)
 
     //
     // ChangeGraphAppearanceByAtt(true)
@@ -681,9 +679,11 @@ function prepareNodesRenderingProperties(nodesDict) {
   for (var nid in nodesDict) {
     var n = nodesDict[nid]
 
+    let sizeFactor = TW.conf.sizeMult[TW.catDict[n.type]] || 1
+
     // 3 decimals is way more tractable
     // and quite enough in precision !!
-    n.size = Math.round(n.size*1000)/1000
+    n.size = Math.round(n.size*sizeFactor*1000)/1000
 
     // new initial setup of properties
     n.active = false
@@ -722,8 +722,8 @@ function prepareNodesRenderingProperties(nodesDict) {
       n.color = `rgb(${rgbStr})`
     }
     else {
-      n.color = TW.defaultNodeColor
-      rgbStr = TW.defaultNodeColor.split(',').splice(0, 3).join(',');
+      n.color = TW.conf.defaultNodeColor
+      rgbStr = TW.conf.defaultNodeColor.split(',').splice(0, 3).join(',');
     }
 
     n.customAttrs = {
@@ -757,7 +757,7 @@ function prepareEdgesRenderingProperties(edgesDict, nodesDict) {
 
     var rgbStr = sigmaTools.edgeRGB(nodesDict[e.source].color, nodesDict[e.target].color)
 
-    e.color = "rgba("+rgbStr+","+TW.edgeDefaultOpacity+")"
+    e.color = "rgba("+rgbStr+","+TW.conf.edgeDefaultOpacity+")"
     e.customAttrs = {
       grey: false,
       activeEdge : false,
diff --git a/tinawebJS/sigma.parseCustom.js b/tinawebJS/sigma.parseCustom.js
index 3e08386df36a544fbbe950975882fcb9696dc453..8c22055d3d79aa88ebb19ac8be66bcb7293d4314 100755
--- a/tinawebJS/sigma.parseCustom.js
+++ b/tinawebJS/sigma.parseCustom.js
@@ -213,7 +213,7 @@ function scanGexf(gexfContent) {
 // sorting observed node types into Sem/Soc (factorized 11/05/2017)
 // --------------------
 // FIXME this factorizes what we had twice (json & gexf scanFile workflows),
-//       and we just added missing TW.catSoc/Sem comparisons
+//       and we just added missing TW.conf.catSoc/Sem comparisons
 //       *but it doesn't fix the underlying logic*
 //       (current expected structure in 'categories' can only accomodate 2 types
 //        and the way it and catDict are used is not entirely coherent throughout
@@ -239,7 +239,7 @@ function sortNodeTypes(observedTypesDict) {
       // but in practice it's more often terms. anyways doesn't affect much
       catDict[observedTypes[0]] = 0;
 
-      if (TW.debugFlags.logParsers)
+      if (TW.conf.debug.logParsers)
         console.log(`cat unique (${observedTypes[0]}) =>0`)
   }
   if(nTypes>1) {
@@ -248,7 +248,7 @@ function sortNodeTypes(observedTypesDict) {
       // POSSible: allow more than 2 cats
       for(var i in observedTypes) {
           let c = observedTypes[i]
-          if(c == TW.catSoc || (c != TW.catSem && c.indexOf("term")==-1)) {// NOT a term-category
+          if(c == TW.conf.catSoc || (c != TW.catSem && c.indexOf("term")==-1)) {// NOT a term-category
               newcats[0] = c;
               catDict[c] = 0;
           }
@@ -281,14 +281,14 @@ function facetsBinning (valuesIdx, Atts_2_Exclude) {
 
   let facetIdx = {}
 
-  if (TW.debugFlags.logFacets) {
+  if (TW.conf.debug.logFacets) {
     console.log('dictfyGexf: begin TW.Clusters')
     var classvalues_deb = performance.now()
   }
 
   // var gotClusters = false
   // for (var nodecat in valuesIdx) {
-  //   gotClusters = gotClusters || (valuesIdx[nodecat]['cluster_index'] || valuesIdx[nodecat][TW.nodeClusAtt])
+  //   gotClusters = gotClusters || (valuesIdx[nodecat]['cluster_index'] || valuesIdx[nodecat][TW.conf.nodeClusAtt])
   // }
 
   // all scanned attributes get an inverted index
@@ -332,11 +332,11 @@ function facetsBinning (valuesIdx, Atts_2_Exclude) {
 
         // how many bins for this attribute ?
         var nBins = 3
-        if (TW.customLegendsBins && TW.customLegendsBins[at]) {
-          nBins = TW.customLegendsBins[at]
+        if (TW.conf.customLegendsBins && TW.conf.customLegendsBins[at]) {
+          nBins = TW.conf.customLegendsBins[at]
         }
-        else if (TW.legendsBins) {
-          nBins = TW.legendsBins
+        else if (TW.conf.legendsBins) {
+          nBins = TW.conf.legendsBins
         }
 
         // create tick thresholds
@@ -345,7 +345,7 @@ function facetsBinning (valuesIdx, Atts_2_Exclude) {
           legendRefTicks.push(valuesIdx[cat][at].vals[nthVal])
         }
 
-        if (TW.debugFlags.logFacets)    console.debug("intervals for", at, legendRefTicks)
+        if (TW.conf.debug.logFacets)    console.debug("intervals for", at, legendRefTicks)
 
         var nTicks = legendRefTicks.length
         var sortedDistinctVals = Object.keys(valuesIdx[cat][at].map).sort(function(a,b){return Number(a)-Number(b)})
@@ -413,16 +413,16 @@ function facetsBinning (valuesIdx, Atts_2_Exclude) {
     }
 
     // 'clust_default' is an alias to the user-defined default clustering
-    if (TW.nodeClusAtt != undefined
-        && facetIdx[cat][TW.nodeClusAtt]   // <= if found in data
+    if (TW.conf.nodeClusAtt != undefined
+        && facetIdx[cat][TW.conf.nodeClusAtt]   // <= if found in data
         && !facetIdx[cat]['clust_default'] // <= and if an attr named 'clust_default' was not already in data
       ) {
-      facetIdx[cat]['clust_default'] = facetIdx[cat][TW.nodeClusAtt]
+      facetIdx[cat]['clust_default'] = facetIdx[cat][TW.conf.nodeClusAtt]
     }
 
   }
 
-  if (TW.debugFlags.logFacets) {
+  if (TW.conf.debug.logFacets) {
     var classvalues_fin = performance.now()
     console.log('end TW.Clusters, own time:', classvalues_fin-classvalues_deb)
   }
@@ -435,7 +435,7 @@ function facetsBinning (valuesIdx, Atts_2_Exclude) {
 // for {1,2}partite graphs
 function dictfyGexf( gexf , categories ){
 
-  if (TW.debugFlags.logParsers)
+  if (TW.conf.debug.logParsers)
     console.log("ParseCustom gexf 2nd loop, main data extraction, with categories", categories)
 
 
@@ -455,11 +455,9 @@ function dictfyGexf( gexf , categories ){
     // var edgesAttributes = declaredAtts.eAttrs
 
     var elsNodes = gexf.getElementsByTagName('nodes') // The list of xml nodes 'nodes' (plural)
-    labels = [];
-    minNodeSize=999.00;
-    maxNodeSize=0.001;
-    numberOfDocs=0;
-    numberOfNGrams=0;
+    TW.labels = [];
+    minNodeSize=10000000;
+    maxNodeSize=0;
 
     // debug: for local stats
     // let allSizes = []
@@ -579,8 +577,8 @@ function dictfyGexf( gexf , categories ){
             if(!node.size) console.log("node without size: "+node.id+" : "+node.label);
 
             // user-indicated default => copy for old default accessors
-            if (node.attributes[TW.nodeClusAtt]) {
-              node.attributes['clust_default'] = node.attributes[TW.nodeClusAtt]
+            if (node.attributes[TW.conf.nodeClusAtt]) {
+              node.attributes['clust_default'] = node.attributes[TW.conf.nodeClusAtt]
             }
 
             // save record
@@ -636,7 +634,7 @@ function dictfyGexf( gexf , categories ){
         var edgesNode = edgesNodes[i];
         var edgeNodes = edgesNode.getElementsByTagName('edge');
 
-        if (TW.debugFlags.logParsers)
+        if (TW.conf.debug.logParsers)
           console.log("edgeNodes.length", edgeNodes.length)
 
         for(j=0; j<edgeNodes.length; j++) {
@@ -651,7 +649,7 @@ function dictfyGexf( gexf , categories ){
                 id: indice,
                 source: source,
                 target: target,
-                type : (type) ? type : sigmaJsDrawingProperties['defaultEdgeType'],
+                type : (type) ? type : TW.conf.sigmaJsDrawingProperties['defaultEdgeType'],
                 label: "",
                 categ: "",
                 attributes: []
@@ -895,7 +893,7 @@ function scanJSON( data ) {
 // Level-00
 // for {1,2}partite graphs
 function dictfyJSON( data , categories ) {
-    if (TW.debugFlags.logParsers)
+    if (TW.conf.debug.logParsers)
       console.log("ParseCustom json 2nd loop, main data extraction, with categories", categories)
 
     var catDict = {}
@@ -952,11 +950,11 @@ function dictfyJSON( data , categories ) {
 
     TW.Clusters = facetsBinning (tmpVals, Atts_2_Exclude)
 
-    colorList.sort(function(){ return Math.random()-0.5; });
+    TW.colorList.sort(function(){ return Math.random()-0.5; });
     for (var i in nodes ){
         if (nodes[i].color=="#FFFFFF") {
             var attval = ( isUndef(nodes[i].attributes) || isUndef(nodes[i].attributes["clust_default"]) )? 0 : nodes[i].attributes["clust_default"] ;
-            nodes[i].color = colorList[ attval ]
+            nodes[i].color = TW.colorList[ attval ]
         }
     }
 
diff --git a/tinawebJS/sigmaUtils.js b/tinawebJS/sigmaUtils.js
index dae3f919a8225e6514fa0008266dd742b6f04bda..aff145b14151a07b000109cf3bd29710c80c47aa 100755
--- a/tinawebJS/sigmaUtils.js
+++ b/tinawebJS/sigmaUtils.js
@@ -14,7 +14,7 @@ SigmaUtils = function () {
             var n = nodes[i];
             // console.debug('tr >>> fgr node', n)
 
-            if(initialActivetypes[catDict[n.type]] || TW.debugFlags.initialShowAll) {
+            if(initialActivetypes[catDict[n.type]] || TW.conf.debug.initialShowAll) {
                 // var node = {
                 //     id : n.id,
                 //     label : n.label,
@@ -111,7 +111,7 @@ SigmaUtils = function () {
 
         context.beginPath();
 
-        if (TW.selectedColor == "node")
+        if (TW.conf.nodesGreyBorderColor == "node")
           context.fillStyle = TW.handpickedcolor? node.customAttrs.alt_color : node.color; // node's
         else
           context.fillStyle = "#F7E521"; // yellow
@@ -204,11 +204,11 @@ SigmaUtils = function () {
         // console.debug(`t=${tstamp()} curve render activeedge: ${edgeInfos(edge)})`)
       }
       else if (edge.customAttrs.grey) {
-        color = TW.edgeGreyColor
+        color = TW.conf.edgeGreyColor
         size = 1
       }
       else {
-        color = "rgba( "+baseRGB+" , "+TW.edgeDefaultOpacity+")";
+        color = "rgba( "+baseRGB+" , "+TW.conf.edgeDefaultOpacity+")";
         size = defSize
       }
 
@@ -256,11 +256,11 @@ SigmaUtils = function () {
         color = 'rgba('+rgb.join()+',.7)'
       }
       else if (edge.customAttrs.grey) {
-        color = TW.edgeGreyColor
+        color = TW.conf.edgeGreyColor
         size = 1
       }
       else {
-        // color = "rgba( "+rgb.join()+" , "+TW.edgeDefaultOpacity+")";
+        // color = "rgba( "+rgb.join()+" , "+TW.conf.edgeDefaultOpacity+")";
         color = edge.customAttrs.true_color
         size = defSize
       }
@@ -294,7 +294,7 @@ SigmaUtils = function () {
 
         // mode variants
         if (TW.selectionActive) {
-          // passive nodes should blend in the grey of TW.edgeGreyColor
+          // passive nodes should blend in the grey of TW.conf.edgeGreyColor
           // cf settings_explorerjs, defgrey_color and greyEverything()
           if (node.customAttrs.grey) {
             if (! TW.handpickedcolor) {
@@ -310,7 +310,7 @@ SigmaUtils = function () {
               nodeColor = node.customAttrs.altgrey_color
             }
             // nice looking uniform grey
-            borderColor = TW.nodesGreyBorderColor
+            borderColor = TW.conf.nodesGreyBorderColor
           }
           // neighbor nodes <=> (highlight flag AND selectionActive)
           else if(node.customAttrs.highlight) {
@@ -501,10 +501,9 @@ SigmaUtils = function () {
       //  - conditions on graph size (£TODO use these to slowDown small graphs)
       //  - edges management (turns them off and restores them after finished)
       this.smartForceAtlas = function (fa2duration) {
-
-        if (TW.fa2Available) {
+        if (TW.conf.fa2Available) {
           if (!fa2duration) {
-            fa2duration = parseInt(TW.fa2milliseconds) || 4000
+            fa2duration = parseInt(TW.conf.fa2Milliseconds) || 4000
           }
 
           // togglability case
@@ -514,7 +513,7 @@ SigmaUtils = function () {
           }
           // normal case
           else {
-              if ( TW.fa2enabled && TW.partialGraph.graph.nNodes() >= TW.minNodesForAutoFA2) {
+              if ( TW.conf.fa2Enabled && TW.partialGraph.graph.nNodes() >= TW.conf.minNodesForAutoFA2) {
                 // hide edges during work for smaller cpu load
                 if (TW.partialGraph.settings('drawEdges')) {
                   this.toggleEdges(false)
@@ -547,7 +546,7 @@ SigmaUtils = function () {
 function createWaitIcon(idname, width) {
   let icon = document.createElement('img')
 
-  icon.src = TW.libspath + '/img2/loader.gif'
+  icon.src = TW.conf.libspath + '/img2/loader.gif'
 
   icon.style.position = 'absolute'
   icon.style.left = '0'
@@ -886,7 +885,7 @@ function repaintEdges() {
 // rewrite of clustersBy with binning and for attributes that can have negative float values
 
 // NB - binning is done at parseCustom
-//    - number of bins can be specified by attribute name in TW.customLegendsBins
+//    - number of bins can be specified by attribute name in TW.conf.customLegendsBins
 function colorsRelByBins(daclass) {
   var binColors
   var doModifyLabel = false
@@ -1202,7 +1201,7 @@ function colorsBy(daclass) {
     }
     else {
       // shuffle on entire array is better than random sorting function on each element
-      var randomColorList = shuffle(colorList)
+      var randomColorList = shuffle(TW.colorList)
 
       for(var j in TW.nodeIds) {
           var the_node = TW.Nodes[ TW.nodeIds[j] ]
diff --git a/tinawebJS/sigma_tools.js b/tinawebJS/sigma_tools.js
index f35769a7838cd8fd2e0e4da93c9f4f8f2172fa7f..d31c5c92132383c2f509a2847da9da12d245ec7c 100644
--- a/tinawebJS/sigma_tools.js
+++ b/tinawebJS/sigma_tools.js
@@ -45,7 +45,7 @@ sigmaTools = (function(stools) {
         var rawEdge = rawGexfEdges[i]
 
         var rgbStr = sigmaTools.edgeRGB(newNodes[rawEdge.source].color, newNodes[rawEdge.target].color)
-        var leColor = "rgba("+rgbStr+","+TW.edgeDefaultOpacity+")"
+        var leColor = "rgba("+rgbStr+","+TW.conf.edgeDefaultOpacity+")"
 
         var newEid = rawEdge.source+";"+rawEdge.target;
         var newEdge = {