Hyvor Relay (https://github.com/hyvor/relay) can be self-hosted. We are planning a cloud version for 2026. (I am a co-founder)
HN user
supz_k
We are also looking to migrate off Cloudflare. I thought Bunny.net was mostly a pure CDN, not a reverse proxy like Cloudflare. Am I wrong? One of the most important things for us would be DDoS protection.
Self Plug-in: We are currently beta testing Hyvor Relay [0], a self-hosted alternative for sending emails. We are focusing more on observability (monitoring DKIM/SPF, periodically querying DNSBLs) and DNS automation.
A simple docker compose up can get a reasonably working setup [1]
[0]https://github.com/hyvor/relay [1]https://relay.hyvor.com/hosting/deploy-easy
We are working on an open-source, self-hosted solution [0] to make this easier. When you correctly set up DKIM, SPF, reverse/forward DNS for IPs, it is not much hard to get emails delivered. IPs can still get blacklisted and you need to monitor blacklists and contact them if it happens. Solutions like Postfix are great, but they lack observability. In our solution, we have developed dashboards and health checks to make it easier to find problems with the set up.
We are currently running beta tests (really appreciate it if you can join).
For the past two months, I have been working on Hyvor Relay [1], an open-source, self-hosted alternative to AWS SES, Mailgun. It's been an awesome ride learning SMTP and DNS in depth. And, we're pretty close to a beta release.
We did this [0] as a 3-devs startup, and it was one of the best things we ever did!
For us, we found ourselves repeating again and again when we had multiple UI projects. It became boring and we decided to write the design system. It took us about 3-4 months to complete this.
- It takes a LOT of effort to migrate old projects. A LOT! So, make sure you really have the time and effort for a migration like that.
- In my opinion, it only makes sense to have a component library if you have multiple different projects / repos.
- Try not to reinvent the wheel. Design your components library, but follow a pattern of a popular library so you can see "hey if you have used this library, it's the same here. Just the UI is different"
- Write an extensive documentation with examples (here's ours: [1])
- In our case, integrating dark mode, docs, and i18n into the design system (in an opinionated way) saved us a lot of time.
[0] https://github.com/hyvor/design [1] https://hyvor-design.pages.dev
Slightly off-topic: Until last week, we used Redis for Laravel queues and cache in our blogging platform. We decided to get rid of Redis and use the database. The reason was that we are planning to allow self-hosting of our software so removing a dependency is a huge win to reduce complexity (didn't know about the license change then). There are a lot of arguments against using a relational DB for queues, but from our testing, it just worked! So, we just went with it in production. Surprisingly, there are no noticeable performance issues so far.
We initially used Redis because, well, Laravel recommends it. But, what I learned is that Redis is not a requirement until you absolutely need it.
This is cool! I recently worked on integrating something like this into our blogging platform [0] to help bloggers monitor their links automatically. One main problem is with popular websites which have pretty aggressive bot prevention mechanisms. They often return 5xx codes even in HEAD requests. How do you combat that?
We recently re-indexed comments to Meilisearch (a PHP process that synced data from MYSQL to Meilisearch) after a Meilisearch version upgrade. It only took about 1 hour for about 12 million documents on a 16GB/4vCPU. In your case, maybe it was a config issue? Or, an old version?
So, first thing, I have this inner monologue talking to me everytime. I have to first shut it up. This happens when I'm very relaxed and don't think about anything. Then, I slowly focus on the visuals I see (which is nothing). Then, suddenly some shapes come and go, and I try to keep them in my head as much as I can. To influence a flow of visuals, I look at a light and close my eyes. You see the afterimage of the light (which is a "eye" thing, not a "mind" thing). However, this has helped to start seeing some stuff in the mind, even though it takes 10-20 minutes of focus (and mentally exhausting!)
Also, this subreddit has many information and anecdotal experience on this technique: https://www.reddit.com/r/CureAphantasia/
I have seen some shapes and a few colors for now. Most importantly, I have started to see vivid dreams in the last few days, which has never happened before (before that it was just a feeling not a visual. However, my father suggested this might just be that I have learned to remember dreams more by becoming more conscious about it, which is a possibility). It's too soon to judge. So, I'll keep doing it for a couple more weeks to see if it can help me see visuals rather than random flashes.
I have the same thing and never knew until HN's discussion last week: https://news.ycombinator.com/item?id=37718999
The article mentions Image Streaming, which I've been practising since. Interestingly, it seems to work! I've have been seeing vivid dreams, and have been able to randomly visualize shapes. Nothing to prove it "cures" aphantasia, but we'll see :)
Never thought about it that way. Just wondering what is the percentage of crypto used for criminal activities? I guess it won't be easy to thing to measure?
"At first glance, this might seem like a step back — perhaps even un-Svelte-like. Isn't it better if let count is reactive by default? Well, no. The reality is that as applications grow in complexity, figuring out which values are reactive and which aren't can get tricky. And the heuristic only works for let declarations at the top level of a component, which can cause confusion. Having code behave one way inside .svelte files and another inside .js can make it hard to refactor code, for example if you need to turn something into a store so that you can use it in multiple places."
This is absolutely true. I have been confused many times figuring out what are reactive states and what are not.
I never knew Svelte needs changes like this, but seeing this, it sounds like a good plan.
Just a personal experience. About 6 months ago, we moved from NGINX to Caddy on our web app, which handled about 300 million HTTP requests per month at that time (2 web servers, so about 150 million each)
CPU Usage:
with NGINX - 15-20% with Caddy - 70-80%
I tried multiple tweaks but nothing helped to get NGINX-level performance. So, after a few weeks, we migrated back to NGINX.
That being said, I still absolutely love Caddy and use it in a few small scale apps.
- The DX it provides is amazing. - Creating a PHP-FPM reverse proxy is just a couple of lines. - Generating SSL certificates on the server is a breeze. With NGINX, you have to mess with other software like certbot. - It just works :)
Not sure if I understood the questions.
In both iframes and Web Components, a Javascript code (Preact in our case) rendered the comments element, there is no much difference.
Maybe we are not on the same page?
Hey! Great question.
The installation code has two parts:
<script> that registers the element <hyvor-talk-comments> element in the place user needs to load comments
The script is hosted in our servers so we can push updates anytime we want.
I hope that makes sense? (Our installation guide: https://talk.hyvor.com/docs/install)
Shameless plug: I've been working on Hyvor Blogs (https://blogs.hyvor.com), a blogging platform with multi-language support, custom themes, in-built SEO, custom domain, AI translations, and options to self-serve the blog from your Laravel/Symfony/NextJS apps. It's been very interesting (and not so easy) so far to work on a very competitive market.
Give https://blogs.hyvor.com a try. It supports multi-languages by default. (I'm the founder)
Here are some enjoyable technical experiences we had / decisions we made while developing Hyvor Blogs...
Tech Stack
Our other product, Hyvor Talk [http://talk.hyvor.com], handles more than 30 million users and 500 million requests each month for a considerably low hosting cost using monolith architecture. So, it was a no-brainer to use the same technologies:
PHP and Laravel for the backend MYSQL for the primary database Meilisearch [https://meilisearch.com] for the search index Redis for cache
PHP isn’t dead. It definitely has some weirdness introduced in older versions that cannot be removed due to backward compatibility promises. However, recent versions of PHP have improved performance and developer experience significantly. Also, we use strict types and PHPStan [https://phpstan.org] (max level) to ensure type safety. And, we try to have 95%+ coverage using Pest PHP [https://pestphp.com]. With those tools, writing PHP is fun. Laravel saves a lot of time by abstracting away many HTTP, queue, and CLI-related tasks. MYSQL is the single source of truth. We sync data to Meilisearch for search. Laravel Scout makes syncing effortless. Redis is used for caching and queues.
More details on the open-source software we use are available here: [https://blogs.hyvor.com/docs/oss]
Theme Development:
In Hyvor Blogs, all themes are fully customizable. We wanted to make the theme development process as friendly as possible for developers. Being a hosted software, this is quite hard. Developers aren’t fond of (including me) editing a file on the browser to make something work. Providing an online web editor to create themes wasn’t an option. So, we created a simple CLI tool [https://github.com/hyvor/hyvor-blogs-cli] that developers can install locally via NPM. This CLI tool listens for file changes and syncs all theme files to a development blog in our production system. So, developers can make changes in their local editor and see changes with almost no delay. This has worked pretty well so far!
Theme Structure:
We wanted to keep the theme structure simple. No Javascript frameworks - just plain old-school HTML because it works the best with search engines, minimizes the data transfer required between the server and the browser, and even provides a better experience for end users.
We obviously needed a templating language to render HTML from data. There were many options like Handlebars, Liquid, and Twig. All do the job. We went with Twig because its original package is written in PHP and managed by the Symfony team so we could trust it and easily integrate it into our system.
Another thing we cared about a lot is creating standardized theme guidelines. For example, if you take WordPress themes, most themes have their own structure and are very different from each other. This adds a learning curve to each theme. To prevent that, we created standardized theme guidelines for all published themes to follow. We also standardized how common things in blogs like color theme switching, searching, language switching, etc. work. This helps users switch between and customize their themes effortlessly.
Then, there is one important thing we realized. “The structure of a blog is very simple”. First, you might think you need several stylesheets, jQuery, bootstrap, etc. NO! Just one stylesheet and barely some vanilla javascript for interactive elements like search. Realizing this helped us further improve theme performance. In our themes, the developer writes several SCSS files inside the /styles directory. This makes it easier for them to manage styles in chunks. Then, we convert all SCSS files into a single styles.css when loading it in the blog. That way, only 1 HTTP request is needed for styles - it’s super fast!
You can see more about theme development here: [https://blogs.hyvor.com/docs/themes-overview]
All official themes are free and open-source. [https://github.com/hyvor/hyvor-blogs-themes]
We have ported multiple open-source themes, and now working on a couple of original themes as well.
Caching:
We incrementally cache content using “first-request caching”. If you visit a post in the blog, the response is dynamically created and cached. Subsequent responses are served from the cache until the blogger updates the post.
This is highly efficient and scalable. Also, there is no building step involved as in Netlify or similar static hosting platforms. You can immediately see changes but also benefit from caching.
The cache is saved on a Redis server in our data centers, but we may try CDN edge caching in the future.
Multi-language support:
Multi-language support is probably the most unique selling point of Hyvor Blogs. The first version of Hyvor Blogs did not have a multi-language feature. Adding that feature took a lot of careful thought and effort, but it was totally worth it. I can safely say there’s no other hosted blogging platform that makes managing multiple languages as easy as Hyvor Blogs does.
First, we had to figure out what data was translatable. For example, post content, description, etc. Then instead of saving that data in the `posts` table, we created a new `post_variants` table to save them linked to a specific `language_id`. The blogger can create multiple languages and each entity (`post` , `tag` , `user`) can have variants for each language.
Additionally, we integrated DeepL [https://deep.com] to let bloggers automatically translate posts into many languages.
Data API filtering:
Our Data API [https://blogs.hyvor.com/docs/api-data] returns public data of the blog. This is also internally used in themes to fetch additional data. If you think about filtering data (ex: posts), one may want to filter `published_at < {time}` while another wants `published_at > {time}`. If we went with the normal API approach, we’d need many query parameters like `published_at_greater_than`, `published_at_less_than`, etc. That’s ineffective. So, we wrote a little query language called FilterQ to take a single `filter` input parameter and safely convert it to the `WHERE` part of the SQL query. With it, you can call the API with `filter=published_at>{time}` param. And, it’s even possible to use `and` / `or` and grouping for complex filtering.
Library (implemented in Laravel): https://github.com/hyvor/laravel-filterq
Sub-directory hosting:
We designed a new way to host a blog in a subdirectory of a web application. Let’s say you have a Laravel application at example.com. We created Delivery API [https://blogs.hyvor.com/docs/api-delivery] to help you host your blog at example.com/blog.
This API tells you how to deliver a response for a request (hence “Delivery” API). For example, when your Laravel app receives a request to /blog/hello-world, your app calls the Delivery API to learn how to respond to “/hello-world”. The Delivery API returns a JSON with all the data needed. Your app will then use that JSON response to create an HTTP response and send back the response to the client. It will also save the response in the cache so that it doesn’t have to call the Delivery API next time for the same path.
This is quite similar to a reverse proxy with caching, but the JSON API makes it easier to use it in web applications as we do not need HTTP parsing logic.
This is also similar to how our “first-request” caching works, but this time this caching happens inside your web application. To clear the cache, we use webhooks.
For now, we have developed libraries for Laravel and Symfony for sub-directory hosting, with plans to cover more frameworks in the future.
Rich Editor
This was probably the hardest part of all. We spent months testing many frameworks like Draft.js, Prosemirror, and even pre-built rich editors like TinyMCE. We wanted customizability and also ease-of-use. No framework checked all boxes.
We decided to go with ProseMirror [https://prosemirror.net]. It was complex but eventually, we came to understand the power of it. It has a steep learning curve, but it’s totally worth it. We actually enjoy writing Prosemirror plugins now to add some functionality to the Rich Editor. Also, recently the author added typescript support, which incredibly improved the experience. We created many nodes like Blockquotes, Callouts (with emoji), Images with captions, Embeds, and Bookmarks pretty easily after that. ProseMirror has quite good browser support as well.
Flashload
I’ve been a fan of InstantClick [http://instantclick.io/]. We wanted to add something similar to all blogs to add a “fake-fast” effect. If you haven’t used InstantClick before, it is a simple library that turns separate HTML pages into a single-page app. It starts loading content on the mouseoever event of a link and replaces the <body> when clicked on it. This makes navigation super fast. We created an almost copy of Instantclick named Flashload [https://github.com/hyvor/flashload] with additional configurations and optimized caching. Feel free to use it in your projects :)
Overall, it’s been a great learning experience working on Hyvor Blogs. We’d love to know what HN thinks about our project. I am happy to answer any questions you might have.
Yes, I have also noticed that Shiki is slower. We use it in our blogging platform for code block highlighting and posts with code blocks are noticeably slower to save than posts without them.
Are there any alternatives that supports VS Code syntax but faster?
I yesterday migrated our Laravel project from Laravel Mix (which uses webpack) to Vite (https://laravel.com/docs/9.x/vite), and couldn't be more happier.
Earlier, webpack took 3-4 seconds to re-bundle on file changes when running npm run watch (It is a quite large typescript + react project). In Vite, it is less than 300ms. And, React Hot-Reloading is awesome.
Are those changes real? I don't see any network requests/WebSocket connections.
Great stuff.
Off topic, any pgDash alternatives for MYSQL?
Disclose: I'm a founder of a commenting system
I have worked with bloggers and news sites over the last 2 years, and are some things I have learned:
* Comments give a better sense of the your audience. Take Youtube for example. When you see comments in a video, you know what kind of audience that channel has, and what the audience like. Same for blogs. * Comments give new visitors an idea how good/bad your blog post is. For example, take a programming tutorial. When there are comments about the article, you can make a better decision whether you should use the code examples in your application. Don't forget that stackoverflow is built on user comments. People are not going to search the article you shared on Twitter to find out comments. (If you only share on Twitter/HN, make sure to link the Twitter/HN discussion at the bottom, like Cloudflare blog does) * Comments let you build your own audience, which you own. Just think, what happens when Twitter bans you?
However,
* When new bloggers do not get comments from their audience, they become discouraged. I have seen people really excited about starting their new blog and adding our commenting system, and they just say after a few weeks, they just remove comments from their blog because they don't get comments. The fact is that getting comments on your blog is harder than getting a comment on social media. The obvious reason is that the user has to "signup".
Okay, so what if make commenting easier? For example, just with username. So, we make commenting public. It works fine until you are flooded with spam comments. Tools like Akismet do a good job on detecting spam. The real problem comes when people start to publish non-spam but not-so-good comments on your blog. This is when you need moderating... manual moderating. It requires time.
Finally, to answer your question: Are blog comments a thing of the past? It is a decision of the blogger. Some like to have public discussions, but some like to have it in Twitter DMs or emails. Some don't care about moderating but some do. From my experience, most news sites I worked with REALLY care about their commenting section, and they invest a lot in software and moderation teams to have nice, engaging conversations on their websites.
We handle 50-60 million monthly page views (comments embed requests) in our commenting system using PHP/Laravel, NGINX (2 load balanced servers), Redis (for queues and caching), and MYSQL.
All performance issues we have ever encountered were always related to the database - never had an issue with PHP or Laravel.
However, we use Node.js for websockets. Though there are some improvements in PHP for event-driven development (like ReactPHP [1]), it was quite hard to find proper documentation and help to build a production-ready WebSocket server. So, we ended up using Node.js for that.
The new features added to PHP in the latest versions are great. Type hinting and return types are really helpful in writing better code. I hope there will be an addition to type hint advanced data structures (ex: Arrays of Objects) in a future version.
Thanks this looks promising.
Tried. Good. Being used to Sumatra feels like missing the organising of documents, and features like "Sign" are really distracting.
One of the pains of moving from windows to a Mac was not having Sumatra. I've been using it on Windows for so long. I have tried many options on Mac, but they just doesn't feel "right" (too many options in viewers like Acrobat, too less features compared to Sumatra in others). Any plans to create a mac version?
Yep, commento is a great self-hosted alternative.
There's also Isso[1] and utterances[2] (Github issues based)
[1] https://posativ.org/isso/ [2] - https://github.com/utterance/utterances
Thanks for the all resources. I'm mainly looking for a mathematics-based approach. "How to solve it" looks promising. Thanks.