Intro to PYJSX
Debajyati Dey

Debajyati Dey @ddebajyati

About: Web Developer, Freelance Technical Writer, always eager to learn new technologies

Location:
West Bengal, India
Joined:
Feb 25, 2024

Intro to PYJSX

Publish Date: Jul 13
33 20

Did you know that you can write JSX in python code?

Yes, I am not kidding! It is actually possible today!

You may have found jinja templates ugly and absolutely nightmare for templating in django or flask. If that's so, you are really going to enjoy this quick tutorial.

In this article, I am going to show you an interesting approach to component driven frontend development in python using a new library which is called pyjsx.

So, let's get started!

Get Started

Set up the Virtual Environment

First things first. Let's quickly set up a venv to install the required library.

python3 -m venv .venv
Enter fullscreen mode Exit fullscreen mode

and activate it -

In Linux/MacOS -

source .venv/bin/activate # for POSIX Shells
Enter fullscreen mode Exit fullscreen mode

In Windows -

./.venv/Scripts/activate.bat REM for windows cmd
Enter fullscreen mode Exit fullscreen mode
./.venv/Scripts/activate.ps1 # for powershell
Enter fullscreen mode Exit fullscreen mode

Install the Library

pyjsx logo

.venv/bin/pip3 install python-jsx # (for POSIX Shells)
Enter fullscreen mode Exit fullscreen mode
.\.venv\Scripts\pip3.exe install python-jsx # (for windows)
Enter fullscreen mode Exit fullscreen mode

If you use mypy then set up the ini file (mypy.ini) for accurate type checking.

[mypy]
plugins = pyjsx.mypy
Enter fullscreen mode Exit fullscreen mode

Now we are ready to dive in.

Note: I am not going to install flask or quart or hypercorn or any other dedicated backend framework or http server library, for this simple pyjsx demonstration.

We will use the http.server module from the standard library of python for setting up the web server.

Let's Write some Python JSX (PYJSX)

Just exactly how you write functional components and pass props to them in React you do it the same way in pyjsx.

for example, you would write a header component this way -

# coding: jsx
from pyjsx import jsx, JSX

def Header(style, children) -> JSX:
    return <h1 style={style}>{children}</h1>
Enter fullscreen mode Exit fullscreen mode

The most important things here to know and be careful about are -

  1. The comment # coding: jsx is REQUIRED. It is not a plain regular comment but a directive that tells Python to let our library parse the file first.
  2. The components can't be defined in a regular python file. You are only allowed to import the components in a python file, from the parsed files that contain the component definition(s). This component filename must end with .px file extension.
  3. The import from pyjsx import jsx is vital because PyJSX transpiles JSX into jsx(...) calls so it must be in scope.

Let's define some components

Make sure you put the file extension as .px NOT .py.

The <Header/> component -

# coding: jsx
from pyjsx import jsx, JSX

def Header(style, children) -> JSX:
    return <h1 style={style}>{children}</h1>
Enter fullscreen mode Exit fullscreen mode

The <Main/> component -

# coding: jsx
from pyjsx import jsx, JSX

def Main(children) -> JSX:
    return <main>{children}</main>
Enter fullscreen mode Exit fullscreen mode

And here is the <App/> component.

# coding: jsx
from pyjsx import jsx, JSX
from main import Main
from header import Header

def App() -> JSX:
    return (
        <div>
            <Header style={{"color": "darkgreen"}}>Hello from PYJSX!</Header>
            <Main>
                <p style={{"color": "crimson"}}>This was rendered with PyJSX!</p>
            </Main>
        </div>
    )
Enter fullscreen mode Exit fullscreen mode

Now, Here comes the part of server. We will set up a pretty simple http server to serve the <App/> component on GET request.

Hey, hey, hey, before writing a runnable file, remember this -

❗❗ To run a file containing JSX, the jsx codec must be registered first in the runtime, which can only be done with from pyjsx import auto_setup.
⚠️ This must occur before importing px files or any other file containing JSX.

Setting Up the server

Import modules -

from http.server import BaseHTTPRequestHandler, HTTPServer
from pyjsx import auto_setup # MUST import this before importing JSX
from app import App
Enter fullscreen mode Exit fullscreen mode

Define constants -

HOST = '127.0.0.1'
PORT = 8080
Enter fullscreen mode Exit fullscreen mode

Define the HTTP request handler class to setup server

class MyHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        self.send_response(200)

        # Send response headers
        self.send_header('Content-type', 'text/html')
        self.end_headers()

        # using fstring to convert the JSX into string
        response = f"{App()}"
        # convert the string data into bytes before sending over network
        self.wfile.write(response.encode())

    def log_message(self, format, *args):
        return  # Suppress default logging for clean output

def run_server():
    server = HTTPServer((HOST, PORT), MyHandler)
    print(f"Serving HTTP on {HOST}:{PORT} ...")
    try:
        server.serve_forever()
    except KeyboardInterrupt:
        print("\nShutting down the server.")
        server.server_close()
Enter fullscreen mode Exit fullscreen mode

Now let's run the server to see it in action (I mean browser).

Running the server through console

Look, our server works perfectly fine, and the pyjsx code is beautifully rendered in the DOM!
Rendered in browser

Look at the browser console -
elements in the browser console

Wrapping it up

You must be delighted to know that pyjsx also supports fragment components <></> and nested expressions like -

<div>
    {[<p>Row: {i}</p> for i in range(10)]}
</div>
Enter fullscreen mode Exit fullscreen mode

already.

So, we see that pyjsx has a lot of potential.

It is a new library, and I think it is not ready for production yet. But it is completely open source with Apache Licence, so with valuable community contributions we can make development of this library progress rapidly and see it as a huge leap forward towards declarative web ui development in python.

What do you think, want to give it a go?

Check it out in GitHub and explore more examples to build something awesome with it!

GitHub logo tomasr8 / pyjsx

Write JSX directly in Python

PyJSX - Write JSX directly in Python

PyPI - Version

from pyjsx import jsx, JSX

def Header(style, children) -> JSX:
    return <h1 style={style}>{children}</h1>

def Main(children) -> JSX:
    return <main>{children}</main>

def App() -> JSX:
    return (
        <div>
            <Header style={{"color": "red"}}>Hello, world!</Header>
            <Main>
                <p>This was rendered with PyJSX!</p>
            </Main>
        </div>
    )
Enter fullscreen mode Exit fullscreen mode

Installation

Get it via pip:

pip install python-jsx
Enter fullscreen mode Exit fullscreen mode

Minimal example (using the coding directive)

Tip

There are more examples available in the examples folder.

There are two supported ways to seamlessly integrate JSX into your codebase One…

Conclusion

I would really appreciate your feedback on this tutorial. How would you rate it? How can I improve it?

If you found this project or tutorial helpful, please consider sharing some love to the article. It will encourage me to create more content like this.

If you found this POST helpful, if this blog added some value to your time and energy, please support by sharing it with your developer friends.

Thanking you for Reading!

Follow me for more quality tech content. 👇🏽👇🏽👇🏽

Feel free to connect with me at - Twitter, LinkedIn or GitHub :)

Happy Coding 🧑🏽‍💻👩🏽‍💻! Have a nice day ahead! 🚀

Comments 20 total

  • Subhradip Sinha
    Subhradip SinhaJul 14, 2025

    Insightful

  • K Om Senapati
    K Om Senapati Jul 14, 2025

    Wow its so cool

    But is it better than Jinja2 ?
    That can be setup easily with fastapi or flask

    • Debajyati Dey
      Debajyati DeyJul 14, 2025

      Well actually Jinja really serves its purpose greatly. That being said, it is a templating engine for python.

      Jinja is generally static, (HTML rendered before delivery). While JSX is dynamic and is loved by devs mostly for its component-based reusability, nesting and the ability of easily passing props for dynamic behavior.

      The best way is to use the best of both worlds. 

      As in the end, we are converting PyJSX into strings currently for rendering as html, we will be able to use them directly in flask routes. What we can do is break our whole UI into reusable components and then serve them as html when sending via response in flask routes.

      A Quick Example for you if my explanation above was messy (sorry 🥲😅😅🥲) -

      PyJSX with Flask

      With PyJSX, you define your components in Python files (often with a .px extension, though not strictly required for simple cases if transpiled correctly). The output of a PyJSX component is of JSX type which can be formatted in fstrings, which Flask can directly return.

      First, define a PyJSX component. You would typically save this in a file, for example, component.px -

      # coding: jsx
      from pyjsx import jsx, JSX
      
      def HomePage(user_name, items) -> JSX:
          list_items = [<li>{item}</li> for item in items]
          return (
              <>
                  <h1>PyJSX Home Page</h1>
                  <p>Welcome, {user_name} from PyJSX!</p>
                  <p>Here are your items:</p>
                  <ul>{list_items}</ul>
              </>
          )
      
      Enter fullscreen mode Exit fullscreen mode

      Then, in your Flask application (app.py), you would import and use these components:

      from flask import Flask
      from pyjsx import auto_setup
      from component import HomePage
      
      app = Flask(__name__)
      
      @app.route('/')
      def home_pyjsx():
          # Render the PyJSX component to a string
          rendered_html = HomePage(user_name="KOmSenpati", items=["Pen", "Paper", "Laptop"])
          print(rendered_html)
          return f'{rendered_html}', {'Content-Type': 'text/html'}
      
      if __name__ == '__main__':
          app.run()
      
      Enter fullscreen mode Exit fullscreen mode

      See it works perfectly fine -

      Running the flask server

  • Lisa Butler
    Lisa ButlerJul 14, 2025

    Amazon job offer (USA only)
    work from home tasks.
    (Daily payment) No prior experience needed Get paid to complete.
    Simple Amazon–related tasks..

  • Parthib Mukherjee
    Parthib MukherjeeJul 14, 2025

    such a great blog. keep it up

  • Syed Muhammad Ali Raza
    Syed Muhammad Ali RazaJul 15, 2025

    Insightful

    • Debajyati Dey
      Debajyati DeyJul 15, 2025

      Thanks for letting me know. Now build something cool with it

  • Okoro chimezie bright
    Okoro chimezie brightJul 15, 2025

    Cool thanks for sharing

    • Debajyati Dey
      Debajyati DeyJul 15, 2025

      You're welcome 🤗. Glad you found it useful 😁.

  • Parag Nandy Roy
    Parag Nandy RoyJul 16, 2025

    That’s seriously cool ..

  • G. Mete Ertürk
    G. Mete ErtürkJul 16, 2025

    • Debajyati Dey
      Debajyati DeyJul 16, 2025

      Why, do you hate python?

      • G. Mete Ertürk
        G. Mete ErtürkJul 16, 2025

        No, I am even fine with people breaking established industry standards, I get it, it is fun. I just don't like it when people take the joke too seriously and actually start using these in production. Look what happened to React. They invent a new "solution" to the mess they helped create every year, and each solution requires two new inventions.

        If you hold your ear from the other side so often that your arms get entangled, you should just let go.

        • Debajyati Dey
          Debajyati DeyJul 17, 2025

          Wow. insightful!

          And the HeadWind HTML is super awesome man!! Lol!

  • fonbless mtohbless
    fonbless mtohblessJul 18, 2025

    Interesting..

    • Debajyati Dey
      Debajyati DeyJul 18, 2025

      Thanks now try it out and let me how it goes

  • steve
    steveJul 19, 2025

    I've recently been using python for devops automation with aws. Its faster than using bash aws cli (though bash is still essential for provisioning ec2 setup, along with Docker). Its twice as fast as using nodejs for file automation. What it sucks on is type integration. Even with pydantic, flake8 and black formatter, typescript is three times faster and intellisense is fast. Python has its place but in comparison to nodejs, vite, react is all over it. I don't even have to worry about indentation.

    Conclusion:
    Jsx for python is like trying to write semantic html in an svg text tag. Pardon my English - Crap.

Add comment