Repository: HapticX/happyx (language: python)

Issue:
query string not updated in liveview example 🐛
**Describe the bug** 🐛
In liveview the query string does not update

**To Reproduce** 👨‍🔬
1. Start the testc12.nim example
2. Open http://localhost:5000/search?q=1
3. Note that it shows "You search: 1" as expected
4.  Open http://localhost:5000/search?q=2
5.  It still shows "You search: 1"

**Expected behavior** 🤔
I would expect the displayed value to change when the query parameter is changed.

**Environment**
HappyX 4.4.1
Nim 2.1.9 [Linux: amd64]
opensuse Tumbleweed
Firefox 127.0.2
query string not updated in liveview example 🐛
**Describe the bug** 🐛
In liveview the query string does not update

**To Reproduce** 👨‍🔬
1. Start the testc12.nim example
2. Open http://localhost:5000/search?q=1
3. Note that it shows "You search: 1" as expected
4.  Open http://localhost:5000/search?q=2
5.  It still shows "You search: 1"

**Expected behavior** 🤔
I would expect the displayed value to change when the query parameter is changed.

**Environment**
HappyX 4.4.1
Nim 2.1.9 [Linux: amd64]
opensuse Tumbleweed
Firefox 127.0.2


Discussion / hints:

Fix patch:
diff --git a/.github/workflows/language_bindings.yml b/.github/workflows/language_bindings.yml
index 2f187c151..eb5ae1283 100644
--- a/.github/workflows/language_bindings.yml
+++ b/.github/workflows/language_bindings.yml
@@ -80,9 +80,9 @@ jobs:
           echo "Win Module compiled with"
           echo "nim c --app:lib --out:../bindings/python/happyx/happyx.pyd -d:useRealtimeGC --mm:arc --tlsEmulation:off --passL:-static --t:-flto --l:-flto --opt:speed --threads:off -d:release -d:httpx -d:export2py happyx"
           echo "Linux amd64"
-          nim c --app:lib --out:../bindings/python/happyxpy/happyx_unix_amd64.so -d:useRealtimeGC --mm:arc -t:-flto -l:-flto --opt:speed --threads:off -d:release -d:happyxDebug -x:off -a:off -d:beast -d:export2py happyx
+          nim c --app:lib --out:../bindings/python/happyx/happyx_unix_amd64.so -d:useRealtimeGC --mm:arc -t:-flto -l:-flto --opt:speed --threads:off -d:release -d:happyxDebug -x:off -a:off -d:beast -d:export2py happyx
           echo "Linux arm64"
-          nim c --app:lib --cpu:arm64 --out:../bindings/python/happyxpy/happyx_unix_arm64.so -d:useRealtimeGC --mm:arc -t:-flto -l:-flto --opt:speed --threads:off -d:release -d:happyxDebug -x:off -a:off -d:beast -d:export2py happyx
+          nim c --app:lib --cpu:arm64 --out:../bindings/python/happyx/happyx_unix_arm64.so -d:useRealtimeGC --mm:arc -t:-flto -l:-flto --opt:speed --threads:off -d:release -d:happyxDebug -x:off -a:off -d:beast -d:export2py happyx
         shell: bash
       - name: Build Python Package 🏗
         run: |
diff --git a/README.md b/README.md
index d17b04ccf..06d6602fd 100755
--- a/README.md
+++ b/README.md
@@ -19,7 +19,7 @@
 
 [![VS Code Plugin](https://img.shields.io/badge/Plugin-1b1e2b?style=for-the-badge&logo=visualstudiocode&logoColor=f1fa8c&label=VS%20Code&labelColor=2b2e3b)](https://github.com/HapticX/hpx-vs-code)
 
-[![Python Bindings](https://img.shields.io/badge/Bindings-1b1e2b?style=for-the-badge&logo=python&logoColor=f1fa8c&label=Python&labelColor=2b2e3b)](https://pypi.org/project/happyxpy/)
+[![Python Bindings](https://img.shields.io/badge/Bindings-1b1e2b?style=for-the-badge&logo=python&logoColor=f1fa8c&label=Python&labelColor=2b2e3b)](https://pypi.org/project/happyx/)
 [![NodeJS Bindings](https://img.shields.io/badge/Bindings-1b1e2b?style=for-the-badge&logo=npm&logoColor=f1fa8c&label=NodeJS&labelColor=2b2e3b)](https://www.npmjs.com/package/happyx)
 
 </div>
@@ -53,7 +53,7 @@ HappyX is macro-oriented web framework so you mustn't write a lot of code ✨
 - Automatic translate with `-d:hpxTranslate` or `-d:translate` flags.
 - CLI tool for `creating`, `serving` and `building` your projects.
 - Hot code reloading (only for `SPA` projects as of now).
-- [Python bindings](https://pypi.org/project/happyxpy/)
+- [Python bindings](https://pypi.org/project/happyx/)
 - [NodeJS bindings](https://www.npmjs.com/package/happyx)
 
 ## Minimal Example 👩‍💻
@@ -101,7 +101,7 @@ nimble install https://github.com/HapticX/happyx
 
 ### PyPI
 ```shell
-pip install happyxpy
+pip install happyx
 ```
 
 ## Usage ▶
diff --git a/bindings/python/MANIFEST.in b/bindings/python/MANIFEST.in
index e373ebe0f..bee3b735d 100644
--- a/bindings/python/MANIFEST.in
+++ b/bindings/python/MANIFEST.in
@@ -1,3 +1,3 @@
 # MANIFEST.in
-include happyxpy/*.pyd
-include happyxpy/*.so
+include happyx/*.pyd
+include happyx/*.so
diff --git a/bindings/python/README.md b/bindings/python/README.md
index 6f539749a..d78db77aa 100644
--- a/bindings/python/README.md
+++ b/bindings/python/README.md
@@ -15,7 +15,7 @@
 
 You can install HappyX via `pypi`:
 ```bash
-pip install happyxpy
+pip install happyx
 ```
 
 ## Usage 🔌
@@ -23,7 +23,7 @@ pip install happyxpy
 ### Hello World 👋
 
 ```py
-from happyxpy import Server
+from happyx import Server
 
 
 app = Server('127.0.0.1', 5000)  # host and port are optional params
@@ -41,7 +41,7 @@ app.start()
 ### JSON/HTML/File Responses 🛠
 
 ```py
-from happyxpy import Server, JsonResponse, HtmlResponse, FileResponse
+from happyx import Server, JsonResponse, HtmlResponse, FileResponse
 
 
 app = Server()
diff --git a/bindings/python/happyxpy/__init__.py b/bindings/python/happyx/__init__.py
similarity index 99%
rename from bindings/python/happyxpy/__init__.py
rename to bindings/python/happyx/__init__.py
index ad164b886..17f0cd538 100644
--- a/bindings/python/happyxpy/__init__.py
+++ b/bindings/python/happyx/__init__.py
@@ -1,7 +1,7 @@
 from collections import defaultdict
 from enum import IntEnum
 
-from .server import Server, happyx
+from .server import HappyX, happyx
 
 try:
     from jinja2 import Template
diff --git a/bindings/python/happyxpy/constants.py b/bindings/python/happyx/constants.py
similarity index 100%
rename from bindings/python/happyxpy/constants.py
rename to bindings/python/happyx/constants.py
diff --git a/bindings/python/happyx/happyx_win.pyd b/bindings/python/happyx/happyx_win.pyd
new file mode 100644
index 000000000..f3553f834
Binary files /dev/null and b/bindings/python/happyx/happyx_win.pyd differ
diff --git a/bindings/python/happyxpy/server.py b/bindings/python/happyx/server.py
similarity index 96%
rename from bindings/python/happyxpy/server.py
rename to bindings/python/happyx/server.py
index 6237f4277..c0f1ec27c 100644
--- a/bindings/python/happyxpy/server.py
+++ b/bindings/python/happyx/server.py
@@ -1,6 +1,7 @@
 import asyncio
 import platform
-from typing import Callable, Any, List
+from threading import Thread
+from typing import Callable, Any, List, Awaitable
 from re import match
 
 from .constants import SWAGGER_HTML_SOURCE, REDOC_HTML_SOURCE
@@ -9,22 +10,23 @@
 _platform = platform.system().lower()
 
 if _platform == 'windows':
-    import happyxpy.happyx_win as happyx
+    import happyx.happyx_win as happyx
 else:
     if _cpu == 'arm':
-        import happyxpy.happyx_unix_arm as happyx
+        import happyx.happyx_unix_arm as happyx
     elif _cpu in ['arm64', 'aarch64']:
-        import happyxpy.happyx_unix_arm64 as happyx
+        import happyx.happyx_unix_arm64 as happyx
     elif _cpu in ['amd64', 'x86_64']:
-        import happyxpy.happyx_unix_amd64 as happyx
+        import happyx.happyx_unix_amd64 as happyx
     else:
-        import happyxpy.happyx_unix_amd64 as happyx
+        import happyx.happyx_unix_amd64 as happyx
 
 
 Callback = Callable[[Any], Any]
+AsyncCallback = Awaitable[Any]
 
 
-class Server:
+class HappyX:
     """
     Provides HTTP Server made with HappyX
     """
@@ -64,6 +66,7 @@ def __init__(
         self.host = host
         self.port = port
         self._server = happyx.new_server(host, port)
+        self._loop = None
         self.path = path
         # OpenAPI docs
         self._swagger_url = swagger_url
@@ -345,7 +348,7 @@ def mount(self, route: str = None, other = None) -> None:
         route {str} -- mounting path (default taken from other Server)
         other {Server} -- other server that should be mounted (default is None)
         """
-        if not isinstance(other, Server):
+        if not isinstance(other, HappyX):
             raise ValueError('mounting canceled! Other is not Server')
         if route is None:
             if other.path is None:
diff --git a/bindings/python/happyxpy/happyx_win.pyd b/bindings/python/happyxpy/happyx_win.pyd
deleted file mode 100644
index c320e2c35..000000000
Binary files a/bindings/python/happyxpy/happyx_win.pyd and /dev/null differ
diff --git a/bindings/python/setup.py b/bindings/python/setup.py
index c7d9271ed..ef50e736e 100644
--- a/bindings/python/setup.py
+++ b/bindings/python/setup.py
@@ -11,14 +11,14 @@
 
 
 if _platform == 'windows':
-    import happyxpy.happyx_win as happyx
+    import happyx.happyx_win as happyx
 else:
     if _cpu == 'arm64':
-        import happyxpy.happyx_unix_arm64 as happyx
+        import happyx.happyx_unix_arm64 as happyx
     elif _cpu in ['amd64', 'x86_64']:
-        import happyxpy.happyx_unix_amd64 as happyx
+        import happyx.happyx_unix_amd64 as happyx
     else:
-        import happyxpy.happyx_unix_amd64 as happyx
+        import happyx.happyx_unix_amd64 as happyx
 
 
 # Load readme
@@ -27,7 +27,7 @@
 
 
 setup(
-    name='happyxpy',
+    name='happyx',
     description='HappyX web framework bindings for Python 🐍',
     long_description=long_description,
     long_description_content_type='text/markdown',
@@ -40,7 +40,7 @@
     packages=find_packages(),
     include_package_data=True,
     install_requires=['jinja2'],
-    py_modules=['happyxpy'],
+    py_modules=['happyx'],
     license='MIT',
     classifiers=[
         'Development Status :: 5 - Production/Stable',
diff --git a/build_py.cmd b/build_py.cmd
index 2cfb4af17..9ed0f9aa2 100644
--- a/build_py.cmd
+++ b/build_py.cmd
@@ -3,7 +3,7 @@ cd src
 
 nim c ^
   --app:lib ^
-  --out:../bindings/python/happyxpy/happyx_win.pyd ^
+  --out:../bindings/python/happyx/happyx_win.pyd ^
   --tlsEmulation:off ^
   --mm:arc ^
   --passL:-static ^
diff --git a/build_py_debug.cmd b/build_py_debug.cmd
index c706c2596..1f00f7c2f 100644
--- a/build_py_debug.cmd
+++ b/build_py_debug.cmd
@@ -1,4 +1,4 @@
 echo "Build Python Win Bindings"
 cd src
-nim c --app:lib --out:../bindings/python/happyxpy/happyx_win.pyd -d:useRealtimeGC --mm:arc --tlsEmulation:off --passL:-static --threads:off -d:debug -d:httpx -d:export2py happyx
+nim c --app:lib --out:../bindings/python/happyx/happyx_win.pyd -d:useRealtimeGC --mm:arc --tlsEmulation:off --passL:-static --threads:off -d:debug -d:httpx -d:export2py happyx
 cd ../
diff --git a/examples/website/src/docs/introduction.nim b/examples/website/src/docs/introduction.nim
index 8364be34e..1a108890b 100644
--- a/examples/website/src/docs/introduction.nim
+++ b/examples/website/src/docs/introduction.nim
@@ -82,8 +82,8 @@ component Introduction:
           tTr:
             tTd: "PyPI"
             tTd:
-              tA(href = "https://pypi.org/project/happyxpy/"):
-                tImg(class = "h-12 lg:h-10 xl:h-8", alt = "PyPI Downloads", src = "https://img.shields.io/pypi/dm/happyxpy?style=for-the-badge")
+              tA(href = "https://pypi.org/project/happyx/"):
+                tImg(class = "h-12 lg:h-10 xl:h-8", alt = "PyPI Downloads", src = "https://img.shields.io/pypi/dm/happyx?style=for-the-badge")
           tTr:
             tTd: "npm"
             tTd:
diff --git a/examples/website/src/ui/code/python.nim b/examples/website/src/ui/code/python.nim
index 71a126079..d7825601e 100644
--- a/examples/website/src/ui/code/python.nim
+++ b/examples/website/src/ui/code/python.nim
@@ -1,5 +1,5 @@
 const
-  pythonHelloWorldExample* = """from happyxpy import Server
+  pythonHelloWorldExample* = """from happyx import Server
 
 # Create application
 app = Server('127.0.0.1', 5000)
@@ -41,7 +41,7 @@ def handle(user_id: int):
     print(user_id)
     return {'response': user_id}
 """
-  pythonCustomRouteParamType* = """from happyxpy import Server, register_route_param_type
+  pythonCustomRouteParamType* = """from happyx import Server, register_route_param_type
 
 
 app = Server()
@@ -62,7 +62,7 @@ def handle(data: MyUniqueIdentifier):
 
 app.start()
 """
-  pySsrAdvancedHelloWorld* = """from happyxpy import Server, JsonResponse, Response
+  pySsrAdvancedHelloWorld* = """from happyx import Server, JsonResponse, Response
 
 
 app = Server('127.0.0.1', 5000)
@@ -110,7 +110,7 @@ def test_all():
 
 app.start()
 """
-  pySsrAdditionalRoutes* = """from happyxpy import Server, HttpRequest
+  pySsrAdditionalRoutes* = """from happyx import Server, HttpRequest
 
 
 app = Server("127.0.0.1", 5000)
@@ -177,7 +177,7 @@ def read_users():
 
 app.start()
 """
-  pyMongoDb* = """from happyxpy import Server
+  pyMongoDb* = """from happyx import Server
 from pymongo import MongoClient
 from datetime import datetime
 
@@ -224,7 +224,7 @@ def read_users():
 
 app.start()
 """
-  pySqlalchemy* = """from happyxpy import Server
+  pySqlalchemy* = """from happyx import Server
 from sqlalchemy import create_engine, Column, Integer, DateTime
 from sqlalchemy.ext.declarative import declarative_base
 from sqlalchemy.orm import sessionmaker
@@ -280,7 +280,7 @@ def read_users():
 
 app.start()
 """
-  pySqlalchemy1* = """from happyxpy import Server
+  pySqlalchemy1* = """from happyx import Server
 from sqlalchemy import create_engine, Column, Integer, DateTime
 from sqlalchemy.ext.declarative import declarative_base
 from sqlalchemy.orm import sessionmaker
@@ -337,7 +337,7 @@ def read_users():
 app.start()
 """
   pyPostgreSql* = """import psycopg2
-from happyxpy import Server
+from happyx import Server
 from datetime import datetime
 
 # Connect to postgresql
@@ -407,7 +407,7 @@ def read_users():
 app.start()
 """
   pyPostgreSql1* = """import psycopg2
-from happyxpy import Server
+from happyx import Server
 from datetime import datetime
 
 # Connect to postgresql
@@ -473,7 +473,7 @@ def read_users():
     return response
 
 app.start()"""
-  pyMounting* = """from happyxpy import Server
+  pyMounting* = """from happyx import Server
 
 app = Server()
 profile = Server()
diff --git a/happyx.nimble b/happyx.nimble
index 60f053488..469bc9309 100755
--- a/happyx.nimble
+++ b/happyx.nimble
@@ -2,7 +2,7 @@
 
 description = "Macro-oriented asynchronous web-framework written with ♥"
 author = "HapticX"
-version = "4.4.1"
+version = "4.4.2"
 license = "MIT"
 srcDir = "src"
 installExt = @["nim"]
diff --git a/src/happyx/cli/consts.nim b/src/happyx/cli/consts.nim
index bdc94cefc..80a373df4 100644
--- a/src/happyx/cli/consts.nim
+++ b/src/happyx/cli/consts.nim
@@ -18,7 +18,7 @@ nimble install happyx@#head
 """
   readmeInstallPy* = """## Install
 ```shell
-pip install happyxpy
+pip install happyx
 ```
 """
   readmeInstallJs* = """## Install
diff --git a/src/happyx/cli/html2tag_command.nim b/src/happyx/cli/html2tag_command.nim
index c4c774163..8d8333712 100644
--- a/src/happyx/cli/html2tag_command.nim
+++ b/src/happyx/cli/html2tag_command.nim
@@ -2,7 +2,7 @@ import
   ./utils
 
 
-proc html2tagCommand*(output: string = "", args: seq[string]): int =
+proc html2tagCommand*(output: string = "", toProc: bool = false, args: seq[string]): int =
   ## Converts HTML into `buildHtml` macro
   styledEcho fgGreen, emoji["🔨"](), " Convert HTML into happyx file"
   var o = output
@@ -33,7 +33,11 @@ proc html2tagCommand*(output: string = "", args: seq[string]): int =
 
   var
     tree = parseHtml(input)
-    outputData = "import happyx\n\n\nvar html = buildHtml:\n"
+    outputData =
+      if toProc:
+        "import happyx\n\n\nproc " & args[0].replace(re2"\-(\w|\d)", "_$1") & "*(): TagRef = buildHtml:"
+      else:
+        "import happyx\n\n\nvar html = buildHtml:\n"
   xmlTree2Text(outputData, tree, 2)
 
   outputData = outputData.replace(re2"""( +)(tScript.*?:)\s+(\"{3})\s*([\s\S]+?)(\"{3})""", "$1$2 $3\n  $1$4$1$5")
diff --git a/src/happyx/cli/serve_command.nim b/src/happyx/cli/serve_command.nim
index ddd0f73de..0bfa65363 100644
--- a/src/happyx/cli/serve_command.nim
+++ b/src/happyx/cli/serve_command.nim
@@ -2,7 +2,7 @@ import
   ./utils
 
 
-proc serveCommand*(host: string = "0.0.0.0", port: int = 80): int =
+proc serveCommand*(host: string = "0.0.0.0", port: int = 80, buildDirectory: string = "build"): int =
   ## Serve SPA for production
   var
     project = compileProject()
@@ -22,17 +22,17 @@ proc serveCommand*(host: string = "0.0.0.0", port: int = 80): int =
   
   serve host, port:
     get "/":
-      let f = open(getCurrentDir() / "build" / "index.html")
+      let f = open(getCurrentDir() / buildDirectory / "index.html")
       var data = f.readAll()
       f.close()
       req.answerHtml(data)
  
     get "/{file:path}":
       var result = ""
-      let path = getCurrentDir() / "build" / file.replace('\\', '/').replace('/', DirSep)
+      let path = getCurrentDir() / buildDirectory / file.replace('\\', '/').replace('/', DirSep)
       echo "File: ", file
       echo "Path: ", path
       if fileExists(path):
         await req.answerFile(path, forceResponse = true)
   shutdownCli()
-  QuitSuccess
\ No newline at end of file
+  QuitSuccess
diff --git a/src/happyx/cli/utils.nim b/src/happyx/cli/utils.nim
index cd615a0b9..cd86700c3 100644
--- a/src/happyx/cli/utils.nim
+++ b/src/happyx/cli/utils.nim
@@ -547,11 +547,11 @@ proc xml2Text*(xml: XmlNode): string =
       result &= "("
       var attrs: seq[string] = @[]
       for key, value in xml.attrs:
-        let k = if key notin NimKeywords: key else: "`" & key & "`"
+        var k = if key notin NimKeywords: key else: "`" & key & "`"
         if value == "":
-          attrs.add(k)
+          attrs.add("\"" & k & "\"")
         else:
-          attrs.add(k & " = \"" & value & "\"")
+          attrs.add("\"" & k & "\" = \"" & value & "\"")
       result &= attrs.join(", ") & ")"
     if xml.len > 0:
       result &= ":"
diff --git a/src/happyx/core/constants.nim b/src/happyx/core/constants.nim
index f712f7eb1..acbf9f246 100755
--- a/src/happyx/core/constants.nim
+++ b/src/happyx/core/constants.nim
@@ -90,7 +90,7 @@ const
     "slot", "small", "source", "span", "strong", "style", "sub", "summary", "sup",
     "svg", "cicle", "path", "g",
     "table", "tbody", "td", "template", "textarea", "tfoot", "th", "thead", "time",
-    "title", "tr", "track", "u", "ul", "var", "video", "wbr",
+    "title", "tr", "track", "text", "u", "ul", "var", "video", "wbr",
   ]
   availableCryptoMethods = ["sha224", "sha256", "sha384", "sha512"]
   # Nim version
@@ -99,7 +99,7 @@ const
   # Framework version
   HpxMajor* = 4
   HpxMinor* = 4
-  HpxPatch* = 1
+  HpxPatch* = 2
   HpxVersion* = $HpxMajor & "." & $HpxMinor & "." & $HpxPatch
 
 
diff --git a/src/happyx/hpx.nim b/src/happyx/hpx.nim
index 4689278c9..e8b95ce22 100755
--- a/src/happyx/hpx.nim
+++ b/src/happyx/hpx.nim
@@ -22,9 +22,9 @@ import illwill except
 
 proc buildCommandAux(optSize: bool = false, no_compile: bool = false): int = buildCommand(optSize, no_compile)
 proc mainHelpMessageAux() = mainHelpMessage()
-proc html2tagCommandAux(output: string = "", args: seq[string]): int = html2tagCommand(output, args)
+proc html2tagCommandAux(output: string = "", toProc: bool = false, args: seq[string]): int = html2tagCommand(output, toProc, args)
 proc updateCommandAux(args: seq[string]): int = updateCommand(args)
-proc serveCommandAux(host: string = "0.0.0.0", port: int = 80): int = serveCommand(host, port)
+proc serveCommandAux(host: string = "0.0.0.0", port: int = 80, buildDirectory: string = "build"): int = serveCommand(host, port, buildDirectory)
 proc projectInfoCommandAux(): int = projectInfoCommand()
 proc flagsCommandAux(): int = flagsCommand()
 proc translateCsvCommandAux(filename: string, output: string = ""): int =
diff --git a/src/happyx/spa/renderer.nim b/src/happyx/spa/renderer.nim
index 06e88b2d2..ce458b704 100644
--- a/src/happyx/spa/renderer.nim
+++ b/src/happyx/spa/renderer.nim
@@ -121,7 +121,14 @@ var
   currentRoute*: cstring = "/"  ## Current route path
   scopedCycleCounter*: int = 0
 when enableLiveViews and not defined(js):
-  var liveviewRoutes* = newTable[string, proc(): TagRef]()
+  import std/httpcore
+  var liveviewRoutes* = newTable[string, proc(
+    query: StringTableRef,
+    queryArr: TableRef[string, seq[string]],
+    reqMethod: HttpMethod,
+    inCookies: StringTableRef,
+    headers: HttpHeaders
+  ): TagRef]()
   var components* = newTable[string, BaseComponent]()
 when enableDefaultComponents:
   var
@@ -202,8 +209,10 @@ else:
     componentsResult[comp.uniqCompId] = "route:" & path
   proc js*(comp: BaseComponent, script: string) =
     componentsResult[comp.uniqCompId] = "script:" & fmt"<script>{script}</script>"
-  proc rerender*(hostname, urlPath: string) =
-    requestResult[hostname] = "rerender:" & liveviewRoutes[urlPath]().children[1].ugly()
+  proc rerender*(query, queryArr, reqMethod, inCookies, headers: auto, hostname, urlPath: string) =
+    requestResult[hostname] = "rerender:" & liveviewRoutes[urlPath](
+      query, queryArr, reqMethod, inCookies, headers
+    ).children[1].ugly()
   proc bck*(hostname, urlPath: string) =
     requestResult[hostname] = "bck"
   proc frwrd*(hostname, urlPath: string) =
@@ -302,7 +311,6 @@ when defined(js):
         if vdom.childNodes[i].nodeType != NodeType.TextNode:
           diff(vdom.childNodes[i].TagRef, dom.childNodes[i])
   proc prerenderLazyProcs*(tag: TagRef) {.exportc: "prrndr".} =
-    echo tag.nodeType, ", ", tag.lazy
     if tag.lazy:
       let t = tag.lazyFunc()
       t.prerenderLazyProcs()
diff --git a/src/happyx/spa/state.nim b/src/happyx/spa/state.nim
index 8e9412389..88bf7dcb8 100644
--- a/src/happyx/spa/state.nim
+++ b/src/happyx/spa/state.nim
@@ -49,7 +49,7 @@ func remember*[T](val: T): State[T] =
   State[T](val: val)
 
 
-func watchImpl[T](state: State[T], o, n: T) =
+func watchImpl*[T](state: State[T], o, n: T) =
   for w in state.watchers:
     w(o, n)
 
@@ -68,7 +68,7 @@ else:
     if self.watchers.len > 0:
       self.watchImpl(self.val, value)
     self.val = value
-    rerender(hostname, urlPath)
+    rerender(query, queryArr, reqMethod, inCookies, headers, hostname, urlPath)
 
 
 func `$`*[T](self: State[T]): string =
@@ -136,7 +136,7 @@ else:
         self.watchImpl(before, self.val)
       else:
         `op`(self.val, other.val)
-      rerender(hostname, urlPath)
+      rerender(query, queryArr, reqMethod, inCookies, headers, hostname, urlPath)
     template `funcname`*[T](other: T, self: State[T]) =
       if self.watchers.len > 0:
         let before = self.val
@@ -144,7 +144,7 @@ else:
         self.watchImpl(before, self.val)
       else:
         `op`(self.val, other)
-      rerender(hostname, urlPath)
+      rerender(query, queryArr, reqMethod, inCookies, headers, hostname, urlPath)
     template `funcname`*[T](self: State[T], other: T) =
       if self.watchers.len > 0:
         let before = self.val
@@ -152,7 +152,7 @@ else:
         self.watchImpl(before, self.val)
       else:
         `op`(self.val, other)
-      rerender(hostname, urlPath)
+      rerender(query, queryArr, reqMethod, inCookies, headers, hostname, urlPath)
 
 
 template boolOperator(funcname, op: untyped): untyped =
@@ -338,7 +338,7 @@ else:
     if self.watchers.len > 0:
       self.watchImpl(self.val, value)
     self.val = value
-    rerender(hostname, urlPath)
+    rerender(query, queryArr, reqMethod, inCookies, headers, hostname, urlPath)
 
 
 func `[]`*[T, U](self: State[array[T, U]], idx: int): T =
diff --git a/src/happyx/spa/tag.nim b/src/happyx/spa/tag.nim
index 7189c5636..b9afeb032 100644
--- a/src/happyx/spa/tag.nim
+++ b/src/happyx/spa/tag.nim
@@ -203,7 +203,7 @@ when defined(js):
         e.setAttribute(cstring(key), cstring(val))
 
   proc newElement(name: string): TagRef {.exportc: "nwelm".} =
-    if name.toLower() in ["svg", "path", "circle", "rect", "g", "defs", "animate", "ellipse", "polygon", "mask"]:
+    if name.toLower() in SvgElements:
       result = TagRef()
       let n = cstring(name)
       {.emit: "`result` = document.createElementNS('http://www.w3.org/2000/svg', `n`)".}
diff --git a/src/happyx/ssr/liveviews/liveviews.nim b/src/happyx/ssr/liveviews/liveviews.nim
index b53505a68..61fc4f758 100644
--- a/src/happyx/ssr/liveviews/liveviews.nim
+++ b/src/happyx/ssr/liveviews/liveviews.nim
@@ -69,10 +69,20 @@ proc handleLiveViews*(body: NimNode) =
                   newCall("tDiv", newNimNode(nnkExprEqExpr).add(ident"id", newLit"scripts"))
                 ))
               ))
-            ), @[ident"TagRef"])
+            ), @[
+              ident"TagRef",
+              newIdentDefs(ident"query", ident"StringTableRef", newEmptyNode()),
+              newIdentDefs(ident"queryArr", newNimNode(nnkBracketExpr).add(ident"TableRef", ident"string", newNimNode(nnkBracketExpr).add(ident"seq", ident"string")), newEmptyNode()),
+              newIdentDefs(ident"reqMethod", ident"HttpMethod", newEmptyNode()),
+              newIdentDefs(ident"inCookies", ident"StringTableRef", newEmptyNode()),
+              newIdentDefs(ident"headers", ident"HttpHeaders", newEmptyNode()),
+            ])
           ),
         )),
-        newLetStmt(ident"_html", newCall(newNimNode(nnkBracketExpr).add(ident"liveviewRoutes", path))),
+        newLetStmt(ident"_html", newCall(
+          newNimNode(nnkBracketExpr).add(ident"liveviewRoutes", path),
+          ident"query", ident"queryArr", ident"reqMethod", ident"inCookies", ident"headers",
+        )),
         newCall("add", newNimNode(nnkBracketExpr).add(ident"_html", newLit(1)), newCall("buildHtml", newStmtList(script))),
         newNimNode(nnkReturnStmt).add(ident"_html"),
       ))


Test patch:
diff --git a/bindings/python/test1.py b/bindings/python/test1.py
index 9d82bab43..d3159b23e 100644
--- a/bindings/python/test1.py
+++ b/bindings/python/test1.py
@@ -1,12 +1,12 @@
-from happyxpy import (
+from happyx import (
     FileResponse, HtmlResponse, JsonResponse, HttpRequest, WebSocket,
-    Response, Server, reg_cors, RequestModelBase, __version__
+    Response, HappyX, reg_cors, RequestModelBase, __version__
 )
 
 
-app = Server()
-user = Server()
-sub_user = Server()
+app = HappyX()
+user = HappyX()
+sub_user = HappyX()
 
 print(app)
 
@@ -33,7 +33,7 @@ class Auth(RequestModelBase):
 
 
 @app.websocket('/ws')
-def handle_websocket_connection(ws: WebSocket):
+async def handle_websocket_connection(ws: WebSocket):
     if ws.id() == 2:
         ws.send_text("failure")
         ws.close()
@@ -47,24 +47,24 @@ def handle_websocket_connection(ws: WebSocket):
 
 
 @user.get("/id{userId?}")
-def hello_from_user(userId: int):
+async def hello_from_user(userId: int):
     return f"Hello, {userId} user!"
 
 
 @user.route('/', ['get', 'post'])
-def handle():
+async def handle():
     return "You'll see it only on GET or POST"
 
 
 @user.post("/messages[u]")
-def get_messages(req: HttpRequest, u: User):
+async def get_messages(req: HttpRequest, u: User):
     print(u)
     print(u.first_name, u.identifier)
     return u.to_dict()
 
 
 @sub_user.get("/")
-def test():
+async def test():
     return "hi"
 
 
@@ -75,14 +75,14 @@ def test():
 
 
 @app.get("/")
-def read_root(req: HttpRequest) -> dict:
+async def read_root(req: HttpRequest) -> dict:
     print(req)
     print(req.path())
     return {"Hello": "World"}
 
 
 @app.get("/calc/$i/$j")
-def read_root(i: int, j: int):
+async def read_root(i: int, j: int):
     print("i + j is", i + j)
     return JsonResponse(
         {"hello": "world"},
@@ -91,7 +91,7 @@ def read_root(i: int, j: int):
 
 
 @app.get("/hello_world")
-def read_root(req: HttpRequest, required: bool, optional = 5):
+async def read_root(req: HttpRequest, required: bool, optional = 5):
     """
     # Hello, world!
     Responds **Hello, world!**
@@ -106,7 +106,7 @@ def read_root(req: HttpRequest, required: bool, optional = 5):
 
 
 @app.notfound
-def on_not_found():
+async def on_not_found():
     return HtmlResponse(
         "<h1>Oops! Not found!</h1>",
         headers = {
@@ -116,11 +116,11 @@ def on_not_found():
 
 
 @app.middleware
-def on_not_found(req: HttpRequest):
+async def on_not_found(req: HttpRequest):
     # print(f"Middleware handled path at [{req.http_method()}]:", req.path())
     # print(f"Middleware detect these headers: {req.headers()}")
     # print(f"Middleware detect this body: {req.body()}")
     pass
 
 
-app.start()
+app.run()
diff --git a/bindings/python/test2.py b/bindings/python/test2.py
index 77fd573f7..d6575a83f 100644
--- a/bindings/python/test2.py
+++ b/bindings/python/test2.py
@@ -1,4 +1,4 @@
-from happyxpy import new_server, register_route_param_type
+from happyx import new_server, register_route_param_type
 
 
 app = new_server("127.0.0.1", 5000)
diff --git a/tests/testjs18.nim b/tests/testjs18.nim
index 63c40710e..7353c2844 100644
--- a/tests/testjs18.nim
+++ b/tests/testjs18.nim
@@ -73,6 +73,18 @@ var testCounter = remember 0
 testCounter.watch(old, new):
   echo "set testCounter from ", old, " to ", new
 
+let A = buildHtml:
+  tSvg(viewBox="0 0 240 80"):
+    ttText(x="35",y="20", style="fill: black;"): "A: Anyone Here?"
+
+let B = buildHtml:
+  tSvg(viewBox="0 0 240 80"):
+    tText(x="35",y="20", style="fill: black;"): "B: Anyone Here?"
+
+let C = buildHtml:
+  tSvg(viewBox="0 0 240 80"):
+    text(x="35",y="20", style= "fill: black;"): "C: Anyone Here?"
+
 
 appRoutes("app"):
   "/":
@@ -86,6 +98,12 @@ appRoutes("app"):
     for i in 1..5:
       tDiv:{$htmlTags[0]}
       FormatTagHtml(htmlTags[1])
+    {$A}
+    {A}
+    {$B}
+    {B}
+    {$C}
+    {C}
   "/issues/304":
     "in a div"
     tDiv: