public function start():void {
		$server = new ServerInfo($_SERVER);

		$cwd = dirname($server->getDocumentRoot());
		chdir($cwd);

		$config = ConfigFactory::createForProject(
			$cwd,
			implode(DIRECTORY_SEPARATOR, [
				dirname(__DIR__),
				"config.default.ini",
			])
		);

		$input = new Input($_GET, $_POST, $_FILES);
		$cookie = new CookieHandler($_COOKIE);

		$sessionHandler = SessionSetup::attachHandler(
			$config->get("session.handler")
		);
		$sessionConfig = $config->getSection("session");
		$sessionId = $cookie[$sessionConfig["name"]];
		$sessionHandler = new Session(
			$sessionHandler,
			$sessionConfig,
			$sessionId
		);

		$databaseSettings = new Settings(
			$config->get("database.query_directory"),
			$config->get("database.driver"),
			$config->get("database.schema"),
			$config->get("database.host"),
			$config->get("database.port"),
			$config->get("database.username"),
			$config->get("database.password")
		);
		$database = new Database($databaseSettings);

		$this->protectGlobals();
		$this->attachAutoloaders(
			$server->getDocumentRoot(),
			$config->getSection("app")
		);

		$request = $this->createServerRequest(
			$server,
			$input,
			$cookie
		);

		$router = $this->createRouter(
			$request,
			$server->getDocumentRoot()
		);

		$csrfProtection = new SessionTokenStore(
			$sessionHandler->getStore(
				"gt.csrf",
			true
			)
		);
		$csrfProtection->processAndVerify(
			$input->getAll(Input::DATA_BODY)
		);

		$dispatcher = $this->createDispatcher(
			$config,
			$server,
			$input,
			$cookie,
			$sessionHandler,
			$database,
			$router,
			$csrfProtection
		);

		$response = $this->process($request, $dispatcher);
		$this->finish($response);
	}