Full Width [alt+shift+f] Shortcuts [alt+shift+k]
Sign Up [alt+shift+s] Log In [alt+shift+l]
1

Album Listening in Album Whale

from Good Enough [alt+shift+b] in technology

Back in March we added Album Search in Album Whale. This was a very nice update because it meant you no longer had to first grab an album share link from a music service (e.g. Spotify, Apple Music, Bandcamp, etc) in order to save an album to a list. You can just head straight to Album Whale and do it all there. Today we’ve added another feature to Album Whale with a similar goal in mind, this time on the other end of the spectrum: now you can listen to an album right in Album Whale! No more needing to jump over to a music service first to do so. Hover over any album artwork and you’ll find a green ▶︎ play button, which opens a dialog containing music service embeds for that album, like this: While amazing for discovering new music quickly, I’ve also found it very useful for my own To Try list. Now this entire flow can happen within Album Whale after hearing of a new album I want to listen to at some point: Add it to my To Try list in Album Whale using search Listen to it right in Album Whale If I like it, copy it to another list in Album Whale (oh ya, this is another small feature we added!) A couple more notes: For albums added to Album Whale using a Bandcamp share link, those green play buttons just link back to Bandcamp. At least for Spotify, I found I needed to be logged into Spotify on the web to have their embeds in Album Whale play the whole album, not just a preview. This might also be true for other music services. We hope you discover many great new tunes this summer! Listen on Album Whale Reply by email
4th Aug 2026

Stay updated

Get a weekly newsletter with the top 5 articles worth reading every week.

More from Good Enough

TIL: Detaching Action Text Images

A Pika author was editing the same post in two browsers. They added six images in Browser A, then later they referenced an old tab editing the post in Browser B. That copy of the editor did not include those images. Browser B saved and removed all six images from Active Storage. A short time later, Browser A saved its newer copy of the post and put the image references back, but at that point the originally uploaded files were gone due to Browser B saving the post without the images. This exposed two separate problems: Missing images produced uncached 404 responses that the editor requested repeatedly. Action Text purged an image as soon as one save removed it from the body. Here’s how we fixed those problems. Why Action Text deleted the images Action Text keeps a rich text record’s embeds synchronized with the attachments in its body. When a submitted body no longer contains an image, Action Text removes its ActiveStorage::Attachment. Active Storage then purges the dependent blob, deleting both its database record and its file. That behavior makes sense when there is only one current copy of a document. It is unsafe when the same post can be open in multiple tabs, browsers, or devices. One stale save can delete an image that another editor is still using. Why the missing images flooded the server Browser A still had the six images in its editor, each pointing at an Active Storage redirect URL: /rails/active_storage/blobs/redirect/:signed_id/:filename Pika uses the ProseMirror-based Rhino editor. Rhino rebuilt an image’s DOM node when its caption or selection changed. Each new <img> element requested its URL again. Healthy images did not cause trouble since Active Storage makes its redirect cacheable. For a purged blob, Rails returned a 404 without Cache-Control, so the browser kept sending the request to Rails instead of reusing the failure. In a gallery, typing could re-request several missing images per keystroke. In these scenarios, this issue led to hundreds of requests hitting our servers. Fix 1: Cache permanent Active Storage 404s A purged blob’s redirect URL can never start working again. Blob IDs are not reused, and uploading the image again creates a new blob with a new signed URL. Sinc there is no concern of a 404 becoming stale, we made a specific 404 cacheable for the same period as a successful redirect: # app/controllers/concerns/active_storage_missing_blob_cache.rb module ActiveStorageMissingBlobCache extend ActiveSupport::Concern included do rescue_from ActiveRecord::RecordNotFound, with: :render_cacheable_not_found end private def render_cacheable_not_found expires_in ActiveStorage.service_urls_expire_in render file: Rails.public_path.join("404.html"), layout: false, status: :not_found end end We included the concern only in the controller serving these blob redirects: # config/initializers/active_storage_missing_blob_cache.rb Rails.application.config.to_prepare do ActiveStorage::Blobs::RedirectController.include(ActiveStorageMissingBlobCache) end (We also offered an update to Rhino that avoids it being so aggressive re-requesting images.) Fix 2: Detach dropped images instead of purging them When a save removes an image from an Action Text body, we now remove the attachment while temporarily keeping its blob. Another browser can save the image again and reattach that same blob. If nothing brings it back, a cleanup job purges it later. First, we added a timestamp for when the image was dropped: class AddDetachedAtToActiveStorageBlobs < ActiveRecord::Migration[8.1] def change add_column :active_storage_blobs, :detached_at, :datetime end end We then intercepted the private callback Active Storage uses to purge a dependent blob: # config/initializers/detach_dropped_embeds.rb module DetachDroppedEmbeds private def purge_dependent_blob if dropped_from_rich_text? blob&.update_columns(detached_at: Time.now) else super end end def dropped_from_rich_text? record.is_a?(ActionText::RichText) && !destroyed_by_association end end ActiveSupport.on_load(:active_storage_attachment) do prepend DetachDroppedEmbeds end The destroyed_by_association check preserves intentional deletion. Removing an image from a saved body detaches it, but deleting the post and its rich text still purges its images normally. Purge detached blobs after a grace period The cleanup query considers both when the blob was created and when it was detached: ActiveSupport.on_load(:active_storage_blob) do scope :unattached_since, ->(time) { unattached.where( created_at: ..time, detached_at: [nil, ..time] ) } end That scope handles both kinds of unattached blobs: A new upload that has never been attached becomes eligible based on created_at. An image removed from an old post becomes eligible based on detached_at. Pika gives both a 30-day grace period: class PurgeUnattachedUploadsJob < ApplicationJob GRACE_PERIOD = 30.days def perform ActiveStorage::Blob.unattached_since(GRACE_PERIOD.ago).find_each do |blob| blob.purge_later end end end If another browser saves the image during that period, it is attached again and the unattached scope excludes it from cleanup. The result Replaying the original two-browser edit now works safely: Browser B saves a body without the six images. The attachments are removed, but their blobs are only marked as detached. Browser A saves its newer body and reattaches the existing blobs. The images remain available and do not need to be uploaded again. If no editor brings a detached image back, the cleanup job eventually purges it. Much better! Reply by email

a week ago • 1 votes
How to: Adding a floating “Back to top” button in Pika

As we say repeatedly on its homepage, Pika is designed to help you focus on writing, not tinkering with your blog design. To that end Pika purposely doesn’t support complex liquid templating or other such code customization. However, today I thought I’d share how crazy powerful custom CSS can be in some circumstances where you want to augment Pika. Pika has a “Scroll to top” button floating in the bottom right of the Dashboard. Some people have asked if they can have this on their own blog. This may or may not be a feature we build right into Pika one day, but in the meantime, you can get close to a full implementation yourself in Pika. Here’s how: First, head to Pika’s Settings, scroll down to Site footer and add this to the bottom of the site footer editor: ↑ — This is an up arrow that is linking to #top, which will now be on every page of your Pika site. After saving that, head to Settings > Theme, scroll down to Additional options and check “Add custom CSS”. In the resulting code editor that appears, let’s add some CSS that targets that specific link, and designs it as a floating button: .user-site-footer a[href="#top"] { /* Float this in the bottom right of the page */ position: fixed; bottom: var(--space-S); right: var(--space-S); z-index: 1; /* Centered styling */ display: grid; place-content: center; /* Button styling with built-in Pika style variables */ background-color: var(--color-primary); border-radius: var(--radius-round); color: var(--color-txt-on-primary); font-family: var(--font-family); font-size: var(--font-L); height: var(--space-XL); width: var(--space-XL); text-decoration: none; } Depending on if you have other custom CSS, you might need to add !important to any of the style lines above. That’s it! Now you have a floating back to top button on your Pika blog, designed to look like other buttons on your site. But if you want to go the extra mile, here’s how you would make it so the back to top button only shows up after scrolling a bit (since it’s not so useful when you’re already at the top of the page): .user-site-footer a[href="#top"] { /* Float this in the bottom right of the page */ position: fixed; bottom: var(--space-S); right: var(--space-S); z-index: 1; /* Centered styling */ display: grid; place-content: center; /* Button styling with built-in Pika style variables */ background-color: var(--color-primary); border-radius: var(--radius-round); color: var(--color-txt-on-primary); font-family: var(--font-family); font-size: var(--font-L); height: var(--space-XL); width: var(--space-XL); text-decoration: none; /* Hide it until a little bit of page scroll */ transition: 200ms; opacity: 0; pointer-events: none; } .scrolled-a-bit .user-site-footer a[href="#top"] { opacity: 1; pointer-events: all; } Feel free to make this button your own, like adding a box-shadow (since it’s floating), or making it a rounded square, or whatever you’d like. If you’re really clever, you could probably get the button to say “Scroll to top” when you hover on it, though that would take quite a bit more HTML and CSS — but it’s possible! I leave that as an exercise for you. Reply by email

22nd May 2026 • 1 votes
Album Search in Album Whale

Did you know that we, Good Enough, make a little website called Album Whale where you can make beautiful lists of albums to share with your friends, the world, or just yourself? It’s true! We haven’t made an update there in quite some time (it’s pretty good enough as-is), but I was inspired this week. Adding an album to a list previously required you to first grab an album share link from a music service of your choice (e.g. Spotify, Apple Music, Bandcamp, etc). This has always been a bit cumbersome. I’m excited to share you can now just search for an album right away in Album Whale! Like this: 🔍 💿 🎉 No need to first go somewhere else, you can jump right to Album Whale when you want to save an album to a list. I’ve found this really made my private “To Try” list more useful. Behind-the-scenes we’re using MusicFetch, which supports most of the big music services. We aren’t sure, but there may be some albums that aren’t found via search? If so you can still paste in a link as you always could. Reply by email

24th Mar 2026 • 1 votes
How We Configure Our Rails Local CI

Continuous integration is a great thing, and having tests and security checks run before every deploy is also a great thing. But if you’re a developer who has been shipping production code for more than a week, you definitely understand how much it can all feel like a house of cards that tumbles down nearly every day. The Good Enough suite of products have been using GitHub Actions to make sure our automated test suites run before each deployment. The (mostly free) servers GitHub offers are predictably slow, with the Pika test suite generally taking close to ten minutes to run. (To that you say, “Delete most of your system tests!” Alas, due to Pika’s lovely editor, we unfortunately have to maintain quite a few system tests for the service.) Even when upgrading, and paying for, a higher-strength GitHub Action server we were seeing runs approaching eight minutes for Pika. That’s already no fun, but even worse is the fact that our system tests were a bit flaky in the GitHub Actions environment. We eventually got the hint that running system tests in parallel just isn’t possible, but even running them one test at a time would lead to odd failures in part because of how slow things  move in the Actions environment. So imagine the cycle of trying to deploy a Pika update and needing to run continuous integration two, three, or four times. Frustration! There’s got to be a better way! There is. Hopefully. With the arrival of Rails 8.1 came the option to set up local CI. As a team of two wanting to move a little more quickly and with a little less frustration, this seems like a perfect fit. Here’s how I’ve set it up for Pika… ci.rb: # Run using bin/ci CI.run do step "Setup", "bin/setup --skip-server" step "Security: Gem audit", "bin/bundler-audit" step "Security: Brakeman code analysis", "bin/brakeman --quiet --no-pager --exit-on-warn --exit-on-error --confidence-level 2" step "Security: Importmap vulnerability audit", "bin/importmap audit" step "Tests: Rails", "bin/rails test" step "Tests: System", "bin/rails test:system" step "Tests: Seeds", "env RAILS_ENV=test bin/rails db:seed:replant" # Set a green GitHub commit status to unblock PR merge. # Requires the `gh` CLI and `gh extension install basecamp/gh-signoff`. if success? step "Signoff: All systems go. Ready for merge and deploy.", "gh signoff" else failure "Signoff: CI failed. Do not merge or deploy.", "Fix the issues and try again." end end In order for the importmap vulnerability audit to run successfully, I needed to update our gemfile with openssl: group :development, :test do gem "openssl" end Here’s an excerpt of Pika’s application_system_test_case.rb: ENV["PARALLEL_WORKERS"] ||= "1" # System tests seem less flakey when not run in parallel require "test_helper" class ApplicationSystemTestCase < ActionDispatch::SystemTestCase browser_options = Selenium::WebDriver::Chrome::Options.new.tap do |opts| opts.add_argument("--window-size=1200,800") opts.add_argument("--disable-extensions") # Disable non-foreground tabs from getting a lower process priority opts.add_argument("--disable-renderer-backgrounding") # Normally, Chrome will treat a 'foreground' tab instead as backgrounded if the surrounding # window is occluded (aka visually covered) by another window. This flag disables that. opts.add_argument("--disable-backgrounding-occluded-windows") # Suppress all permission prompts by automatically denying them. opts.add_argument("--deny-permission-prompts") opts.add_argument("--enable-automation") end Capybara.register_driver :chrome_headless do |app| browser_options.add_argument("--headless") Capybara::Selenium::Driver.new(app, browser: :chrome, options: browser_options) end Capybara.register_driver :chrome do |app| Capybara::Selenium::Driver.new(app, browser: :chrome, options: browser_options) end if ENV["SYSTEM_TESTS_BROWSER"] driven_by :chrome, screen_size: [ 1200, 1000 ] else driven_by :chrome_headless, screen_size: [ 1200, 1000 ] end end Prerequisites to run local CI: brew install gh gh auth login gh extension install basecamp/gh-signoff Run: gh signoff install This installs the GitHub command-line interface, installs the signoff extension for GitHub command-line, and turns on the signoff requirement in your repo. Here’s the process: Get all your changes pushed to a branch and make a PR Make sure your local environment doesn’t have any lingering file changes or CI will fail Run bin/ci Upon successful completion of local CI, signoff will land on your branch, and you can merge and push to main. If you ever need to move quickly, say in an emergency situation: > gh signoff create -f > git push Since Lettini and I are both super-duper admins in our GitHub account, we needed one more update to protect us from willy-nilly pushing to main. I had to update a setting on GitHub in each repository. I clicked on Do not allow bypassing the above settings in repo > branches > Branch protection rules > main > edit: It’s not all rainbows and unicorns In an ideal world, hands-off CI is a really great thing. It will take a bit for these steps to become muscle memory. I hope they do! System tests are still notoriously flaky, but running tests only in our local environments means we shouldn’t have to account for both general flakiness and super-slow-test-running flakiness. GitHub has a useful feature called Dependabot, which can apply security updates to your dependencies and create a pull request that’s often ready to merge. Sometimes we’ve just clicked that merge button in the past, feeling confident because our test suite had already run in GitHub Actions. Now we’ll have to pull down those branches to go through a local CI and signoff step in order to merge things. If local CI doesn’t end up fitting us, I’ve also discovered there are faster, GitHub-Action-based alternatives for automating CI, such as Blacksmith. These services also have historically been cheaper than increasing server power at GitHub, though recent policy changes at GitHub have changed that math. And a thank you I’d be remiss if I didn’t thank 37signals for opening up their Fizzy repository. This helped me to really streamline our application_system_test_case.rb, which had become a Frankenstein’s monster of a thing as I troubleshot system test issues over the years.

9th Jan 2026 • 1 votes

More in technology

Nathaniel at WordCamp Canada

Nathaniel Christopher has a lovely recap of his time at WordCamp Canada. Very cool that the dashboard widget helped connect him to the local community. Hat tip: Anne.

49 minutes ago • 1 votes
Introducing The 4-Year Battery Keychain for AirTag

There are few things worse than a dead AirTag when you need it. That's why we designed the The 4-Year Battery Keychain for AirTag. It replaces the low power CR2032 coin cell with an included Toshiba CR2477 battery for over 4x more capacity. And does so in a minimal form factor.  Assembles in seconds. Split key ring + braided cord included. Easy to open with included tool. Perfect on a keychain.  And great for backpacks or a purse.  Also available on Amazon.

yesterday • 1 votes
The classic console corner's CRT changeover

In the corner of the rear Floodgap lab sits a pile of classic game consoles. It used to look like this: Sega Dreamcast all the consoles here only came with NTSC RF output and date from the pre-flat panel TV era. That includes multiple Atari consoles (including the inevitable VCS, here a Darth Vader 2600), several Pong machines — including two Commodore units — with various chipsets, an Intellivision (as the rebadged Tandyvision One, my first) and a Bally Astrocade with lots of upgrades. It seems wrong to use them with a flat panel, and CRTs lag less. Plus, games with a light gun (here the Dreamcast and one of the Pong consoles) often rely on the CRT's rapidly scanning beam to know where they're pointed. So what do you do when the CRT TV goes bad? I should note that this isn't all the old school gaming fun in the house. In the commons next to the pinball machines are an Xbox 360 Slim and a PlayStation 2, and in the home theatre connected to the 3D projector is a PlayStation 3 since it has some stereoscopic titles. These might appear in future articles. But most of the rest are here. I bought this Panasonic Omnivision PV-M2035 from a friend at church in 1999 for $100 [about $200 in 2026 dollars]. He had no use for it, and the top of the plastic shell had been heat-warped by sitting in his car too long, but it worked, still had the remote, and was a suitably cheap TV for my unsuitably cheap studio apartment. I used it for local news and Friends with a set of rabbit ears, VHS movies, and speakers for playing music by connecting a CD player to the single rear input. When I moved to a less cheap 1-bedroom, it came along, and its flat top was flat enough to become a shelf for a DVD player. I got the Dreamcast from Fry's in 2001 after Sega discontinued it and managed to share the composite input between them. That apartment was my crashpad for about a decade before moving to the current orbiting HQ, whereupon I bought a passive-3D flat panel TV and moved the Omnivision to its current location in the back of the house. It shared the RF input between the Inty, and later the Atari 2600, and later still the Astrocade and various Pongs. At any one time there were at least four consoles always connected to it via switches and switchboxes, and I wired up an accessory port for more. plastic was broken and on these TVs that's pretty much the load-bearing part. When it arrived at the mailbox and I unpacked it, I could see the lower half had sandwiched right through the VCR slot, with visible PCB fragments and broken buttons; aside from the tube itself (ironically), the thing was a total loss. The seller nevertheless made good on the refund, to their credit, and I got to schlep it to the recycler. Overall, however, it had occurred to me that there were very few TVs sufficiently contemporary with the M2035 out there, which might be a hint about their general longevity. So, if I was going to be forced to buy a different Panasonic, then it might as well be a more recent one, and it should be one of the "triple play" units (i.e., TV, VCR, DVD) so that I could at least get rid of the external DVD player. Mission: Impossible '88 and '89 DVD sets, where the "in stereo" animation was even burned into the video stream.) not recording and thus impossible to watch many DVDs, for which the Sima CopyMaster was the cheapest solution: it simply blots out that portion of the vertical blank along with the pulses, which also has the side effect of sometimes stripping closed captioning (in the vertical blank as well), though DVDs with proper subtitles are of course unaffected. Later Sima devices could regenerate portions of the vertical blank for better quality, and Macrovision actually sued them over their products in 2005, but later settled. The mixer on the right was purchased literal decades ago at Radio Shack (more specifically a "Video Enhancer Stereo Audio Mixer") that I think we used for a Halloween display exactly once and then forgot about. Here it was used first as a cutoff switch, and second as a way to match the audio volume from the DVD player with the audio volume from the Dreamcast, which was also directly connected to the second rear Y-cable. This TV is mono, so the stereo channels from the audio mixer and the DC get merged using their own Y-connectors (also Radio Shack) before going into the Y-cable to the single line audio input. The video function isn't used here at all; it was just a audio mixer on the shelf I wasn't otherwise using. The DVD player is under the mixer and the CopyMaster, a cheapie Sony special that will only eject discs if it's in the mood or summarily threatened with violence. You already met this system when we adjusted the laser pickup and refurbished its rechargeable battery. you met the Tandyvision One (otherwise identical to the Mattel Intellivision Master Component, and manufactured by them as an OEM) when we installed a composite video modification and a front power-cutoff reset. I later upgraded it with an original Mattel Intellivoice speech synthesizer (Tandy never rebadged these) and a CuttleCart. But you haven't met the Bally on the bottom, officially introduced in 1978 as a game console and simple home computer, sold under various names such as the Bally Professional Arcade seen on early units, later the Bally Computer System badging here, and now collectively referred to under its final incarnation as the Astrocade. These machines were based around a 1.789MHz Z80 (half NTSC colourburst) combined with the same graphics hardware Dave Nutting Associates used for Midway's arcade games Gorf and Wizard of Wor, among others. Unfortunately, much of its theoretical graphics power went unrealized because it only has half the video memory of the arcade units (i.e., 4K) — and that's all the memory it has, so it has to interleave bits in the video memory to store BASIC programs, meaning only game ROMs can take full advantage. Still, that was enough to be solid competition for the likes of the Atari VCS and Fairchild Channel F, and it holds its own well against the slightly later Intellivision. does have is a doozy: the cooling vents are on the underside. These machines are very prone to overheating and can be easily damaged by it, which is why I use two foam struts to keep it off the carpet. The yellow label is for Astrovision, a separate enterprise that had been attempting to develop their own console. The (then) Bally Professional Arcade was selling poorly, though part of this was due to a tardy launch and Bally's weak retail presence, and Bally decided to sell off the consumer products division in 1979. Astrovision, unable to get their unit to market quickly, bought it in 1981 along with a limited license to the Bally name and reintroduced it at Winter CES 1982. Astrovision units are otherwise the same except for the badging and are the most common Astrocades today, though the company became another victim of the 1983 video game crash and went bankrupt shortly afterwards. Simultaneously, an Astrocade derivative merged with Bally's unfinished ZGRASS-100 expansion chassis was reworked into the Datamax UV-1 graphics generator, sold in small numbers until around 1982. the wall warts and power strips, and do a little spot vacuuming with the Roomba. out in spring. Gremlin's Blockade; and a simple calculator and screen paint toy ("Scribbling"). The display is a bit noisier than the Inty/Tandyvision, probably because of the difference in shielding, but still quite good. Videostak Video Game Center, which allegedly could accomodate a VCS, Intellivision or ColecoVision. The front decal is somewhat worn and the woodgrain veneer doesn't match the Vader VCS nearly as well, but it's still a fun-looking setup. Intellivision System Changer which has Atari 2600 hardware in an expansion box for the Intellivision II (useable on the original Inty with modification). It might be fun to explore the reputed irregularities between what is believed to be a VTI clone TIA in the System Changer and the slightly earlier Coleco Expansion Module 1 (and the related Coleco Gemini), and see how they differ in practice. Now for the Pong machines. These attach to the "accessory port" on the input switcher. The current Pong menagerie are mostly MOS 7600-based, MOS' own Pong-on-a-chip: two from Commodore themselves but PAL only using the MOS 7601 (the TV Game 2000K and TV Game 3000H), plus two MOS 7600 (NTSC) systems, a Coleco Telstar Gemini, not to be confused with the Coleco Gemini or Coleco Telstar, and an Allied Leisure Name of the Game II, possibly the earliest use of the chip in NTSC regions. We'll play the Name of the Game II and Telstar Gemini below. These will be consoles for another day, but I also have a boxed Atari Video Pinball, an "honorary" Pong machine though it plays several other games, and a boxed Atari Ultra Pong Doubles, which we had before we got the Tandyvision, but I don't ever recall it working fully and it later failed to power up and got thrown away, so this is a replacement. My least favourite of the Pongs here (I really only picked it up because it was cheap) is a 1977 Magnavox Odyssey 3000. The 3000 is basically an upmarket Odyssey 2000 with proper handheld controllers, but otherwise the same me-too AY-3-8500 Pong-on-a-chip generating the same black-and-white display. Allied Leisure Name of the Game II is a two-player Pong based on the MOS 7600-001. This chip notionally contains three field games (a tennis game, a "goal" game usually billed as either soccer or hockey, and a racquetball game) and a skeet shooter, but the racquetball game can be put into a single player mode by setting it to "four" players and the NotG2's switch triggers this mode in place of the skeet shooter. It was noisy on the other TV and it's noisy here, possibly because it has its own internal RF switchbox, but it plays fine. Coleco Telstar Gemini, an MOS 7600-004 system. This has two "pinball" variants (with flippers and moveable Pong paddles, so it's still a Pong of sorts) and two shooting gallery variants involving shooting a deformed bear sprite. The light gun connector is the same as the Coleco Telstar, so I borrowed the gun from that. sing along with The Offspring. But the output looks crisp through the rear jacks, the sound is proper stereo, and we now have front inputs I can use for something else without rigging a whole bunch of Y-adapters again. Plus, if the Telstar Gemini's gun works, it's all but guaranteed the Dreamcast's does. am likely to play some Video Pinball, and in its box that's easy to move, so that can go on top of the 2600 and the NotG and Telstar Gemini can sit next to it. The old TV is out in the garage and as I have time I'll extract its circuit boards and go over them more thoroughly, since I had a lot of good times with that television and it would be nice to fix. If I do, I'll write it up here, since it's an actual old VCR. Meanwhile, I have some possible projects in mind for the Tandyvision and Astrocade, and maybe some mods to go in the VCS, and you can read about those in future articles too. In the end, with the new TV all set up, the 1980s can live again in my rear office. Or, as my wife likes to point out, they never actually died there either.

yesterday • 1 votes
Nazi Literature in the Americas

Learn by fire.

2 days ago • 1 votes
iPhone Duo early review

By a mile, the iPhone Duo has garnered more questions about what I think about it than any other phone I’ve ever had. It’s clearly a phone that has people intrigued, so I thought I’d jot down some loose, unorganized thoughts about what I think about it after about ten days. If I could sum all my thoughts up into one word, it’d simply be “fun”. I think for the vast majority of people, myself included, the iPhone 18 Pro is a more practical phone that through scientific analysis you’d likely even find a better phone. Even if they were priced the same, its package is more traditionally comfortable and ergonomic, with a better quality main camera, a helpful telephoto camera, a screen that’s more practical to use more of the time, a better biometric system (Face ID versus Touch ID) and a more established software experience. But damn if the iPhone Duo isn’t fun. Phones have been downright boring for so long. Incredible technology, lovely apps, but the hardware has been a bit slow moving since the iPhone X. Maybe that’s why I jumped onto the iPhone Air so readily. Even that slight departure from “black slab of glass” to “a dramatically thinner black slab of glass” was exciting versus what we’ve grown accustomed to. So I pick up the Duo, and it’s kinda just exciting to hold a phone for the first time in ages. Maybe that’s a honeymoon period and after a few months I’ll be over it. Maybe everyone who tries a folding phone for the first time experiences this. And to be clear, it’s not just all raw novelty. The fun aspect is fueled by having an absolutely incredible inner screen that fundamentally transforms what a phone is and can be. In addition, support the Apple Pencil has turned out to be phenomenally handy for me to be able to jot down quick thoughts and notes. For downsides, Touch ID is objectively worse than Face ID, but honestly, I don’t mind it as much as I expected I would. The smaller camera sensor than the Pro series phones is still decidedly great (rumors were it was a 17e size which was not correct, it’s the size of the normal 17’s). Software support gets better by the day, though iOS on the Duo is still decidedly a bit buggy at times. Other random thoughts Touch ID is objectively worse than Face ID, but honestly, I don’t mind it as much as I expected I would, previewing notifications is where I miss it the most After getting used to having a single speaker in the iPhone Air for a year, having stereo (not to mention great sounding) speakers is amazing The FaceTime camera on the inside is indeed not great for selfies/photography but honestly perfectly acceptable for FaceTime, and I’d definitely prefer this solution over a cutout on the inside so I’m happy! It definitely has a heavy feel to it, but it’s nothing honestly that bothersome A lot of the reviews said something to the effect of “the crease is practically invisible” and while I don’t really mind it or anything I definitely would disagree with that statement, you can see it a fair bit even with light content The hinge is a bit harder to open than I expected, I’ve found the secret is don’t pry from the middle of the side, instead put a thumb near the top and bottom (also helps prevent pressing Camera Control instead which I was doing all the time). I imagine this is necessary to have it be able to stop at arbitrary angles once open (which I do like) and hopefully it loosens up a bit with more use, but playing with Android foldables at Best Buy I did find their hinge easier to open I am really split on the inner, nano texture screen. It definitely helps reflections, has a neat look to it, and is super nice to draw on with the pencil, but it’s significantly less vibrant than the outer display which to my eyes looks a fair bit nicer. I think they made the right decision ultimately but it’s definitely not a zero-compromise solution. I was considering nano texture on my next MacBook but after this I think I’ll stick with glossy. My glass half full take with the Duo for now though is that we get two really cool screens to play with The outer screen is awesome for taking photos, unlike taller iPhones, your viewfinder fills the screen completely so it’s the largest feeling viewfinder I’ve used on a phone I miss the action button, nice little launcher for ChatGPT/Claude depending on which month it is Battery life is downright phenomenal versus my iPhone Air and 15 Pro (two devices admittedly not known for having great battery life) So, I don’t think the Duo is for most people who either don’t care much about phones, or care a lot about having the perfect phone, but for a decent amount of people in the middle I think the Duo represents a fundamentally different experience, that’s a ton of fun, and I’m excited to be excited about a phone again. (But, Apple, please figure out a way to add a telephoto lens.)

3 days ago • 1 votes
📚 BoredReading

You seem to be enjoying this.

Join free to unlock everything.

Create free account

Already have an account? Sign in