diff --git a/src/lib.rs b/src/lib.rs
new file mode 100644
index 0000000..9b52e00
--- /dev/null
+++ b/src/lib.rs
@@ -0,0 +1,289 @@
+/*! Zterton
+*/
+// Copyright 2021, Jesús Pérez Lorenzo
+//
+// Make rustc's built-in lints more strict and set clippy into a whitelist-based configuration so
+// we see new lints as they get written, then opt out of ones we have seen and don't want
+// #![allow(warnings, unused)]
+#![allow(warnings, unused)]
+// #![warn(warnings, rust_2018_idioms)]
+#![warn(clippy::all, clippy::pedantic)]
+#![allow(
+  clippy::float_arithmetic,
+  clippy::implicit_return,
+  clippy::needless_return,
+  clippy::print_stdout,
+  clippy::multiple_inherent_impl
+)]
+#![forbid(unsafe_code)] // Enforce my policy of only allowing it in my own code as a last resort
+
+#[allow(unused_imports)]
+
+#[macro_use]
+extern crate serde_derive;
+use dotenv::dotenv;
+use glob::glob;
+use std::fs; 
+use std::net::{IpAddr, Ipv4Addr, SocketAddr, ToSocketAddrs};
+use std::env;
+// use warp::Filter;
+
+// use salvo::prelude::*;
+// use tracing_subscriber;
+// use tracing_subscriber::fmt::format::FmtSpan;
+use app_errors::AppError;
+
+use app_env::{
+  appenv::AppEnv,
+  module::Module,
+  config::Config,
+  AppRunMode, BxDynResult, Zterton
+};
+// use crate::auth::defs::AuthStore;
+
+/// [`AppEnv`](models/struct.AppEnv.html) init with default,  __`main_store`__ is set to [slab](../slab/index.html):
+/// ```
+///  Some(Storage::default());
+/// ```
+#[allow(clippy::print_stdout)]
+async fn load_app_env(app_env: &mut AppEnv,verbose: isize) -> BxDynResult<()> {
+	let args: Vec<String> = std::env::args().collect();
+	let mut arg_cfg_path = String::from("");
+	let mut arg_env_path = String::from("");
+	args.iter().enumerate().for_each(|(idx,arg)| {
+		if arg == "-c" { 
+			arg_cfg_path=args[idx+1].to_owned();
+		} else if arg == "-e" { 
+			arg_env_path=args[idx+1].to_owned();
+		}
+  });
+  let config_content = Config::load_file_content(verbose,&arg_cfg_path);
+  #[allow(unused_assignments)]
+  if !config_content.contains("run_mode") {
+    let e = format!(
+      "App config load error {}: {}",
+      &app_env.info.appmode,
+      AppError::RunningModeError
+    );
+    return Err(e.into());
+  }
+  // println!("content: {}",&config_content);
+  app_env.config = Config::new(config_content,verbose);
+  if app_env.get_curr_websrvr_config().srv_host.is_empty() {
+    let e = format!(
+        "App config error, check config APP_CONFIG_PATH: {}",
+        &envmnt::get_or("APP_CONFIG_PATH", "config.toml")
+      );
+    return Err(e.into());
+  }
+  // Load app_msg from file
+  let app_msg = fs::read_to_string(format!("{}/{}/.app_msg",&envmnt::get_or("APP_HOME", "."),app_env.get_curr_websrvr_config().home_path))
+		.unwrap_or_else(|e|{
+	  eprintln!("{}",e);
+		String::from("")
+	});
+  if check_running_mode(app_env).is_ok() {
+    println!(
+      "\n{} {}\n(c) {}\n\n{}",
+      &app_env.info.name, &app_env.info.version, &app_env.info.author, &app_env.info.about
+    );
+    println!("Web: {}",&app_env.get_curr_websrvr_config().name);
+    println!(
+      "\nRunning mode: {} {}\n{}",
+      &app_env.info.appmode, &app_env.info.usedata, app_msg
+    )
+  } else {
+    println!(
+      "Error checking running mode: {}",
+      app_env.config.run_mode.to_owned()
+    );
+    let e = format!(
+      "App load error {}: {}",
+      &app_env.info.appmode,
+      AppError::RunningModeError
+    );
+    return Err(e.into());
+    // return Err(Box::new(e.into()));
+  }
+  // dbg!(&app_env);
+ // load_colls_def(app_env).await?;
+  load_module_def(app_env, verbose).await?;
+  Ok(())
+}
+
+/// load collections definiton from resources
+// #[allow(clippy::print_stdout)]
+// async fn load_colls_def(app_env: &mut AppEnv) -> BxDynResult<()> {
+//   let pattern = format!("{}/collections/*.toml", &app_env.config.resources_path);
+//   for item in glob(&pattern).expect("Failed to find coll defs") {
+//     if let Ok(path) = item {
+//       let content = Collection::load_fs_content(&path);
+//       let coll_defs: toml::Value = toml::from_str(&content)?;
+//       if ! &content.is_empty() {
+//         let coll_def: Collection::new(&content);
+//         if let Some(name) = coll_defs["name"].as_str() {
+//           println!("Collection: {} from {:#?}", &name, &path.display());
+//           app_env.collections.insert(name.to_string(), coll_defs);
+//         }
+//       }
+//     }
+//   }
+//   Ok(())
+// }
+
+/// load modules definiton from resources
+#[allow(clippy::print_stdout)]
+async fn load_module_def(app_env: &mut AppEnv, verbose: isize) -> BxDynResult<()> {
+  let pattern = format!("{}/modules/*.toml",&app_env.get_curr_websrvr_config().resources_path);
+  for item in glob(&pattern).expect("Failed to find coll defs") {
+    if let Ok(path) = item {
+      let content = Module::load_fs_content(&path);
+      if ! &content.is_empty() {
+        let module_def = Module::new(content, verbose);
+        if ! module_def.key.is_empty() {
+					if verbose > 0 {
+             println!("Module: {} from {:#?}", &module_def.name, &path.display());
+					}
+          app_env.modules.insert(module_def.key.to_owned(), module_def);
+        }
+      }
+    }
+  }
+  Ok(())
+}
+
+#[allow(clippy::missing_errors_doc)]
+pub fn check_running_mode(app_env: &mut AppEnv) -> BxDynResult<()> {
+	app_env.info = app_env.info.load_data(app_env);
+  // TODO check mode license ?
+  app_env.info.appmode = AppRunMode::get_from(&app_env.config.run_mode);
+  if app_env.info.usedata.is_empty() && app_env.info.appmode != AppRunMode::Basic {
+    app_env.checked = false;
+    let e = format!("Running mode load error {}", &app_env.info.appmode);
+    Err(e.into())
+  } else {
+    if app_env.info.appmode == AppRunMode::Basic {
+      app_env.info.usedata = String::from("");
+    }
+    app_env.checked = true;
+    Ok(())
+  }
+}
+ 
+/// # Zterton app is a backend services
+// static DB: Lazy<models::Db> = Lazy::new(|| models::blank_db());
+
+#[allow(clippy::missing_errors_doc,clippy::dbg_macro)]
+pub async fn init_app(app_env: &mut AppEnv,verbose: isize) -> std::io::Result<()> {
+  dotenv().ok();
+
+  let matches = clap::App::new(&app_env.info.name.to_owned())
+    .version(app_env.info.version.as_str())
+    .author(app_env.info.author.as_str())
+    .about(app_env.info.about.as_str())
+    .arg(
+      clap::Arg::with_name("debug")
+        .short("d")
+        .long("debug")
+        .takes_value(true)
+        .help("Debug level"),
+    )
+		.arg(
+      clap::Arg::with_name("config")
+        .short("c")
+        .long("config")
+        .takes_value(true)
+        .help("config"),
+    )
+		.arg(
+      clap::Arg::with_name("env")
+        .short("e")
+        .long("env")
+        .takes_value(true)
+        .help("environment"),
+    )
+    .get_matches();
+
+  if let Some(dbg_lvl) = matches.value_of("debug") {
+    app_env.debug_level = dbg_lvl.to_string();
+    println!("Debug level: {}", &app_env.debug_level);
+  }
+
+  match load_app_env(app_env,verbose).await {
+    Ok(_) => {
+			if verbose > 0 {
+      	println!("Config & Environment loaded !");
+			}
+      if app_env.debug_level.as_str() == "trace" {
+        dbg!(&app_env);
+      }
+    }
+    Err(e) => {
+      if app_env.debug_level.as_str() == "trace" {
+        dbg!(&app_env);
+      }
+      eprintln!("Evironment load error: {}", AppError::NoAppEnvLoaded);
+      return Ok(());
+      // panic!("No App Env loaded");
+    }
+  };
+	let config = app_env.get_curr_websrvr_config();
+  /*
+  let mut db_appdata = DB.lock().await;
+  db_appdata.push(AppData::new(app_env.to_owned()));
+  drop(db_appdata); // End lock 
+  */
+
+//  env_logger::init();
+  if verbose > 0 {
+		println!("WebServices dist path: {}", &config.dist_path);
+		println!("WebServices Html path: {}", &config.html_path);
+	}
+  let resources_path = &config.resources_path.to_owned();
+  if verbose  > 0 {
+  	println!("Services Resources path: {}", &resources_path);
+
+		// dbg!(&app_env);
+		if app_env.has_appkey() {
+			println!("Auth App key: Loaded !");
+		}
+		if app_env.info.appmode == AppRunMode::Pro || app_env.info.appmode == AppRunMode::Premium {
+			println!("WebServices Upload path: {}", &config.upload_path);
+	//    println!("DataServices Main store: {}", &app_env.main_store);
+		}
+	}
+  async_std::fs::create_dir_all(&config.upload_path.as_str()).await?;
+  Ok(())
+}
+
+// pub async fn start_web(app_env: &mut AppEnv, fltrs: impl warp::Filter<Extract = impl warp::Reply, Error = warp::Rejection> + Clone) {
+pub async fn start_web(app_env: &mut AppEnv) -> (Zterton, SocketAddr) {
+  if env::var_os("RUST_LOG").is_none() {
+    // Set `RUST_LOG=todos=debug` to see debug logs,
+    // this only shows access logs.
+    env::set_var("RUST_LOG", "kloud=info");
+  }
+	let config = app_env.get_curr_websrvr_config();
+  let app = Zterton::new(
+    config.srv_protocol.to_owned(),
+    config.srv_host.to_owned(),
+    config.srv_port,
+  );
+  // let filter = std::env::var("RUST_LOG").unwrap_or_else(|_| "hello_world=debug,salvo=debug".to_owned());
+  // tracing_subscriber::fmt().with_env_filter(filter).with_span_events(FmtSpan::CLOSE).init();
+  // (app.to_owned(), SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), app.port.to_owned()))
+  let url = format!("{}:{}",&config.srv_host,&config.srv_port);
+  match url.to_socket_addrs() {
+    Ok(addrs_op) => if let Some(addr) = addrs_op.to_owned().next() {
+       (app.to_owned(), addr) 
+       } else {
+        (app.to_owned(), SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), app.port.to_owned()))
+       }
+    Err(e) => { 
+      eprintln!("Evironment load error: {} {}", e, AppError::NoAppEnvLoaded);
+      (app.to_owned(), SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), app.port.to_owned()))
+    }
+  }
+
+}
+