@javivf@adn.org.es Oh, I like the looks of that.
GTD was undoubtedly the best developed task-management system I ever got into (and I tried a bunch in my time), but even it wound up being too much work for me to keep up with. An app like that might streamline it enough to make it usable. Thanks for the link!
I’m truly in love with Mindwtr, I hope I can keep my self in the GTD loop again :)
@david@daiwei.me if you have some weekend home type place, with no Internet, getting TV through an antenna and a DVBT box, my recommendation is to just buy some old Dell monitor with HDMI to 3.5mm audio output built in, so you can connect speakers to it.
Doesn’t have to be Dell, but you can often just buy one of those from your employer, for under $25 here.
Were this sadly makes much less sense, in with Internet TV services. Those usually need a dedicated TV app to function and while that can be replaced with a $200 TV box, that some providers force you to rent, thus making you pay more for your Internet TV forever - this also means giving up the “archive app”, that gives you access to all the on demand content, included in the price of your mandatory TV license. None of these overpriced boxes come with it, as they’d mauch rather make you pay, for yet another subscription service instead.
So yes, you can kinda do it with an Internet TV too, assuming you trust the expensive box to not spy on you, but in that case you’re mostly just paying a whole lot more, for a lot less, than you would be, with the LG TV.
Also a “Publish who I follow” toggle: writes # follow = + # following = N into your feed like yarnd does. Off by default (it is your social graph 🤔), and only on the GitHub/Gitea backends for now where the app owns the feed file. twtd next 🤞
@GabesArcade@gabesarcade.com I think it would have to be specific to the App itself. So say you somehow didn’t save a recovery key or some shit™ You could still get back up and running with ease if you had exported a config? 🤔
Okay I’m fixing this in lextwt, yarnd and twtxt.app (takes a different path). Soon you’ll be able to write shit™ like (<this>) and it’ll get escaped and rendered correctly on the page. Basically you are really writing HTML here, but not intending to do so, Twtxt never supported HTML, and I don’t think it ever should. We extended the format to support basic Markdown, and I think that’s where it should end.
Probably time we wrote a Spec for this really.
@david@daiwei.me I see it now. Is this also a problem in the app too? Or just yarnd or both?
@movq@www.uninformativ.de You know you could in theory use the Twtxt App and the Twtxt Feeds service as your “news reader” right? 😅
Are you aware of the Residential Proxy pest?
https://spur.us/blog/smart-tv-apps-residential-proxy-sdks
This explains the access patterns that I see in my logs.
It’s funny, because I used to warn years ago that this might happen, and then I lost track of this topic. Now here we are and it’s a real issue. 🤦♀️
@aelaraji@aelaraji.com oh good was that the in app nudge?
Does this seem right to you so far @david@daiwei.me ? 🤔
2026/07/18 02:55:52 sync-reaper: observe-only pass — 1145 namespaces, 3 anchored, 1089 undatable, 0 idle candidate(s), 0 reaped
So far only 3 users of the Twtxt App have achieved their device settings with a recovery key? 🔑
📣 ACTION REQUIRED: Hey folks 👋 For those of you whom are using the Twtxt App either via the Hosted option or on your own twtd instnace or via Github/Gitea or any other publishing backend (doesn’t amtter). Please read.
Please open the app and you should be prompted to save your recovery code for your device. This basically is all of your settings, follows, etc in the app itself. This is synced to the Origin everytime you make a change, and also stored on-device. This is what makes it possible to sync your setting across services, move to another device, etc.
Please save a copy of the recovery code somewhere. This is only your only way to recover your settings.
Thank you 🙏
To retest: reload the app, reconnect Codeberg/Gitea with the same token, fill in the new Owner field (dce), repo twtxt, and Feed URL https://hashnix.club/~dce/twtxt.txt. Publish to Codeberg, serve from Hashnix — exactly what you wanted 🤞 lemme know!
@prologic@twtxt.net That’s more-or-less it. If I could do it without Codeberg (just using SCP, SSHFS, or something similar), that would be even better, but probably out-of-scope for the project.
My thinking behind how twtxt.app worked was that I could give it access to a repo, in order to add to my twtxt.txt, but that the alternative feed URL would then be presented to other users instead of the Codeberg URL; unless, of course, this is already part of the twtxt metadata.
In short, the feed URL would just be a dummy.
@dce@hashnix.club So let me get this straight… You want to store your feed on a Codeberg repo right? But you want to clone that repo down somewhere else to serve it on a different location. Right? And you’d like to use the Twtxt App (https://twtxt.app) to front all of this? Right?
@prologic@twtxt.net I created a repo called twtxt and an application key with read/write access to it (and only it). I then cloned the repo on Hashnix and hardlinked my twtxt into it, before committing and pushing. Next, I supplied the appropriate details on twtxt.app, under Codeberg/Gitea, and clicked “Connect”. gitea https://codeberg.org/api/v1/user: 403 Forbidden.
@prologic@twtxt.net I was actually trying to use twtxt.app, with Codeberg as a backend, but I kept getting a 403 error. As for twtd, well, my twtxt is hosted on a pubnix. The people behind Hashnix are really nice, but I’d rather not bother them with software requests if there’s a simpler solution, and I imagine it would be rude of me to run a deamon from my homedir without permission. Could be worth asking, though, unless I decide to write a client myself.
@dce@hashnix.club You may also be interested in the Twtxt App and the little tiny twtd publishing backend? 🤔
based on this, it’s entirely possible that there may still be a subtle bug somewhere with the app
I don’t think I’m going to add edit and delete support in this app because I think it was a horrible mistake to add those features to a client 🤣
twtpub.com is just the default instance tho — it’s a multi-tenant twtd, AGPLv3. Run your own and I’ll list it in the app’s picker so folks choose where to land 🤗 keeps it decentralised + spreads the load. Docs → https://git.mills.io/yarnsocial/twtd
New in the Twtxt App 🥳 a Hosted feed backend — claim a nick, one tap, no account, no server, nothing to run. Your feed lives at https://twtpub.com/u/yournick and you’re posting from the app straight away 🎉
Some further ideas/enhancements for Twtxt App …
- On the “Followers” tab, new followers should appear at the top I thnik.
- On the Following/Followers, each feed should be clickable/tappable.
- Maybe also tidy it up a bit, displaying the full raw Feed URI is messy.
@david@daiwei.me I agree, the App (https://twtxt.app) really does work quite nicely 👌
Hurray, I can now press gg instead of g to go to the top in tt. Much better! :-) Other multi-key combinations are also easily possible now.
I should probably write a real article about this at some point, but here we go. The only downside with my new key binding system is that it breaks tview’s established pattern. You’ve got an InputHandler(), that is implemented using WrapInputHandler(…). It typically then directly implements the switching logic depending on the key press. Something like this:
func (w *Widget) InputHandler() func(event *tcell.EventKey, setFocus func(p tview.Primitive)) {
// WrapInputHandler allows for intercepting key events with SetInputCapture(…)
// from the outside for customization. This handles the default key bindings.
return t.WrapInputHandler(func(event *tcell.EventKey, setFocus func(p tview.Primitive)) {
switch event.Key() {
case tcell.KeyRune:
if event.Modifiers() == tcell.ModNone {
switch event.Rune() {
case 'k':
w.scrollUp()
return // we already handled the event, stop processing
case 'j':
w.scrollDown()
return
}
}
}
// We didn't handle the key event. Maybe the parent
// widget knows what to do with it.
if handler := w.parent.InputHandler(); handler != nil {
handler(event, setFocus)
}
})
}
From the outside, you can intercept and either stop or continue the widget’s original key handling with a potentially rewritten key event using SetInputCapture(…):
w := NewWidget()
// customized or additional key bindings
w.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
switch event.Key() {
case tcell.KeyUp:
// Rewrite the event, so the "cursor up" key is an alias
// for the vim key binding "k", that is handled by the
// wrapped input handler above. (I know, I know, this is a
// completely unrealistic example, why would anyone use
// cursor keys when there are vim key bindings available?!)
return tcell.NewEventKey(tcell.KeyRune, 'k', tcell.ModNone)
case tcell.KeyRune:
if event.Modifiers() == tcell.ModNone {
switch event.Rune() {
case 'q':
app.Stop()
// we already handled the event, do not pass it
// to the wrapped input handler above
return nil
case 'r':
toggleMessageReadStatus()
return nil
}
}
}
// we didn't handle the event, pass it to the wrapped
// input handler above
return event
}
Since they all expect a single key, I’ve noticed that using multiple dedicated KeyBindings of mine on these different levels kinda breaks multi-key handling with common prefixes. The outer-most KeyBinding captures the prefix, but it can’t transfer it to the inner one if not handled by the outer one. At least not without some more (potentially ugly) changes. So, I now have to work with just a single KeyBindings object for the entire widget chain (if it consists of multiple other widgets or the regular input handler and input capture are in the game). The outside needs to register all its key bind customizations or extensions at the same level that the original widget handles its default ones. Doable by exposing the widget’s KeyBindings instance, but not pretty. You always have to keep this in mind.
With the KeyBindings, it will look like that:
type Widget struct {
parent tview.Primitive
// make it available to children or the outside either by
// direct field access or by providing a getter method
KeyBindings *bind.KeyBindings
}
func NewWidget() *Widget {
w := &Widget{KeyBindings: &bind.KeyBindings{}}
w.KeyBindings. // default key bindings
Bind0(bind.KeySequence('k', w.scrollUp).
Bind0(bind.KeySequence('j', w.scrollDown)
return w
}
func (w *Widget) InputHandler() InputHandler() func(event *tcell.EventKey, setFocus func(p tview.Primitive)) {
return t.WrapInputHandler(func(event *tcell.EventKey, setFocus func(p tview.Primitive)) {
// also note the missing support for focus transfer at the moment
event = w.KeyBindings.Capture(event)
if event == nil {
return
}
if handler := w.parent.InputHandler(); handler != nil {
handler(event, setFocus)
}
}
}
And then from the outside, or in a child widget:
w := NewWidget()
w.KeyBindings. // additional or customized key bindings
Bind1(bind.KeySequence(tcell.KeyUp), func(*tcell.EventKey) *tcell.EventKey {
return tcell.NewEventKey(tcell.KeyRune, 'k', tcell.ModNone)
}).
Bind0(bind.KeySequence('q'), app.Stop).
Bind0(bind.KeySequence('r'), toggleMessageReadStatus)
When directly working with tview primitives that are not part of custom widget implementations, the following works well so far:
textView := tview.NewTextView().
SetWordWrap(true).
SetText("…")
SetScrollable(true)
textView.SetInputCapture((&bind.KeyBindings{}).
Bind0(bind.KeySequence('q'), app.Stop).
Bind1(bind.KeySequence('g', 'g'), func(*tcell.EventKey) *tcell.EventKey {
return tcell.NewEventKey(tcell.KeyHome, 0, tcell.ModNone)
}).
Capture)
I need to sleep on this some more.
Also, writing very long messages like this one is really not all that fun in tt’s editor. I should absolutely provide a way to shell out to vim.
(Took me about one and a half hours to compose, holy crap. But not only because of not using vim. Although, that might have saved me a quarter hour or so for sure. Proof-reading this message also uncovered quite a few bugs in my real documentation. So, that’s a big win!) Good night!
Yeah this is my fault sorry! In this case i’ve axtually found yarns to be soex non-compliant 😱 Twtxt.app is doing yhe right thing🤣 As is Jammy 👌
@-mentions), unread dots, Back keeps your spot, and it'll now guide you to install it as a proper app 📱 Reload https://twtxt.app and have a play! Thanks @quark and @balloon-fu-sen for all the reports 🙏
Self-hosting twtd? Pull prologic/twtd:latest too — the Avatar URL field in the app now actually writes # avatar = into your feed (needed changes on both sides)
Shipped a bunch of Twtxt App fixes & polish today 🥳 One-tap Refresh that actually refreshes, duplicate follows fixed, Reply/Fork buttons (with proper @-mentions), unread dots, Back keeps your spot, and it’ll now guide you to install it as a proper app 📱 Reload https://twtxt.app and have a play! Thanks @quark@ferengi.one and @balloon-fu-sen@tw.fus.f5.si for all the reports 🙏
@balloon-fu-sen@tw.fus.f5.si Fixed! 🥳 The Avatar URL field now actually gets written to your feed’s # avatar = metadata. Turned out it needed changes in both the app and twtd itself — so you’ll want to update your twtd instance once the new build lands. Thanks for the report! 🙏
@prologic@twtxt.net I really like how these two apps pair-up. Seeing as I’m still tweaking TwtKpr, I’m considering adding support for the same APIs as twtd (so maybe it can be used as another backend for Twtxt.App). 🤔
@prologic@twtxt.net Le Me! both twtd and twtxt.app 👌
@balloonfu-sen@yarn.girlonthemoon.xyz I could in toehry publish a specification for what twtd implements, which forms the basis of the API between twtxt.app <-> twtd, if you wanted to write your own twtd / twtxt.app compatible publishing backend (assuming you didn’t want to use Github/Gitea, etc).
👍 definitely using the Twtxt App as my daily-driver now for Twtxt/Yarn. Not using twtd however, as I just pair the app with my already existing yarnd powered profile on twtxt.net
So… Quick count. Hands up those who are using the Twtxt App? 🤔 – And who’s also pairing this with the twtd publishing backend?
Looks like twtxt.app on mobile emits +00:00 UTC timestamps instead of Z – Yarnd should handle both, but doesn’t 🤦♂️ On the list 🤞
@bender@twtxt.net @david@daiwei.me Good debugging session 👌 Sounds like the root cause is twtxt.app on mobile — +00:00 timestamps and quoted mentions. I’ll dig into Yarnd’s side of that 🧐
@bender@twtxt.net Yeah, Yarnd’s mention parser is pretty naive — if twtxt.app wraps the mention in quotes it probably strips them wrong. Worth fixing 🤔
@david@daiwei.me bender variable in. First thing I see on Yarnd is that my mention is broken. It was entered between quotes on twtxt.app. Yarnd has always had parsing problems, so I am not blaming twtxt.app this time.
@movq@www.uninformativ.de this is what I see on twtxt.app (all looks good there, though, but not here, on Yarnd):

@movq@www.uninformativ.de hmm, I see the same on twtxt.app, and Yarnd. On twtxt.app:

On yarnd:

I’m starting to use the twtxt.app as my daily driver now as opposed to yarnd and my pod twtxt.met 🥳
Fixed the broken hashes in the Twtxt App (https://twtxt.app) 🥳 It was hashing your twts with a client-side timestamp the server never used 🤦♂️ Now it keeps the canonical created/hash the pod (or twtd) returns, and the GitHub/Gitea backends write a # url = preamble so every client hashes your feed the same way. Thanks @fastidious@tilde.town for the report 🙏
2027-07-07T18:05:37+00:00 but is always showing up as having been just posted now on twtd 🤔
@itsericwoodward@itsericwoodward.com good catch! I don’t think that was possibly done by twtxt.app, so the issue I had open on it on @aelaraji@aelaraji.com’s behalf is being closed. Thanks!
@aelaraji@aelaraji.com do not use twtxt.app yet. It has issues that @prologic@twtxt.net will fix soon.
@prologic@twtxt.net I linked you some of my findings on the twtxt.app on IRC. The main problem is the hashing. Totally broken. But you have got to give it some thought, because GitHub hosting of the feed is tricky (even more so if they are CNAMEing their domain to it). It is also finicky because Pages is auto-enabled on username.github.io, so actions must run each time you twt.
And if we can compile a list and file issues for feeds, twtxt.app and anything else as issues for when i get back 🙏 feature requests, bug reports. etc 🤞
Anyone using XMPP? I’ve been hearing a lot about how it is the OG messaging protocol. That G00gle Talk used to use it as a back-end, that FB messanger and w_hatsapp use some modified version of it or something; And that setting up a server (or even using a public one) would be a better alternative to the aforementioned apps, so I did. Now the question is: “Where the Fu__ are my video calls at!!? 🤣” … The protocol supports videoconferencing and I’m yet to find a decent Desktop/Mobile client that implements it. I wish I knew enough Code-Fu to contribute/help implement some, somewhere.
@bender@twtxt.net Haha! Thanks. The broken avatar was a Me and my Hotlinking policy problem, It should be fixed by now. And I Freaking love the twtxt.app by the way. Cheers!
@aelaraji@aelaraji.com wow, look who the cat dragged in! 😂 I was thinking about you just yesterday, when testing the twtxt.app, and seeing your avatar photo broken. And today, here you are! Nice to “see” you mate!
FYi 👋 I’m aware of an optimist precomputed hashing bug on the new twtxt.app 🤯 Trying to work with @bender@twtxt.net remotely on my vacation yo fix it 🤣