url metadata field unequivocally treated as the canon feed url when calculating hashes, or are they ignored if they're not at least proper urls? do you just tolerate it if they're impersonating someone else's feed, or pointing to something that isn't even a feed at all?
@alexonit@twtxt.alessandrocutolo.it prologic has me sold on the idea of hashv2 being served alongside a text fragment, eg. (#abcdefghijkl https://example.com/tw.txt#:~:text=2025-10-01T10:28:00Z), because it can be simply hacked in to clients currently on hashv1 and provides an off-ramp to location-based addressing (though i still think the format should be changed to smth like #<abc... http://example.com/...> so it’s cleaner once we finally drop hashes)
@zvava@twtxt.net Ah okay. Yeah, so far, yarn looks pretty nice and is easy to use. I might even selfhost my own instance too!
url metadata field unequivocally treated as the canon feed url when calculating hashes, or are they ignored if they're not at least proper urls? do you just tolerate it if they're impersonating someone else's feed, or pointing to something that isn't even a feed at all?
@zvava@twtxt.net That was my greatest concern with how it is currently handled, I’m afraid to break threads even by fixing a typo.
Handling it via the pod might work but I think it’s not the best approach, external feeds and clients don’t usually use a pod api but their own implementation, so any workaround won’t work there.
That’s why my proposals addressed those issues:
- the idea of using a “key” instead of the
url(with the url as a fallback), the key could even be a public key so it can be used verifieable in crypto functions
- using the timestamp to prevent content changes to break threads (plus being simpler to implement)
- using an explicit thread reference with an alternative subject format (like
[#THREAD_ID] Hello worldand replies with(#REPLY_ID) Ahoy) so the content can change without affecting the thread reference, and anyone can use their own schemes freely
@rnlog@yarn.girlonthemoon.xyz bbycll, whenever it is ready, in the meantime you’re already on a pretty good one :3
@zvava@twtxt.net I just have plastic plants at home too.
@zvava@twtxt.net Don’t say that.
The eye candy is always good to have.
@zvava@twtxt.net I’m not sure, I could just set up a cors-anywhere via docker in a minute and it would work the same.
Still, I could write one with just a dozen lines of Go or Node.js, I might consider writing one after the client is working decently.
@zvava@twtxt.net What is a nice twtxt client to use?
@alexonit@twtxt.alessandrocutolo.it terrariums are so cool but i couldn’t even keep grass from the back yard in a jar alive
@alexonit@twtxt.alessandrocutolo.it yeah, i didn’t even consider this as an option lol, though if it works it works! will you be writing a compatible proxy for self-hosting separate from the custom backend you were thinking of? :o
@lyse@lyse.isobeef.org I can suggest you a trick to do a “cold” welding.
Using a copper wire or a similarly malleable material, pass it through a drilled hole, hammer it on one end until flat, then do the same on the other side.
It does the same job of a rivet but it’s flatter and look nicer on both sides, it’s of course weaker but still strong enough for small objects.
It’s sometimes used to reduce risk of deformities due to heat in hand-crafted jewelry and to reduce costs of small tools.
@zvava@twtxt.net CORS is our worst enemy. 🥷
I too had the same issue being a browser-based request, so the only solution is using a proxy.
For testing (and real personal use) I rely on this one https://corsproxy.io/.
In my client, I first check if the source allows me to fetch it without issues first and fallback to prefixing with a proxy if it gives an error.
For security reasons the client don’t give you a readable error for CORS, so you must use a catch-all for that, if it fails again with the proxy you can deal with any other errors it throws as you normally would (preferably outside of the fetch function).
After the fetching responded, I store the response.url value to fetch it again for updates without having to do extra calls (you can store it verbatim or as a flag to be able to change the proxy later).
Here an extract of my code:
export async function fetchWithProxy(url, proxy=null) {
return await fetch(url).catch(err => {
if (!proxy) throw err;
return fetch(`${proxy}${encodeURIComponent(url)}`);
});
}
// Using it with
const res = await fetchWithProxy('https://twtxt.net/user/zvava/twtxt.txt', 'https://corsproxy.io/?');
// Get the working url (direct or through proxy)
const fetchingURL = res.url;
// Get the twtxt feed content (or handle errors)
const text = await res.text();
I also plan to allow the user to define a custom proxy field, I like the solution used by Delta.chat in their android app, where you can define the URL format with a variable https://my-proxy?$TWTXT_URL since it allows you to define with more freedom any proxy without a prefix format.
If the idea of using a third-party proxy is not to the user liking they can use a self-hosted solution like cors-anywhere or build their own (with twtxt it should just be a GET).
@lyse@lyse.isobeef.org Yeah, those are my bad.
A couple of weeks ago, I added CORS support, which is the source of the OPTIONS call. What I didn’t do was store the result so it stops trying to make further attempts. I’ll get that in tomorrow.
As for the “If-Modified-Since” header, the server-based component of TwtStrm should be sending that (along with its user-agent tag and my user info). I wasn’t sure if that could be sent with CORS requests, so I’ll need to look into that a bit more.
Thanks, I appreciate the feedback!
@movq@www.uninformativ.de Same 👌
@alexonit@twtxt.alessandrocutolo.it i tried making a webapp initially but i didn’t even get into the initial stages of testing because no one sets the Access-Control-Allow-Origin header, so i just jumped into building a backend instead. did you find away around this limitation? :o
@lyse@lyse.isobeef.org Just as planned! 😅
@itsericwoodward@itsericwoodward.com (I confess, my brain pronounced it as “TwitStorm”. 😂)
Thank you, @alexonit@twtxt.alessandrocutolo.it! It’s not sealed at all. If you were pouring in a liquid, it would run out on all four corners. It’s just folded over and carefully hammered shut as best as possible. 03 is a bit blurred, but you can see the tab from the right (the short side) tucking in on the left (the long side). The hem on top clamps it in place fairly decently.
I decided against blind rivets, because they leave ugly looking and sharp backsides, which can also interfer with the contents of the box. However, they would be an easy solution to make the corners more rigid and prevent any movement from the short sides.
Unfortunately, I can’t weld or solder, so that’s not an option. It would be the by far best solution. I wanna learn it one day, though.
Yes, Ken is a really great dude. He’s the reason I gave this a shot in the first place. :-)
@itsericwoodward@itsericwoodward.com No worries, all good, mate! We all have to start somewhere. Other software requests my feed several orders of magnitude more often.
I can confirm, the User-Agent header appears to be fixed. \o/
Two other things I noticed, though:
There’s now an
OPTIONSrequest for my feed coming from something that claims to be Firefox, pointing to your feed URL in the query. No clue what this is about. In any case, it’s rejected with a405 Method Not Allowed.Not that these few requests bother me at all, but you might wanna implement caching next with either the
If-Modified-SinceorIf-None-Matchrequest headers. This way, if the feed hasn’t changed, the web server can reply with a304 Not Modifiedand no body at all, saving unnecessary traffic. But again, this is really not an issue for me at all. I just wanted to make sure you’re aware of it, that’s all. It might be even already on your agenda. Or you might decide to never do anything about it, which is also fine for me. :-)
@prologic@twtxt.net That zs looks pretty cool! I love simple static site generators, and look forward to trying it on my next web site project. Kudos!
@bender@twtxt.net Yes! What you’re seeing in the demo is just demoing the routes file and redirects, etc/. Pathing more.
User-Agent header. Instead of the URL, the nick is repeated.
@lyse@lyse.isobeef.org Thanks, I think I fixed it now. Sorry for the spam.
@bender@twtxt.net Yes and no.
To build a compliant PWA you need to provide a webmanifest json and a service worker.
Those requirements are not directly part of this project.
You can build the client as a standalone PWA or even as a widget inside an existing page.
The general steps are closer to how you would include a third-party library in an existing project, by importing it as a dependency and using it in your website.
I’m pretty sure most users would expect a PWA (me included) so I plan to provide a ready-made template ready to be deployed as is.
@alexonit@twtxt.alessandrocutolo.it so, a PWA, right?
@prologic@twtxt.net ready, set, goooooooo!
@lyse@lyse.isobeef.org Beautiful handwork, how did you seal the corners? I don’t see and hole or anything.
BTW, That Sheet Metal Dude is something else himself, skilled enough to teach others, can work properly with self-imposed contraints, care about safety and is humble enough to be wiling to learn from others, a true craftman worthy of respect.
@movq@www.uninformativ.de Yeah I was gonna say 😅 The problem isn’t that bad 🤣 But still we should fix this soon™ 🔜
@prologic@twtxt.net I checked a while a ago and there were, like, 3-5 collisions or something like that. Not that many. 🤷 I have to specifically look for them – I don’t notice it in normal operation.
@movq@www.uninformativ.de You were seeing that mayn hash collisions for you to notice this? 😱
@bender@twtxt.net I’ve made several improvements today, tightened up the line height and density of the text plus a few other nice things too! I think I’m ready to start migrating my blog over to this 😅
@bender@twtxt.net I agree ! I reckon the line height could be a bit smaller 👌
@prologic@twtxt.net it is looking good! On mobile, I find that the line height is too large for my liking, and that text takes too much space. I would like it a bit more dense. But that’s just my taste.
I haven’t checked in desktop; I try not to touch desktop on weekends. 😂
groff --version)?
@movq@www.uninformativ.de It’s an ancient 1.22.4. :-)
@lyse@lyse.isobeef.org Thanks!
The way I have it setup right now would take me more work to integrate with your script though.
I’m keeping things dumb on purpose, I just have to finish my client to have all the cool buttons that do it for me.
@prologic@twtxt.net I too, self-host various services on a VPS (and considering buying a mini PC to keep at home instead).
I use most of it as a hosting platform for personal use only and as a remote development environment (I do share a couple of tools with a friend though).
But given the costant risks of DDoS, hacking, bots, etc. I keep any of my public facing resources purely static and on separate hosting providers (without lock-ins of course).
Lately, I began using homebrew PWAs with CouchDB as a sync database, this way I get a fantastic local-first experience and also have total control of my data, that also sync in a locally hosted backup instance in real-time.
Also, I was already aware of Salty.im, but what I’m thinking is a more feature complete solution that even my family can use quickly, Delta.chat with the new chatmail provider (self-hostable) might be the solution for my needs.
But I’m still thinking if it’s worth the trouble. I might just drop everything and only use safe channels to speak with them (free 24/7 family tech-support is easy to manage 😆).
Also, I’ll be waiting for the day you’ll share with us your story, I’m pretty curious about it!
@prologic@twtxt.net I think nobody will stop you if you replace the current hashing with SHA-256 if you call it improvement™ 😉
@lyse@lyse.isobeef.org That looks like an older bug report. Which groff version is that (groff --version)?
@lyse@lyse.isobeef.org Very cool! 😎
@movq@www.uninformativ.de I got an empty line through the table, similarly to one of the linked bug reports, just at a different location:
https://lyse.isobeef.org/tmp/screenshot-2025-09-27-13-56-13.png
@bender@twtxt.net @movq@www.uninformativ.de Thank you! Not sure what I end up putting in there, but I’m sure I will find some tools to go in. :-)
Yes, this was a flat piece of sheet metal. It went together like a cardboard box, just much slower and with timbers clamped down to get a straight folding line. I don’t have a sheet metal brake, so I just carefully hammered the piece bit by bit. Like in this video by the Sheet Metal Dude: https://www.youtube.com/watch?v=WYgEfWEMXk0
@prologic@twtxt.net No, this is a Linux manpage from the man-pages project: https://git.kernel.org/pub/scm/docs/man-pages/man-pages.git/tree/man/man7/ascii.7
I do have an idea what’s going on. Could be an unfortunate interaction between the table preprocessor tbl and the man macro package. 🤔
@movq@www.uninformativ.de Is this for your own OS? 🤔
@lyse@lyse.isobeef.org Not bad. 🤔 So this started out as a flat sheet and then you cut and folded it, like paper (more or less)?
@lyse@lyse.isobeef.org very nice! What’s the intended usage?
@movq@www.uninformativ.de You didn’t miss anything. Just time for more useful stuff. ;-)
@bender@twtxt.net Shh yes 🤣 this is the problem with politics 😆 by that definition; I’m not conservative 🤣
@prologic@twtxt.net well, multiculturalism, immigration, and race (to mention a few, there is more) are key points on conservative’s agendas. That’s why I asked what you thought of it. You haven’t replied yet. Of course, no answer is an answer, right?
@bender@twtxt.net Yes but I guess what I’m saying is; “so what about it?” Aren’t most places in the world these days “multicultural” to some degree or another? 🤔