6 ms·
Show HN: Generate styled web pages with just Python
There are a lot of Python to web app frameworks going around these days but I wanted something that was a little more lightweight that just generates HTML pages and can be embedded in Flask or other Python web servers incrementally.
PyVibe uses Python components to construct a page with styling that you can use in Flask, in a static site, or even in Pyodide.
- DaanDL 4y agoWhat problem does this solve? I mean, we have these kinds of frameworks/libraries for decades now...
- ashishsingal 4y agopeople who know python but don't know (and don't really want to know) react / html / css / js, but still want to build a simple web app. kinda like plotly dash, streamlit, pynecone, etc - except without the web server part - just generates the html.
- thedangler 4y agoThis is cool. Good work.
- zainhoda 4y agoThank you!
- Zurrrrr 4y agoThis is really really nice!
- zainhoda 4y agoThank you!
- dopidopHN 4y agoHey. I will try it in a upcoming hackathon!
- zainhoda 4y agoOh! What's the hackathon? If you're looking for teammates, I'd be down to participate depending on the project.
- keithalewis 4y agoDoing an A/B test on the Python source and the generated html I don't see much difference when I squint my eyes. Why drag Python into this?
- zainhoda 4y agoI agree for simple examples there isn't much difference but I personally find this much easier to read and write: https://github.com/pycob/pyvibe/blob/main/generator/docs/about.py https://github.com/pycob/pyvibe/blob/main/generator/docs/abo... than the output, which is this: https://github.com/pycob/pyvibe/blob/main/docs/about.html https://github.com/pycob/pyvibe/blob/main/docs/about.html It's true, I could hand code an HTML page but I never remember what meta tags to include, how to make it mobile responsive, or do things like set up a grid. I don't normally create front-ends since most of my work is in data so I'd have to look all this stuff up every time I come back to it. I think the market for this is Python developers who want to build quick front-ends to something useful that's written in Python without having to re-learn or look up the front-end stuff.
- chrispogeek 4y agoSo cool! Is there support for layouts? Edit: Aw broken link - https://www.pycob.com/components https://www.pycob.com/components Edit: Nevermind, found it - https://www.pyvibe.com/component_reference.html https://www.pyvibe.com/component_reference.html
- zainhoda 4y agoSorry about that! Where is the broken link? I can't seem to find it
- ashishsingal 4y agowhat do you mean by "layouts"?
- deleted 4y ago[deleted]
- davideg 4y agoAs someone who knows Python and always has to google CSS properties and javascript functions, this is a really sweet little project! I'm not going to reach for this if I need to have a website that needs to look a very specific way, but for cranking something out to display some data or documentation, this seems really nice.
- zainhoda 4y agoExactly! The use cases I've been hearing about are: - You're a data analyst and you did some work in a Jupyter Notebook and now you need to give it a front-end so that other people at your company can view/interact with what you've built - There's a Python library that's runnable as a command-line tool or importable but you want to give it a front-end
- hugginn 4y agoI work with data and keep having the first use case, and it's pretty common in my company. So far we're using Streamlit and Rshiny (bilingual data org). We're not really happy with Streamlit, since it's pretty easy to grow out of its pretty single minded way of working. I'll definitely be checking this out!
- ashishsingal 4y agowhat are your pain points w streamlit?
- winddude 4y agoInteresting. Cool to see python becoming more "full-stack"
- ashishsingal 4y agohehe EXACTLY. python will take over the world!
- jensenbox 4y agoThis reminds me of https://pynecone.io https://pynecone.io I would love to see these merge somehow if possible.
- ashishsingal 4y agokinda but this doesn't have a web server built in. nor does it depend on react or anything. so you can just use flask or whatever else.
- ar9av 4y agoIt's bit odd. You would want the form to be handled by Django forms system or wtforms in Flask - and having third party package to provice CSS for the classes they used (or you use on a wrapper element). And you can make reusable components with Jinja or Django templates as well.
- nurettin 4y agoI wonder what it would look like if websocket support was added. Perhaps add_* would return Sink objects which would have appropriate update methods that could be called in another thread? But that would require a page.run() function
- zainhoda 4y agoI'll give this some thought and I'll DM you on Mastodon if I can come up with a working example
- zainhoda 4y agoHere's a quick example of how Websocket components might work: https://websocket.pycob.app/ https://websocket.pycob.app/ Let me know what you think! We can discuss more on our Discord: https://discord.gg/uQWPfyP6z4 https://discord.gg/uQWPfyP6z4
- drBonkers 4y agoWhat's the difference between PyVibe and PyCob?
- zainhoda 4y agoApologies for this confusion. Pycob was my original project that included the UI components as well as a web server, user auth, cloud services, and hosting. I've decided to split the UI components from the rest of it because I've realized that they don't need to be bundled. The UI components are in a library called PyVibe. Pycob will just be Cloud Services for Python Web Apps PyVibe will be the Python -> HTML library
- Bob2077 4y agoI'm curious about the performance implications of using a Python-centric approach for creating web pages. Would the generated HTML pages be as efficient and optimized as those created with traditional web development techniques?
- shrimpx 4y agoWhat is "traditional"? In Django the web pages are generated by Python, too. In Rails by Ruby, etc.
- andrewfromx 4y agoI noticed: <script src="https://cdn.tailwindcss.com"></script> https://cdn.tailwindcss.com"></script> in the source of the homepage. Just FYI the tailwind people say that's just for dev mode and never deploy that to prod. Instead you gotta run something like: npx tailwindcss -o ../assets/css/tail.min.css --minify and then replace the script with: <link rel="stylesheet" type="text/css" href="/assets/css/tail.min.css"> "a script referred to as the Tailwind Play CDN. This script is only to be used for learning and experimenting, never for a live site." from https://www.codeinwp.com/blog/tailwind-css-tutorial/ https://www.codeinwp.com/blog/tailwind-css-tutorial/
- zainhoda 4y agoYeah, the reason for that recommendation is mostly to reduce file size. For now I don't want to have an npm dependency since this is geared towards Python developers. I'll eventually build in the tree shaking directly into the Python library.
- yule 4y agoNote that tailwind now has a standalone binary: https://tailwindcss.com/blog/standalone-cli https://tailwindcss.com/blog/standalone-cli
- andrewfromx 4y agoAh that’s great to know thank you.
- andrewfromx 4y agoI have the same problem with my project! go vs. python but yeah I hated adding the npm stuff. Let's port tailwind npx command. I'll work on the go version.
- zainhoda 4y agoI haven't tried it yet but I was planning on using this library to do most of the heavy lifting: https://pypi.org/project/treeshake/ https://pypi.org/project/treeshake/ It looks like it's calling C code via Cython so if it works, you could probably use the same underlying C code via CGo for your project.
- jasfi 4y agoI'm planning to add something like this to https://inventai.xyz https://inventai.xyz. Subscriptions aren't ready, so you can't actually generate anything yet.
- zainhoda 4y agoCool! I'd love to check it out!
- mwn 4y agoInteresting. I’ll try it out with my students. Doing HTML and CSS in a Flask app seems advanced to them. I can recommend a “deploy to PythonAnywhere” guide so users can get it online. That would require your module to be part of PythonAnywhere’s environment.
- zainhoda 4y agoWhat’s your timeline? As it happens, we’re also working on a Python hosting solution with a generous free tier.
- pbronez 4y agoDo you have any additional information to share about the hosting service? Will this be a static host, a Python-first PaaS, an education-focused REPL environment, etc?
- zainhoda 4y agoHey there! So it’ll be a Python-first PaaS focused on running data apps. So it’ll include storage for pickle files, a simple NoSQL database, identity aware proxy so you can configure specific routes as being authenticated, secrets manager, and the ability to run background jobs on a schedule (usually some sort of ETL process or model training). I go back and forth on the REPL. We built a REPL but then a lot of the beta users preferred the power of GitHub Codespaces so right now I’m thinking that no, it’ll not contain the REPL. If you have a use case, would you like to beta test the hosting?
- pbronez 4y agoOh, that could be fun. I’ll give it a spin. I’m working on a something like a structured-data first wiki. Most users will be unauthenticated read-only, served well by a static site. A smaller population will submit new data and edits. Submitted data will need some processing pipelines. I’m using Dolt/Dolthub to publish high fidelity data dumps. I’ve been leaning towards doing a static site built directly from Dolthub queries, then use an offline workflow for modifying data. However if I can bring those together easily into something more like a standard dynamic site, that would be useful. For example, I could use your native data storage for basic user profile and authentication information, like API keys for Dolthub.
- iamcreasy 4y agoInteresting. Does it dump the HTML/CSS and then someone needs to go in and add interaction?
- zainhoda 4y agoSo for now client-server interaction would be via forms. So you’d have a form, the user inputs something into the form, then that goes to the server as a query parameter. Then your endpoint would construct the appropriate response to those particular inputs. For fully client-side interactions, the components are typically bundled with some JavaScript code to make that component interactive. So for example, you can include a datagrid, which has built-in sorting and filtering capabilities by doing page.add_datagrid(df) I think if you need a lot of client-side dynamic capabilities, then that would be custom JavaScript that you’d either have to write or include a JS library from somewhere.
- akx 4y agoMmm, looks like the library doesn't do any escaping for content (and doesn't offer a way to do that either)?
- ashishsingal 4y agowhat do you mean by "escaping for content"?
- gvx 4y agoI think what they mean is that methods like add_header and add_text actually take raw HTML as an argument, which means that if you want to add arbitrary text, you actually need to do import html ... card.add_text(html.escape(my_text))
- zainhoda 4y agoThat’s correct. Perhaps I should add some documentation around this. Untrusted user input needs to be sanitized before using it in the page.
- pbronez 4y agoSeems like that should just be a warning in the docs, since mostly we’re talking about trusted code written by the dev…. Although maybe that’s untrusted from your perspective as a PaaS? What’s the escape hatch to write custom HTML in the Python source?
- ashishsingal 4y agothere's "HTML (.add_html)" in the docs - "Renders raw HTML. This is meant to be an escape hatch for when you need to render something that isn't supported by PyVibe." I'm guessing this isn't sanitized and we trust the dev. After all, they can do "eval" in Python which is much riskier than raw HTML :)
- wodenokoto 4y agoIs this a competitor to streamlit?
- ashishsingal 4y agoyes, it would be an alternative. imo it's a bit more powerful esp for multipage apps and uses more traditional web dev techniques (eg routes, etc). streamlit is tricky bc it reruns the whole script each time there's any user input. but it's also a bit more involved (eg you need to use flask or something to serve while streamlit has a webserver built in).
- xceejay 4y agoOn of the best programs for linux tbh
- chatmasta 4y agoI love new technology, and this is really cool. I don't want to derail the discussion too much, but I've noticed this trend of "making web dev easier with just Python" - e.g. htmx, pynecone, streamlit, etc. The common theme seems to be magically hiding JS from the developer. Can any python devs who use these tools explain the appeal? Do you just have an aversion to JS? And how do you reconcile that with the fact that, at the end of the day, your code is running in the browser as JS, CSS, and HTML? As soon as you need to debug something, you'll be a fish out of water. To me that sounds like a "worst of both worlds" kind of situation. Is JS really that bad?
- hkhanna 4y agoI use htmx, and I have a good amount of experience in the JS world. The main issue with JS frameworks like React is that it's painful to integrate into things like Django-rendered templates. It can definitely be done, but the tooling just isn't there yet, although it's way ahead of where it was even 5 years ago. You can go the SPA route and use something like Django Rest Framework with React, but then you need to build API endpoints for basic plumbing like authentication that often doesn't warrant an API. And you lose the use of a lot of the batteries-included features of frameworks like Django. If there were an ergonomic way to integrate React components into specific areas of the DOM tree rendered by Django templates and a sensible way to pass information into props from Django, I'd love to use a mature framework like React over things like htmx.
- robomartin 4y agoI've been away from direct work with Python + Django (P/D) for a couple of years. One of my issues with P/D has always been that deployment on anything other than one of the specialized services is an absolute pain in the ass. In the PHP world, you can get a simplest of servers from any host, upload the files and you are up and running. With P/D, well, it's a lot of work. I have developed this opinion that, while useful, Django's SQLite and runserver approach for getting up and running quickly actually is detrimental. To run a real site you have to break all of that, deal with static content, etc., etc. I could also argue that the default directory structure, while simple, it is also detrimental when moving to production. In other words, sometimes I feel it would be far better if P/D initial setup was closer to a canonical installation that could be run on any server with something as close as possible to a simple FTP file transfer (just like PHP). One can always make things more complex (multiple servers, load balancers, etc.). However, I truly believe the P/D ecosystem is seriously missing the point when not delivering a 5-minute install that actually is a basic production-ready install on any server. Have things changed at all in this regard over the last couple of years?
- macnabas 4y agoThe HTML markup in the form example is not valid. Label for attributes correspond to the input's id – not its name. I'd be really hesitant using a technology that abstracts away something as fundamental as HTML. You're putting a lot of faith and trust into a library that will make mistakes that you can't fix.
- pietz 4y agoI'm just not convinced how useful this will be. On one side you're very limited to the default style and list of available components. On the otger side you have to learn a new framework. It seems to me if you invest the time into a static web framework instead, you can design sites like this just as quickly while being able to dig deeper into html and css whenever you need to.
- drBonkers 4y agoAcknowledging my ignorance in advance— what static web frameworks do you recommend for this?
- aitchnyu 4y agoJSX, Vue, or even django templates spoiled me so this imperative Python syntax sends my eyes spinning and I cant even think about reading somebody's nested loops. Has anybody got used to this syntax for complex layouts? Or has anybody made a templating language for this?
- jollyllama 4y agoIt sounds like you're talking about Jinja? Check out the includes / extends directives. Also, look into HTMX.