Building in public
What we’ve shipped
Qiksy is a small studio building AI-native micro-tools, in the open. Every new tool, real bit of progress and the occasional fix lands here first. No hype, just what changed.
Shelf keeps Shopify, Prom, Rozetka and OLX in step together, across shops and phones
Was: an order from Prom or Rozetka never reached Shopify, a seller's phone did not move the marketplaces, a switch to the owner's second shop carried the first shop's Prom along, Shopify could show −1 after the last piece sold twice at once, and the same Prom cabinet could be connected to two shops, each taking every order off its shelf. Now every sale and order reaches every place once, from any phone of the shop; no place goes below 0, and the seller sees «Sold more than there was» with a Recount button; Shopify takes the shelf's price like Prom for what Shelf put there; and one cabinet belongs to one Shelf shop, the second one says which shop has it.
Shelf shows each marketplace, register and bank by its own logo, the same everywhere
Was: a shop fed by Shopify wore a generic shopping bag in «My shops», the «on sale» pill in Stock and «Send to Shopify» wore a globe, the alerts showed Prom or Rozetka as a letter, and the registers and banks in Settings had only their names. Now Shopify, OLX, Prom, Rozetka, Satu.kz, Kaspi.kz, Checkbox, Vchasno, Webkassa, fiskaly, monobank and Halyk Bank each wear their own official mark on the same white tile at one size, in the shop list, Settings, the product card and the alerts, and our own storefront and posts wear our own pictures.
Shelf sells on Satu.kz in Kazakhstan
Satu.kz runs on the same platform as Prom.ua, so a shop in Kazakhstan now gets everything Prom gives a shop in Ukraine: the stock follows the shelf, Satu orders come off it, prices and markdowns go in tenge, and a product goes to Satu from its card. Connecting is the same numbered guide with the Satu cabinet's own words, and it says first that Satu sells only on a paid package or its trial.
Connecting Prom and Rozetka in Shelf is now a numbered guide, and Rozetka's characteristics fill themselves
Was: one field asking for «the key from the Prom cabinet», no word that Prom gives no access on its free package, and a refusal that said only «check the key». Now Shelf says first what each marketplace asks for (a paid Prom package and the seller identification; a registered Rozetka seller), opens the Prom cabinet on the very page, draws where to tap, checks a pasted key at once and tells a wrong key, a key without rights and the free package apart. On Rozetka the country, the package and how many are in it are filled from the name and your other products for one tap to confirm, and a Prom product without a photo says Prom keeps it out of its catalogue.
Products you put on a marketplace from Shelf sync with no first sync
Was: a new price for a product Shelf had put on Prom waited for a tick that a tab in the background never got, and nothing moved at all before the first sync. Now a product Shelf put on Prom, Rozetka or Kaspi syncs its stock, price and orders from the moment Shelf finds it there, and right after «Pair again». The first sync is only for products made on the marketplace by hand.
A product's card in Shelf Stock is calmer: three groups instead of a column of buttons
Was: an opened product listed its batches, then OLX, «Put aside», the marketplaces and «Edit product» one under another, each a button of its own size. Now the card reads top to bottom: the goods (batches and what is put aside), where they sell (OLX is a row like Prom and Rozetka, with a small button only where something needs doing), and three tiles of one size for Edit, Put aside and Past batches.
A Shelf refund keeps only the AI you already used and the bank’s fee
The 30 days stay money back with no questions. For Smart and Pro we now keep back what the AI already cost in that paid period (the photos and delivery notes it read) and the 1.5% fee the bank does not return, never more than you paid. Fiscal receipts or an extra shop keep only the bank’s fee. The Refund Policy says so in plain words.
A new price in Shelf reaches Prom, Rozetka and Kaspi by itself
Was: a product put on Prom from Shelf kept its old price there after the shelf price changed, and there was no button to send it again. Now the price follows the shelf the way the stock does, from the owner's phone: your own price for that marketplace if the card has one, else the shelf price, sent only when it changes. Products made on the marketplace by hand keep their price unless you turn «prices from the shelf» on in that marketplace's card, and a batch markdown there is left alone until it ends.
Shelf is easier for the people behind the counter
We walked three shop assistants through Shelf and fixed where they stopped. The expiry wheel no longer shows a month that looks picked when it is not, and a new product asks once whether it has a date at all. «Write off» is a word on every batch in Stock, the camera has a real round shutter, and the report no longer calls your takings «earned» when no purchase price is known. OLX shows up before you sign in, the marketplaces of your own country come first, and a refused marketplace login keeps what you typed and only says «no internet» when there is none.
Shelf has two plans, priced in your own money: Smart and Pro
The stock, the dates, the till, receiving and OLX by hand stay free. Smart is for the shop with a counter: the AI camera, new prices from the delivery note, returns to the agent. Pro adds the marketplaces through their APIs: OLX, Prom, Rozetka, Kaspi and Shopify sync. The first 30 days are Pro, free. Prices are fixed in hryvnias, euros, tenge or dollars, and a shop already selling on a marketplace keeps it 30 more days, with the date on screen.
«Scan a product» shows what your shop sells
The big card on Receive now carries the picture of the goods picked when the shop was set up: a jacket on a hanger for a second-hand shop, a hoodie and trainers for clothes, a phone for electronics, cosmetics, toys, pet goods and so on. A shop that sells a bit of everything keeps the grocery basket. The camera card in the Shopify admin follows the same rule.
Sell off before the date in one tap, and an honest «Rescued from the bin»
Stock now says how many products reach their date within the scale and how much money is in them, with one button «Sell off». Before anything changes, a sheet shows what goes on sale, where (the shelf and till, the storefront, Shopify, Prom, Rozetka, Kaspi, OLX), how deep and what it brings if it all sells. The discount follows a scale you can change: 60 days left takes 10 % off, 30 days 25 %, 14 days 40 %. When a batch runs out its price comes back by itself, and «Undo» puts every price back at once. Selling off comes with a paid plan; the morning note says when a batch reaches the next step. «Rescued from the bin» opens its formula: what those pieces would bring at the regular price, minus the discount given, is what came in.
Smart: «Got dearer» with new prices and tags, returns to the supplier's agent with a signature, and where a shortage is
A delivery whose purchase price is above the last one now says so on Receive: «4 got dearer», the old and new purchase price, the new sale price at the markup each product had (or one markup typed for all), and one button that raises the prices and prints the price tags. A product unticked keeps its price. A supplier whose agent takes goods near their date back gets its deal once: how many days before the date, which weekdays the van comes, what exactly. On those mornings Stock says «Today the milkman comes: put aside 2 kefirs, 5 yogurts, for 192 ₴», and «Given to the agent» lists them with the sum and takes the agent's signature with a finger. The goods go off as a return to the supplier, not a loss, and the report shows the sum. After a stock-take that does not add up, the result names the five products short by the most money, with what came in and what was sold since their last count: the shelves to check first. It names goods, never people. Also fixed: saving a stock-take no longer drops the app to an error screen.
A consignment shop sends each consignor their own page, and «Sat too long» marks old things down in one tap
«Receipt for the consignor» sends a link by Viber, Telegram or SMS: a page with no sign-in that shows only that person's things, on the shelf, on OLX or sold and for how much, what they are owed and until when the contract runs. It updates itself after every sale and payout, can be turned off, and a payout goes to them as a receipt. Each consignor has terms: 30, 60 or 90 days, a lowest price, the markdown rule (20% off after 30 days on the shelf, 40% after 60) and what happens at the end, taken back or given to charity. «Sat too long» counts what has been on the shelf over 45 days and marks it down by the rule on the shelf, the storefront, the marketplaces and OLX at once; a consignor's things wait for their «I agree» on their page, and past 90 days the card lists what goes back or to charity.
A live header: what happened grows out of one pill at the top, and the day's figure rolls
Scrolled down, the header becomes a thin pill with the screen's name and its number. What happens without you, a sale, an order from Prom, Rozetka, Kaspi or Shopify, an advert Shelf took off OLX, a buyer writing on OLX, a first sync, a card a marketplace refused, a connection that went through, grows out of it for a few seconds, goes by itself, and a tap leads to where it happened. Several of a kind come as one line («Sold: 3 pcs», with the sum), and while the till holds goods in a receipt the pill keeps quiet and says it all after the sale. The till's takings, the pieces on Stock and the report's revenue turn over like a counter when they change, with «+720 ₴» beside them for a moment, and the day's first sale gets a small burst of the shop's boxes. A delivery note being received, a stock-take or adverts going onto OLX show «12 of 30» at the top while you are on another screen; a tap goes back to it. Without motion in the phone's settings everything only fades.
Receiving a delivery is quicker between products: the camera stays on and a known product opens at once
After «Accept», the camera for the next product no longer starts from a black screen: it keeps running for a short while and goes off by itself, when you leave receiving or put the phone down. A product the shop already has opens its delivery 0.75 s sooner after the scan, and the barcode reader is made ready while you are still on the receiving screen, so the first scan does not wait for it. On Android the phone's own barcode reader is used where it reads every shop code, with Shelf's reader as a second opinion. A barcode met before, even one never accepted, is named from the phone's memory with no network, and counting a delivery with the camera opens in the same running camera.
Stock says in words what a marketplace still waits for, and walks you through it
In the shops testing marketplaces, the product list no longer carries marketplace letters. One card over the list appears only when there is something to do: «3 products are not on Rozetka yet. Missing: photos or brand», a refusal on a line of its own, and a button «Fill in 4 products» that opens each product on the right marketplace, one after another, ending with «Done». «Remind me tomorrow» hides it until the next day. An opened product shows where it sells, one marketplace a row, its state in words and a button only where something is to be done. Prom, Rozetka, OLX, Kaspi and Shopify now show their own logos, and the shop itself is a row of its own with its picture and name. In «Where it sells», the brand, description and category keep themselves as you type, the brand is filled in from the product's name the way OLX does it, and Rozetka's category is searched by what the product is.
Every connection now says it worked, and the screen no longer jumps after Rozetka's password
Connecting Rozetka, Prom, Kaspi, Shopify, OLX, the storefront, a register or a bank ends in a green tick inside that card, one line of what is next and one big button for it, with a short note at the foot of the screen. Before, a register or a bank connected in silence, and a marketplace card jumped to the top of the list while another card slid under the finger; now the cards keep their places until the screen is opened again. A shop's first product, first sale, first advert live on OLX, first invite and second shop are marked once each, and a place connected again gets only the short note.
Stock's header keeps one shape in all three views, and «no purchase price» leads to those products
All, Soon and Expired now show the same three lines in the header: what the figure is, the figure, and a line under it, so the header no longer jumps when you switch. «No purchase price» there is orange and opens the list of products that lack one. In the shops testing marketplaces, a product's marketplace mark sits small on the corner of its picture instead of a line of its own, only where the product differs from the rest or needs something, and «All products go to Rozetka» is said once over the list.
OLX straight from Shelf, for every shop in Ukraine
A shop connects its OLX account once and puts things up from the card or many at once, with what OLX will charge said before the button. A thing sold in the shop comes off OLX by itself, a thing put aside for a buyer comes off until the hold ends, and an advert taken down or repriced on OLX's own site shows in Shelf. Before it opened we ran it on a real OLX account: food, used clothes, household chemicals and cat food, one by one and in a batch, then sold, taken down and deleted. Shelf never turns on anything OLX may charge for; renewing an advert opens OLX's own page.
One shop address for every marketplace, cards in the marketplace's language, and «Where else to sell?»
Settings → Shop has «Shop address»: the town, the district, where buyers pick up and the Nova Poshta branch, guessed from what the shop already said and confirmed in one tap. Each shop of several has its own; it goes into OLX's place and adverts and the storefront's town, and a shop that had given OLX its town gets it as its address. A card written in another language than the marketplace reads is translated before it goes out, and the seller sees beside it what the buyer will read, in their own language. A Shopify store gets the product in its own main language, and the card's words as its translation where the store shows that language too, once it allows Shelf to read its languages. A new shop is asked once «Where else to sell?» with the marketplaces open in its country, or «Later», and after its first five products «Put these 5 on OLX?». The OLX parts open only in our test shop for now, while the OLX connection is being checked on real adverts.
OLX follows the shelf by itself, and goods can be put aside for a buyer
When the last piece is sold at the till, written off or counted away, Shelf takes its OLX advert down by itself, told to OLX as sold, and says «Taken off OLX: sold». With no connection it waits and does it at the next start. Stock coming back does not put the advert up again: the card offers «Put back on OLX». «Put aside» on a product's card keeps pieces for a buyer until a date (tomorrow unless you say otherwise): the till does not sell them and says for whom they wait, and when every piece is put aside the advert comes down and goes back up once the hold ends. Three days before an advert ends, Stock shows a note with «Renew», which asks OLX to renew it itself. Opening Stock asks OLX about all the shop's adverts in one call: a price changed on OLX's own site is shown beside Shelf's with «Take the OLX price» and «Put back», and adverts the shop has on OLX but not in Shelf can be added in one tap. For now it opens only in our test shop, while the OLX connection is being checked on real adverts.
OLX buyers' messages, an advert's numbers and the shop's logo, inside Shelf
Buyers' messages from OLX come into Shelf: «OLX: 2 new» shows beside the settings gear while someone waits, and a product on OLX shows «Buyers' questions (2)». An open conversation has the thing itself beside it (photo, price, how many are left), ready answers such as «Yes, it is in stock», and the answer box; opening it marks it read on OLX. Any phone of the shop can answer, a seller's too. The advert's window says «Views 123 · Opened the phone 4 · Saved 10», read from OLX at most once an hour, and after three days one line of advice: many views and almost nobody calling suggests a price 10% lower, ready to send in one tap; few views suggests photos or lifting the advert. A business OLX account gets the shop's logo on its profile when it connects, or from a button in Settings; a private account is not offered it. For now it opens only in our test shop, while the OLX connection is being checked on real adverts.
Many different things onto OLX in one go
A second-hand or consignment shop can tick things in Stock, or finish a stream of things shot with the camera, and put them all on OLX from one list. Each row shows the photo, the OLX section Shelf found, the price and «Ready» or what is missing, and the missing part is filled right in the row. Above the list OLX's fee for all of them is said as one sum before anything is sent, and Shelf buys nothing. «Publish» sends them one at a time with a pause for OLX, shows OLX's own words under any row it refused, and sends those again on one tap. For now it opens only in our test shop, while the OLX connection is being checked on real adverts.
Receiving starts with one button and the other ways in words and pictures
The top of Receive is one card with one button, «Open the camera», and under it three picture cards: photos from the gallery, a supplier's delivery note, and a product without a barcode. Before, the gallery hid behind a bare icon and the delivery note behind a line ending in an arrow. The search now runs across the whole width, and a search that finds nothing offers to add the typed name as a product without a barcode, or to scan its code. The Shopify admin shows the same cards, with the camera opening in Shelf's own tab.
OLX adverts for food, sports nutrition, pet goods and household chemicals
The OLX category list had no place for an energy drink: it now carries OLX Ukraine's own sections for food and drinks, sports nutrition, cat and dog food, pet goods, household chemicals and the rest of beauty, read from OLX's live category tree, and a product is matched to them by its Shelf category and its name. The written description no longer falls short of OLX's 80 characters: it says the name, brand, size, taste, the date of the stock in hand and where to pick it up, and only when those facts run out does it invite questions in the OLX chat. Alcohol, tobacco and medicines get no category, with the reason said.
My shops: cards with their numbers, and a way out for a Shopify sign-in
With several shops the header shows the open shop's mark and name, and a tap lists the shops as cards: products, dates running out and today's takings, as this phone last saw them and with the time it saw them; a shop never opened on the phone says so instead of guessing, and a seller does not see the takings. From seven shops on the list gets a search and a «dates running out» filter. Someone signed in through Shopify on the website can now sign out in Settings.
Drawn pictures instead of stock icons in Shelf and on its page
The Settings rows (shop, subscription, selling online, dates, phone, the guide, more ways to sell, the feed) and the cards of the Shelf landing (who it is for, features, two ways to install) now carry small illustrations in the style of the goods pictures, each on a pastel square that stays the same in the dark theme. The buttons inside rows keep their plain icons.
One switch across Shelf
Every either-or choice in Shelf now looks like Stock's view switch: cash and card, paying in parts or on credit, raising or lowering prices, month or year, the storefront's look and the post's format, the coin rounding. Each is a proper radio group: one Tab stop, the arrow keys move the choice, and every part is at least 44 px tall.
Stock's view switch is visible on the light theme
The switch's track is a clear grey step from the page instead of almost the page's own colour, and the counts on its corners have a grey outline. On the dark theme the chosen view stands lighter than the track rather than sinking into it.
OLX Ukraine: publish an advert from Shelf with your own OLX account
OLX approved Shelf's Partner API application today. A shop in Ukraine connects its OLX account once in Settings, and an item's advert goes to OLX with its photos, OLX's own section and details, then can be repriced, taken down as sold or deleted. What OLX would charge is shown before publishing, and Shelf never buys a packet itself. OLX Kazakhstan stays on the manual way.
Stock's three views fit in one row on a phone
All, Expiring soon and Expired are now one switch the width of the screen, the chosen view lifted as a card. On a phone the third view used to drop alone onto a second row. How many items each view holds sits on its corner, amber for soon and red for expired.
The Shelf page says where Shelf connects, country by country
A new block on the Shelf page lists what a shop can connect today: its own storefront and Shopify anywhere; Prom.ua, Rozetka, OLX, Checkbox, Vchasno.Kasa and monobank in Ukraine; Kaspi.kz, OLX, Webkassa and Halyk ePay in Kazakhstan. One plain line for each, in all 18 languages of the page.
Shelf sells on credit with the Checkbox register too
With Checkbox connected, a sale on credit works the way Checkbox told us in writing: the money the buyer gives at the till gets a prepayment receipt, every later payment gets its own receipt under the same order, as many as the buyer brings, and the one that pays it off is the receipt of the goods. Shelf never sends more than is left, so no receipt hands back change. Checkbox issues no receipt without money, so with Checkbox the buyer gives at least a part at once, and the till says so. Checked on Checkbox's test register: 40 + 60 and 30 + 30 + 40.
Shelf sells on credit with the Vchasno register
With Vchasno.Kasa connected, a sale on credit works again, the way Vchasno told us in writing: money the buyer gives at once gets an advance receipt, and the rest, when it comes, gets the receipt of the goods with the advance taken off and the advance receipt named, so each payment is fiscalised once. A buyer can also give part of the sum at the till now, with or without a register. Checked on Vchasno's test register; with Checkbox, credit stays off until Checkbox answers.
Shelf puts a product on Prom, Rozetka and Kaspi.kz from its card
In «Where it sells» a product now goes to a marketplace with one button: Shelf picks the marketplace's category from your other goods and from what the camera saw, asks once for the fields that category needs, and shows what the marketplace says after: sent, being checked, on sale, or refused with its own words and the way to fix it. Once on sale there, its stock follows the shelf like a product you listed by hand. Prom takes products through its import, Rozetka and Kaspi.kz through their own APIs; a new Kaspi card is checked by Kaspi for up to three working days.
Goose: a bill from Telegram, and a deposit first
Connect Telegram in the Goose console, then write «800 haircut» to @goose_bills_bot: it answers with a QR code and a caption with the pay link, ready to forward to the client, and your sales arrive in the same chat. A bill can also be split into a deposit now and the balance later: only the deposit goes out, and the balance waits until you send it. With a PRRO linked in your monobank cabinet, each sale in the console has a Receipt button that opens the fiscal receipt on the tax office site, and a refund sends the return receipt the same lines the sale had.
Shelf: as many extra shops as you need, each one its own subscription
A Smart account could buy only one extra shop: a second payment was refused. Now every shop past three is a $5 subscription of its own, up to 20 shops on one email, and the subscription screen lists them, renews each on its own date and cancels any one without touching the others. In Goose, a plan can now be bought several times by one buyer, each purchase a subscription of its own.
Shelf counts shops and AI photos per account, and Smart now covers three shops
Free Shelf is one shop with 200 AI photos a month. Smart, still $10 a month, now covers up to three shops on one account, and its 4000 photos a month are shared by them. Each shop past three is $5 a month. Selling on marketplaces and through your storefront stays free in every plan, and a shop you already have is never closed by the new limits: they only apply when you open a new one.
Goose: bill a client from your phone, free
No site needed: write what for and how much, show the client a QR or send the link, and the console says «Paid!» when the money is in. Bills and QR codes are free up to 20 payments a month; the money goes straight to your own bank, and every bill says who the seller is and how to report one that was not expected.
Goose: how each country pays, and what a subscription can run on
The country picker on the Goose page now says which local methods take subscriptions there (BLIK in Poland, SEPA Direct Debit and PayPal in Germany, MB WAY in Portugal, Bacs in the UK) and which are for one-time payments only. Where no provider documents Apple Pay or Google Pay for subscriptions, the page says so instead of promising it.
Shelf moves to its own address, shelf.qiksy.app, and takes your stock with it
Shelf used to live at qiksy.app/shelf/, beside some twenty other pages of the site, and a browser keeps one drawer for all of them. Now Shelf has a drawer of its own, so nothing else on the site can ever reach your shop. A shop kept only in this browser moves by itself the first time you open the old address: the stock goes page to page, locked with a one-time key and never through our server, it is counted again on arrival, and the old copy is kept until the new one matches. Shops in the cloud just carry on.
Part cash, part card, or on credit, and the cash rounds the way the law says
A customer can now pay part in cash and the rest by card in one sale, and the split lands correctly in the drawer, the day report, the receipt and the fiscal receipt sent to Checkbox, Vchasno or Webkassa. A regular can also take goods on credit: Shelf keeps a list of who owes what since when, and takes the money back in parts. While a fiscal register is connected, credit stays off until the register companies confirm how such a receipt must be made. Cash totals now round as the National Bank of Ukraine requires since October 2025, to 50 kopecks, or to 10 for a shop that still has the coins; Kazakhstan rounds to the tenge. Deposits and withdrawals made through the register now count in the drawer, so the evening count matches.
Every amount checked to the cent against a second calculator
We wrote a separate calculator that works in whole cents and does not borrow a line from Shelf, then ran some twenty thousand sales, refunds and month reports through both. It found nine real differences, all fixed: a weighed line could be a cent off what the register counts, a partial refund in the US and Canada could return a cent more tax than was taken, the report added unrounded lines, and the register could receive a payment a cent apart from its own lines. We broke a rounding on purpose to be sure the check turns red, and it did.
Four tabs that stay put, and a box for every parcel
The bottom bar no longer changes with the mode: Till, Receive, Stock and Report, always in that place. Expiry dates moved into Stock as a filter, Soon and Expired, with their write-off and markdown buttons. The report opens with three numbers a seller asks about in the evening, and the accountant lines wait one tap below. A shop that sends parcels keeps its own boxes in Shelf; for an order it says which box fits, how full it gets, and the Nova Poshta weight class, oversize charge and locker size.
Accountants earn every month their clients pay for Shelf
An accountant who serves sole traders can join Earn as an accountant, give clients a code, and receive 30% of each Shelf payment those clients make, renewals included, for as long as they pay. On Smart that is $2.78 a month, or $15.70 on the yearly plan. Shelf now pays the same 30% to every partner; shops a partner brought before 20 October stay at 50%.
A whole-page picture of a feed reaches the end
A full-page picture of a list that builds itself as you scroll, LinkedIn or search results, could come back as its first few screens and a long blank under them: the camera planned its strips from the height the page promised and ran ahead of the cards. Version 1.76.0 waits for the list to catch up and cuts any empty tail off the picture. It is with the Chrome Web Store for review; the bridge server on npm is already 1.76.0.
Shelf estimates the month's taxes for your shop's own regime
Pick your country and how the shop is registered, and the Taxes screen counts what the month's sales and purchases mean in tax, line by line: VAT, income tax, social contributions, a flat fee. It knows the regimes of 37 countries, from a Ukrainian sole trader to a German GmbH, a US sole proprietor and a Japanese small business, checked against the tax offices' own pages. Each regime is named in plain words in your language, with the local term beside it, and every rate can be corrected, typed with a comma or a point. What depends on your household, like a personal income tax scale with its allowances, is said rather than guessed. Along the way, eleven of Shelf's languages, Finnish, French and Japanese among them, had been opening in English; they open in the language you picked again.
Goose renews by link where a bank keeps no card, and has one price
Some banks take a card payment but will not keep the card for the next one, and a subscription there used to end after its first month. Now it carries on by link: three days before the term ends the buyer gets a letter with a pay button, a reminder on the last day and one more three days later, access kept the whole time. A week after the end, unpaid, it stops, and for a month the same button brings it back. If the bank does keep the card on one of those payments, the charges turn automatic from then on. The page now shows, for each of seventeen countries, which local banks take subscriptions, whether you sign up as a sole trader or a company, and what we do with each, checked on the banks' own sites. And the two plans are one: Starter and Growth were sold by how many active customers you have, a number nothing counted and nobody knows before they start selling. Goose is now $30 a month, billed $300 a year, with everything in it and no limit on customers. If you paid for Starter or Growth, nothing changes for you until your term ends.
Jig takes several jobs at once, and shows you who is on what
A request made of independent parts used to be done one part at a time: ten pages to sweep meant ten passes in a row, and there was no faster way to ask for it, because the ability to split the work was simply absent. It now goes to three workers running at the same time, and nobody has to ask for that or know the word for it. Only genuinely independent parts are split, by page, by role, by form, by checklist item; one form, or a story that walks from step to step, stays with one worker, because splitting those gives two halves that contradict each other. Every worker that touches the page opens its own tab, so they cannot overwrite each other's clicks and read the damage as the application's answer. A dial in settings takes it down to one at a time or up to six. Alongside it there is a map: a row for every job that is running, with the task, the project, the tab and a ticking clock, a button that takes you into that conversation and one that stops just that job. Workers inside a single answer are listed under it without a stop button of their own, and the panel says why rather than offering one that does nothing: they live inside one engine, so what can be stopped is the whole answer.
Qiksy Pay is now Goose
Same product, new name and a new coat. Qiksy Pay sounded like a payment processor, and it is not one: the money goes through your own acquiring, and what we do is keep subscriptions renewing, chase a declined card and deliver the keys. So it is named after the goose that lays a golden egg every month. The old name was also one letter away from QikPay, a card-free POS for shops in the US, and we would rather nobody had to guess which one they found. The page was redrawn around the goose: payments fly into its egg on the first screen, it wears a scarf in the colours of your country, and a country picker beside the language one puts your own banks first and says plainly what works there today and what we would set up for you. Nothing on your side changes: the address is still qiksy.app/pay/, the console is still at /pay/admin, and the widget code on your site keeps working as it is.
The expiry wheel turns like an alarm clock
Putting in an expiry date used to mean a grid of months. It is one wheel now, the kind an iPhone alarm uses: it turns in a circle, so December is one notch from January instead of a scroll away. Three things about it were wrong and are fixed. It used to pick a date on its own when the scroll stopped halfway, which is how a pack gets a month nobody chose. An untouched wheel now looks untouched rather than showing a suggestion that reads as a decision, and refusing to accept a delivery without a date highlights the wheel and scrolls you to it instead of printing a complaint somewhere above. And a screen reader is told the whole date at once rather than a month in one place and a year in another, which is unreadable by ear. The same pass went over the phone itself: every small control, segment and colour dot is at least a 44 by 44 target; on Android the tab bar and the bottom buttons sit clear of the gesture strip; on iPhone the tab bar comes back after you leave a new product with Back; and in the till the search box rises above the keyboard so you can see what you found.
A whole shelf at once: mark down, write off, recount
Until now a shop with sixty products close to their date marked them down one at a time. Stock has a selection mode with bulk actions, the expiry list carries «Mark down all» and «Write off all» in the group heading rather than hunting per row, and a bulk price change rounds to the nearest sensible ending. A markdown sent to Shopify now goes as a percentage discount instead of a rewritten price, so the original price stays visible to the buyer; a product with no code is marked down in Shelf alone, and the Shopify step no longer sends the lines you cancelled. Counting the shelf is its own flow now, with a «counted 2 of 10» strip along the top so you can put the phone down and come back. The till got the matching end of it: anything out of date sits at the bottom of the list with a Write off button next to it. And the numbers stopped lying politely: where a batch has no purchase price, the header says so rather than printing «at cost: 0», and «no purchase price» or «date not checked» are small tags on the row instead of silence.
A declined renewal no longer quietly ends a subscription
A reader asked under our post what happens when a buyer's card expires in month three, and the honest answer was: we retried, but an expired card fails every retry and the buyer had no way to swap it. Now the email about a declined charge has a «pay with another card» button: the buyer pays the term with the new card on the merchant's own mono or Stripe, 3-D Secure included, and every renewal after that goes to it. A declined charge is retried four times over ten days, and access stays open the whole time. The merchant hears of the first decline (a past_due webhook and a mark in the console) and has nothing to do. A subscription that ran out of retries can be brought back the same way within 30 days, and a buyer whose card changed early can pay the next term with the new one ahead of time.
The merchant console signs in with Face ID, Google or Apple
The console used to open only with a long private key you pasted in, which people lose, forward in chats and cannot paste on a phone. Now it also opens with Face ID, Touch ID or a fingerprint (a passkey you add once in Settings), or with a Google or Apple account. A first sign-in through Google or Apple makes the shop by itself. The private key stays what your server checks access with, and getting a new one still locks a leaked key out.
A chat centre of its own, at qiksy.app/inbox
Answering from Telegram works, and it stops working at about the third customer at once: there are no states, no search, no way to see who is already on a conversation, so you answer the same person twice and lose another one entirely. Assist now has a workplace. People on the left, the conversation in the middle, the customer card on the right: status (open, snoozed, closed), tags, who is on it, notes only your team sees, saved replies, and a search that goes through the text of the conversations, not just names, because what you remember is «the one who asked about instalments». It installs on a phone as an icon and opens inside Telegram as well. Access is no longer one key for the whole business: the owner adds people by email and they sign in with Google, each with their own access that can be switched off without touching anyone else. Staff get customer messages on their own phone through Telegram and answer from there; whoever answers first is marked as handling it, so the rest stop being pinged. The owner also gets a summary: how many conversations and requests, how many are waiting right now, how long a reply actually takes (counted for humans separately from the assistant, which answers instantly and would otherwise flatter the number), and where people came from.
Jig 1.18.0: you talk to it now, and it knows when you are not talking to it
Jig could be dictated to before, but it behaved like a microphone button: you pressed, you spoke, you waited, and the answer was read out only once the model had finished writing all of it, so a long reply meant a long silence. It now speaks from its first finished sentence while the rest is still being written, and the wait between asking and hearing is filled by one card that says «right, doing that» and then grows into the answer rather than being replaced by it. The harder half is knowing when it is NOT being addressed: the ear stays open between turns, so a phrase said to a colleague used to become a task. Two rules decide instead of a model, instantly and the same way every time: the window being in front, or its name. Anything it decides is not for it goes nowhere at all, and a bar along the top of the window blinks once so silence is never mistaken for a dead microphone. How much it says out loud is a dial with three settings, and work that has stopped and is waiting for you is spoken at every one of them.
A code for your door, printed from the panel
Assist told owners to put a QR on the door and then handed them nothing to print, so they went to whatever generator the search turned up. Now the panel prints it: a sheet for the door, for the counter, for the window and a business card, each carrying its own tag, so a month later the panel can say which of them actually brings people. The page of a business got the repairs it needed for any of this to matter: it now speaks the language of its own form instead of calling itself Russian everywhere, it arrives in a messenger as a card rather than a grey line, it carries its address, hours and services in a form search engines read, and it has a Share button. The code is drawn by us, without sending the link to anybody else, and every size is checked by reading it back with a different decoder than the one that drew it.
A new Assist landing to try, at /assist/next/
The page opens on a craftsman's counter: scissors and a comb, a spray bottle, a phone lying among them with the booking page open on it. Six trades take turns, the phone stays put, and the panel beside the photograph takes its colour from that counter, so the two halves stop reading as two different pictures. Seven languages, and the translation goes all the way into the phone: the demo salon changes its name, address, price list, city and currency, because a price in one country's money gives a translation away as surely as the wrong alphabet. The live landing is untouched while this one is being tried.
A product card for anything a shop sells, from rings to brake pads
Jewellery, flowers and car parts are categories of their own now, each card asking in its own words: a ring its metal, size, stone, carats and certificate, a bouquet its colour and height, a part its number and the cars it fits. A shop's own category asks once what its goods are like. Every list shows a product the same way, its name first and its size and condition plainly, the search finds an IMEI or a part number, and a batch's date can be put right after it was received. Weighed goods sell by the kilogram on the storefront. Tested on Android and on three iPhones the way a newcomer goes: Back now steps back through the first screens instead of closing the app, and an unsaved card asks before its changes are lost.
Shelf counts the whole shop and what you owe suppliers
A stock-take in Stock lists every product: type what is on the shelf or scan item after item, and Shelf shows the shortage and the surplus in money, then corrects the stock in one go and hands you the report to send. The count survives the app being closed halfway. In the Report, a supplier who delivers on credit is marked once, and Shelf keeps what you owe from the deliveries, the returns and the payments you record. Weighed goods now show their price per kilo in every list.
Shelf opens on the sign-in, with a way on without it
A new phone, a reinstall or a seller signs in on the first screen and lands in the shop, without answering what the shelves hold every time. «Work without signing in» keeps the stock on this phone and asks two short questions; the e-mail is no longer asked again at the end.
Shelf sells by weight, counts the drawer and prints price labels
A product can now be sold by weight: the price is per kilo, the till reads a label scale's sticker with the weight in it, or the seller types the weight, and Webkassa gets the kilogram's unit code. At the end of the day the seller counts the cash and Shelf says whether the drawer is short or over; the owner sees earlier counts and who sold how much. Ticked products become a sheet of 24 price labels with their barcodes, a sale prints as a paper receipt for a 58 mm printer, and «Running low» sends the order to the supplier in Viber or Telegram with one tap.
Qiksy Shelf is free, and you pay only for the AI camera
Stock, receiving, expiry dates and their reminders, the till, reports and the sellers' phones are now free with no time limit, not for a trial month. The AI camera reads 200 photos a month for free, about 30 new products, and after that products go in by hand or with the barcode scanner. Smart, $10 a month, reads a shop's whole range. Fiscal receipts through Checkbox and Vchasno.Kasa are free too: the shop pays its register provider and nothing to us. We charge for the till only where it costs us money, in the EU, where the receipt signing is billed to us.
The Qiksy Pay checkout works on every kind of site
We put the checkout on every kind of site a shop runs: plain HTML and PHP, WordPress, React, Vue, Angular, Next.js, a site builder's HTML box, a strict security policy and a theme that styles everything. Buttons a site draws later are now styled and forms appear by themselves, the bank's page opens on the press itself, which is what Safari requires, and after paying the buyer comes back to the shop instead of our page. Inside a Wix or Google Sites box the checkout opens as a page of its own, and the console says where to paste the snippet on each platform.
Qiksy Facing has a page: shelf share for FMCG suppliers
qiksy.app/get-facing/ introduces Facing in 18 languages. The merchandiser photographs the shelf, Facing counts the brand's share against the chain's norm and checks the price tags against the recommended price and the promo plan, and the manager sees the same numbers in the office the same minute. It also reads a shelf shot at an angle along a narrow aisle. The app is in a closed test, so the page says coming soon.
The Qiksy Pay console and checkout speak seven languages
The merchant console now comes in German, Spanish, Portuguese and Polish as well as English, Russian and Ukrainian, the same seven as the Pay page. The checkout window your buyers see follows the language of your own site, or of their browser, and a data-lang attribute on the script tag can fix it. The buyer's key, refund and subscription letters and the page that cancels a subscription come in the language they paid in, a renewal a month later too. The console also lists every EU country for the Stripe beta now, sorted by name.
Qiksy Pay connects to Stripe in beta, and a merchant can delete their own account
Outside Ukraine a shop can now plug in its own Stripe account with a restricted key. The console lists every permission the key needs and checks the key before saving it. It is a beta: no live shop runs on it yet. Every shop now gets 30 days free, then new payments need a Starter or Growth plan, while subscriptions already running keep renewing either way. A merchant can delete their account from the console settings, and the buyer's mono wallet is keyed with a secret instead of a hash of their email.
Shelf closed eleven holes found by a security review
A seller can no longer swap the shop's bank or carry away the owner's register and bank keys: they stay in the server's vault. A deleted account cancels its card subscription and takes its storefront, orders and Shelf Line listings with it. A buyer can no longer set the price in a storefront order, junk orders can no longer hide the real ones, and three reports no longer hide a listing for good. Shopify staff keep the stock but not the owner's rights.
Shelf's till works with Vchasno.Kasa, and shows the shift so far
Shops in Ukraine can now connect Vchasno.Kasa as well as Checkbox: sales, returns and the Z-report, tried on a test register in Vchasno's own cabinet. Cash in and out of the drawer works with it too, and a new X-report button shows receipts, returns, cash and card for the shift without closing it.
The Assist widget now speaks German, Spanish, Polish and Portuguese
Seven languages instead of three. The widget picks one from the visitor's country, time zone or browser, and the owner can still fix it in the admin panel. Before this a visitor from Berlin or São Paulo met an English widget on a page that was already in their language.
The Qiksy Pay page shows where payments come from, and whether your country is supported
The new first screen is a map of payments arriving from abroad into a shop at home. Pick your country and it says straight away whether Qiksy Pay works there today or which acquirer comes next. The page moved to soft azure on flat colours, and the button styles and example sites below it use pastel shades. In the product catalog Qiksy Pay moved up to fourth and no longer says early access: you connect it yourself in the console. A link to any product page now previews in chats with its name and a fresh picture of the page. The checkout builder in the console also lets you pick the text colour on the pay button, and tells you straight away whether that colour is easy to read.
Qiksy Pay sells subscriptions that renew by themselves, and the checkout wears your colours
A plan can now be billed every month or every year. The first payment asks your own mono terminal to keep the buyer's card, and each renewal is charged with your own token a day before the term ends, so the money lands on your account exactly like the first payment did. The buyer gets a letter three days before every charge with a link to cancel, and a card refused three times stops the subscription. Your site hears about every payment, renewal and cancellation, and can ask at any moment whether an address has paid. The checkout widget also takes its colour, theme, corners and font per button, and the Pay page shows six of them live.
Jig 1.17.0: the keyboard walk is now a real one, and the manual half of an audit is written down
Jig could already list a page's tab order, but it COMPUTED that order from the markup and said so: it knew nothing of iframes. A payment form, a sign-in step and an embedded widget are separate documents, so the computed order looked tidy exactly where a keyboard user falls into someone else's frame and cannot get back. Now Tab is pressed for real and the focused frame itself is asked where focus landed, and what you get is the DIFFERENCE: a focus trap with no way out, a stop in a frame the computation never saw, a control the key never reached. The other half of the release is the craft: sixteen manual accessibility checks now sit in a table with their WCAG criterion and, for each, the known false alarm. A finding filed without a criterion gets one from that table, and is told plainly that the number was inferred from its wording rather than measured.
Qiksy Shelf takes several photos from the gallery at once
A product's «From the gallery» now lets you tick several pictures in one go. The first becomes the cover, the rest join the photos the storefront shows, and the slider puts them in order. It works on the phone that keeps the storefront, since that is where the extra photos live.
Qiksy Shelf storefronts open in albums, and every photo is a swipe away
A storefront now starts with its categories as circles, each with a photo and how many things are in it, then a shelf of each category to swipe sideways. Inside a category its groups (jackets, dresses) are chips, and the cards keep the shape of their photo: a dress shot upright stands tall, a sofa lies wide. A card's photos swipe right on the card, and a product's page frames its gallery by the first photo instead of cutting it square. Shelf Line has the same circles and groups. In the app a product has a subcategory, a tap on any of its photos opens them all full size, and one press makes any of them the cover. Opening a storefront now says how many products have no price and so are not on it, and «Share» opens the picture of the post first. The cross that removes a photo no longer reaches into the middle of it.
Jig 1.16.0: you can see which files changed, open one, and put the edits back
The branches sheet used to answer with a number, «12 unsaved files», and nothing more. It now names every file with its own word (edited, new, deleted, renamed), the lines added and removed, and marks the ones Jig itself touched. Press a name and the diff opens; from there the file opens in its own tab, or its edits go back to the last commit, one file or all of them. A revert takes a return point first, so «undo the revert» is right there, and a file git never knew goes to the Trash rather than nowhere. Faster, too: the kind of work a project is for now decides which verbs load, and a chat project costs a quarter of what it did per step.
Qiksy Shelf no longer offers sample goods to a real shop
A new shop could press «Load sample goods» on the empty till, and it got our sports nutrition and the shop name «Demo», which then went on to its storefront and its posts. The button is gone from the till and from Settings, and a shop that still has the sample loses it on the next start: the sample goods, their sales and the name «Demo» go, everything the shop added itself stays.
Qiksy Shelf's paid plan for receipts is called «Fiscal receipts», not «Till»
Every shop has the till, the sales screen, free. The plan sold on top of the stock adds one thing, fiscal receipts through the shop's own online register, and it was called «Till» too, so a shop could not tell what it would pay for. It is «Fiscal receipts» now in all 18 languages: in the app's subscription card and its notes at the till, on the prices of qiksy.app/get-shelf/, on the payment page and in the subscription letters. Nothing about the price, the free month or the plans already paid changes.
The tour on the Qiksy Shelf page shows today's app in all 18 languages
The screens on qiksy.app/get-shelf/ were shot again, for a shop with a till and for a Shopify store, so they show what changed today: the camera's five cells with «more» for the rest, the price right under the name on a new product, «Could be lost this week» on Dates, and «Without a selling price» in Stock. Every language now has the camera's middle frame, the one where it reads the label; seven had lost it.
A Qiksy Shelf sale is no longer lost to a reload in its first seconds
For fifteen seconds after «Cash» or «Card» a sale can still be undone, and in that time it lived only in the open page. A reload of the page, or a closed tab, in those seconds could leave the day without it: the till said «Today 0». The sale is now written down the moment it is paid, kept until the shelf itself is saved, and put through on the next start if it was not. A sale that did make it is never counted twice.
Qiksy Shelf's till gives a discount on one line and counts the change
Press the sum of a line in the sale and it opens this sale's price: five to twenty percent off in one tap, or any price typed in, and a way back to the full one. The price on the shelf stays as it was, the line carries its «−10%» tag, and the receipt shows the price as sold. A hired seller sells at the shelf price. A cash sale shows the notes a buyer is likely to hand over, 750, 800, 1 000 and 2 000 for a sale of 735.50, and one tap on the note shows the change in large figures while it is counted out.
Qiksy Shelf's report says what sells, what sits, and what the bin cost
The report names the five products that brought the most money in the period, with pieces and sum, returns taken off. Under them, for the owner, what has stood on the shelf thirty days without one sale and how much money is in it at purchase price, with a line on what to do: move it closer to the till, mark it down, or order less next time. The list of write-offs now has its total in the heading, and a return to the supplier is listed there but not counted as money lost.
Qiksy Shelf says, a week before the free month ends, what the month was worth
The first thing a shop used to feel of the subscription was receiving locked on day 31, with nothing before it. Now, from a week before the end, the till (or the stock, for a shop without one) shows one note: the date the free month ends, the money taken for batches sold near their date, how many batches came in, and how many sales went through the till and for how much, all from the shop's own month. It says what goes on afterwards and what will need the subscription. On the website a button opens the subscription; the store apps say the same without one. «Got it» puts the note away, and it comes back once in the last two days.
Qiksy Shelf's first run says how many steps are left and what it will cost
The three screens of a new shop are marked «Step 1 of 3» and so on. The first one asks what is on the shelves and now shows the answers right under the question, with the country and the currency after them, where before the cards began a screen further down. On the website the choice of how Shelf works says under each answer that the first month is free and what a month costs after it, so the price is not first met a month later. monobank in the till settings is one row, like the registers above it: the steps, the token and the test mode open when it is pressed. The camera reading a new product shows five cells instead of nine: the photo, the barcode, the name and the date have one each, and the rest share a wide cell that says how many of them are read and what, so no label is cut in half on a small phone.
Qiksy Shelf's settings are five sections instead of eight screens of cards
Settings opened on seventeen cards in a row, from the shop's name to the screen's contrast, and the one a person came for was usually far down. Now the first screen is five sections: Shop, Subscription and till, Selling online, Dates and reminders, Phone and data, each with a line saying what is inside, and each opens on its own. Sellers are named under Shop, where the cloud and the invitations live, and the invitation button says what a seller can and cannot do: sell, receive and recount, but no purchase prices, profit, month's reports, register or discounts. A button that leads to one setting, such as the till's «connect» or the report's taxes, opens its section directly, and Back returns to where it was pressed. Before the shop is in the cloud, the storefront, Prom and Rozetka share one card with a button to the cloud, in place of three cards that each said «turn it on above».
Qiksy Shelf says what is running low and how much to order, and its numbers mean what they say
Stock now has «Running low»: a product whose stock will not outlast the wait for a delivery is marked with how many days it lasts and how many to order. The speed comes from the last four weeks of sales, the order covers the wait and two weeks more, and the wait is set in Settings (a week unless changed). Next to it, «Without a selling price» lists what the till would have to ask about. Receiving shows the selling price right under the name and the purchase price without opening anything, and a product taken in without a price gets a button to set it. On Dates, «Could be lost» counts only what is expired or due within a week, the same colours mean the same thing on Dates and in Stock, and «saved» counts only what sold within a month of its date, not three months off it as a sports shop's 90 day warning used to allow. A return to the supplier is a line of its own in the report, no longer a loss. The camera says «The main things are read» instead of claiming every field is filled. Delete moved from beside Edit into the edit sheet, where the price is now at the top and Save stays at the bottom. The undo button counts its seconds down, and the cart's last piece has a minus, not a bin.
Qiksy Shelf's screens tell one story: a can of energy drink, from the camera to the shelf
The camera in the tour on qiksy.app/get-shelf/ used to look at a tub drawn on a page. Now it sees a can of energy drink held up in a sports nutrition shop, the whole can in the frame, with the brand, the barcode and the best before date on one label, and reads all of it in one go. The screens then follow that same can: the card it filled, «Received 1 pc» at the top of the shop's list, the can found on the shelf by its brand. The Google Play page shows the same story in eight screens, in place of five tabs in a row.
The Qiksy Shelf page shows today's app, and says how a paid plan goes on
The tour of the app on qiksy.app/get-shelf/ was shot again in all 18 languages, for a shop with a till and for a Shopify store: receiving now shows «Don't accept» and the camera's «hold still». The Turkish page had borrowed the English screens and now has its own. Under the prices the page says that a paid plan renews itself by card, with a letter three days before each charge, that it can be cancelled any time, and that a year at once is $100. A shop's own page with Instagram posts made from the stock is named among what Shelf does. The picture a shared link shows was from the first week and still said «Coming to Google Play»; it is the current page now.
Qiksy Shelf: subscription letters come in the language you use the app in
The letters about a Shelf subscription (it is on, it renews in three days, it renewed, the card was refused, it is cancelled) were written in Ukrainian, Russian or English, picked by the country the card paid from, so a shop in Warsaw would have read them in English. Now the app passes its own language at checkout, and every letter and the page their button opens speak it, in all 18 languages Shelf has. A yearly plan's page also says «a year» now, where it said «a month».
Qiksy Shelf renews itself, and stopping it is one tap
A Shelf plan used to be a month bought by hand, and every month a shop had to come back and pay again. Now the first payment keeps the card with the bank, monobank, and the plan renews a day before its term ends, for the same shop it was paid for. A letter comes three days before every charge, and a receipt after it. A card that is refused is tried twice more over a week before the subscription stops, and the paid term always runs to its end. Cancelling is one tap in the app or in any of the letters, and a refund cancels it as well. The checkout says all of this above the pay button. We tested it on real money: a payment, a charge with nobody at the screen, a cancel and two refunds.
Qiksy Shelf: paying for a plan says what you get, and Shopify is matched the moment it is linked
The checkout for a Shelf plan asked for an «email for your key» and promised a key on the screen, and the bank line read «Shelf Pro, licence, key by email». Shelf has no key: the plan switches on for the shop you sign in to. The page now asks for that address, the bank line names the plan, and a letter confirms what was switched on and until when. A refund made inside the free month also puts the shop back on its free month, where the app used to say «paid until» the month's last day. And when a Shopify store is linked, the comparison of the shelf's stock with the store opens by itself, once, with «Write to Shopify» and «Not now», instead of a button to find in the settings.
Qiksy Shelf: the till gets a free month of its own, and the camera says «hold still»
A till added to a shop that has worked for months now starts with its own free month, counted from the day its register is connected. That holds where the register is the shop's own account, as Checkbox and Vchasno are in Ukraine; under our fiskaly contract the till is still paid from its first day, because it costs us from the first day. The smart camera now answers the hand: a moving view turns the frame amber with «Hold still», and a still one fills a ring with «Good, hold it there», since the camera reads a view that stands still. A product a scan opened can be turned away with a red «Don't accept» beside «Accept», and brought back for fifteen seconds. «Select» on Stock now offers «Share» beside the bin, so ticked products become a post's picture in any shop, the storefront opened on the way where there is none. A card's «Save» waits for a change. And someone who picks «Stock with till» and then signs in to a shop that only kept stock is asked whether to add the till, instead of losing the choice without a word.
Qiksy Shelf: five Shopify stores under one owner, each with its own stock
We set up five test Shopify stores under one owner and went through the whole way on each. Three things were wrong and are fixed. A stock begun in the Shopify admin had no name, so «My shops» listed «Shop 1» to «Shop 5»: it now takes the store's own name. The admin of a new store offered to take over, in one tap, a stock another store was already linked to: such a stock is no longer offered, and the server refuses the takeover. And every store opened in one browser shared one Shelf storage, so two admins in two tabs would have written into the same place: each store now keeps its own.
Qiksy Shelf speaks the language of what the shop sells
A product's category now brings its own examples into the empty fields: jeans and a size in a clothes shop, dry cat food in a pet shop, whey protein in a sports shop, where pasteurised milk used to stand in all of them. The category list shows what the shop said it sells, with «Show all categories» one tap away, and a new product is filed by that answer rather than by whatever the shelf held before. A shop whose goods keep no date is no longer promised expiry dates and lots on its first screens. Texts across the app now say what a thing is for: the delivery note and the purchase price lost their «optional», and the purchase price says it is what the report counts profit from.
Qiksy Shelf: several shops under one sign-in, and a Shopify store linked with one tap
One email can now keep several shops, each with its own stock and its own plan; the free month is one per account. The shop's name at the top of every screen opens «My shops»: a card per shop with its logo or colour, the role, how it is paid, and «New shop». Signing in to several shops asks which one to open before anything loads, and goes back to the one the phone held. A switch first sends up what the phone has not sent, and waits while a receipt is open or not printed. In the Shopify admin, the store's owner whose address Shopify has verified links the store to their own stock with one tap and no code, and a stock begun in the admin belongs to them as well. A store with several locations picks which one is the shelf. Morning date reminders name every shop on the phone. Write-offs reach Shopify with their reason, damaged or shrinkage, which a real store's adjustment history now shows.
Qiksy Shelf reads the supplier's delivery note and lays its prices on the goods
Receive has a card for the delivery note: photograph it, several pages if needed, and Shelf reads every goods line with its pieces and the price of one piece, boxes turned into pieces where the box size is printed. Photographed first, each product scanned after it finds its line, and the pieces, the price and the supplier fill in by themselves, all still yours to change; a line tapped opens its product. Photographed after the goods, it offers to set their prices in one tap. The card ticks off what has come in, and typing the price by hand works as before.
Qiksy Shelf: every rounded number now adds up to the total it sits under
A pass over the arithmetic itself. Tax lines are rounded to the kopeck and the total is their sum; a break-even day no longer shows a red «−0,00»; the storefront keeps a price's kopecks (42,90 ₴, not 43 ₴); markdown buttons save exactly the percent they name, and ones that would take nothing off are gone. In Germany the export for the tax office takes VAT per rate, the way the receipt does, and a return's VAT is the sale's with a minus. Typed sums read «0.500» as a half and full-width digits as digits, and a price the edit sheet cannot read is said so instead of being dropped. A storefront order waits on the till until its buyer comes; the seller taps cash or card there, the register issues the receipt at that moment, the money shows in the drawer or on the terminal, and such an order can be returned over the counter. A VAT payer can say purchase prices are entered without VAT. Thousands of random runs over months then checked that every screen agrees with every other: removing the demo no longer leaves a batch laid out by dates behind, a consignor assigned later does not get earlier sales, and taking back a write-off from last month leaves last month as it was.
Qiksy Shelf: the numbers checked against each other, and the ones that disagreed fixed
Two passes read Shelf the way a bookkeeper would, screen against screen. Online orders are now booked at the price the buyer paid, and the Report keeps them apart from cash and card, so the evening check against the terminal comes out right; the till's «Today» takes cancelled online orders off as the Report does. The month's balance counts a batch sold below zero, recounts in the spreadsheet, and batches split by date and priced later, so each month closes where the next one opens. German VAT is worked out at each product's own rate and income tax from the money without it; the Ukrainian 3% group shows its ПДВ and takes 3% of the net. A consignor keeps the share a thing sold at, and a payout made on one phone is no longer lost when another phone saves. The Polish 20 000 zł counter counts the till's own sales less returns.
Qiksy Shelf: one price per batch everywhere, and a report warning you can clear
A marked-down batch now sells at the lowest of its markdown, the product's price and the time-on-shelf discount, so cutting a product's price can no longer leave an old batch dearer than a fresh one, and Stock shows the markdown on the batch. The report's «batches without a purchase price» warning lists those batches and opens each one's price, sold-out ones included. A batch two phones sold below zero is shown in Stock with a recount instead of a count that did not add up. In a shop linked to Shopify, a write-off taken back no longer stays in the report as a loss plus a surplus, and the first import no longer counts as a delivery. Smaller words: «On the shelf» over the till's quick picks before the first sale, «Accept and leave» when leaving Receive, «Remove demo goods», and the Dates sum says it is at purchase price.
Qiksy Shelf: Receive no longer reads as if stocked goods were never accepted
The list under the scan button was titled like a queue of goods waiting to be accepted, while the same goods already sat in Stock. It is now «Accept again»: each row shows how many are on the shelf and when the last delivery came, and the button says «Accept 1 more». A deleted product no longer shows up there, and accepting it again brings it back. Goods in a shop without expiry dates are no longer flagged as expired at the till or on the Dates tab. The purchase price field now says it is per piece, and the delete warning says plainly that sales stay and the write-off shows in the report.
Qiksy Shelf: «Accept» no longer sits on a delivery's purchase price
A delivery opened in its row on Receive, the last one in the list, had its «Accept» button lifted over the purchase price and supplier, with an empty gap under it: the list clipped its corners, and to a button that follows the screen down that made the list itself the screen. The list now lets go while a delivery is open in it. Every tab and Settings were checked on an Android phone for anything left under a floating bar at the end of the page; nothing else was. Then every screen and every opened card was walked through by eye: «Recount» now names the batch code beside its date, as the purchase price does. The Google Play listing shows Shelf in a phone now, and its banner keeps the name and logo in the middle.
Qiksy Shelf 1.5 for Android is out in Google Play
Google approved Shelf 1.5 and it is published to everyone in the countries the app is offered in. The Shelf page now links to it instead of saying it is coming, in each of its 18 languages, and the Ukrainian header no longer carried a Russian line there.
Qiksy Shelf checked on a 320px phone, in Ukrainian and German
Every tab, Settings and every list in them were walked on an Android phone at 411, 360 and 320 pixels wide, and the opened product with its sheets and the new product form at 411 and 320, with a check that nothing sticks out past the screen or out of its box. Two things did, at 320 only: the storefront colours in Settings, which now give way a little instead of running past the edge, and a list opened upwards near the top, which scrolled the page along with itself to reach the chosen row and slid a pixel off the screen. A list now scrolls only itself. On a phone every button standing alone is now as wide as its box, «Product without a barcode» included, and a choice of chips stands in equal columns: two for short answers like the write-off reasons, one for what the shop sells. The Shelf page's footer links to qiksy.app.
Qiksy Shelf: a tidier product card, and lists that stay on the screen
An opened product in Stock now holds its stock: the batches with «Recount», «Write off» and the purchase price, then «Edit» and «Delete» side by side at the foot, as the swipe shows them. Name, fields, photos, category and price are changed together in «Edit», in the order Receive asks for them, and a shop's own categories are made in Settings, which now shows them to shops without expiry dates too. The opened card's frame lies on the list's own edge instead of inside it. A list opened in a field is the field's width with long rows on two lines, turns upwards when the tab bar is close, and the screen no longer slides sideways after it. A row being swiped stays solid instead of turning see-through.
Qiksy Shelf: delete any product, one or many at once
A product in Stock swiped left shows «Edit» and «Delete», as the phone's own lists do, and an opened one has «Delete product» beside «Edit the card». «Select» on the list's heading ticks several and deletes them together, for a run of wrong shots after receiving things in a stream. What is left of a deleted product is written off as «Product deleted», so the counts and the money still add up, and its sales stay in the reports. «Put back» undoes it for fifteen seconds, and a barcode scanned later starts a new card.
Qiksy Shelf: the camera says when it takes the product photo, and ticks when the card is filled
A new card starts with the product photo: the hint asks for it, its cell is lit, and the frame flashes like a shutter when it is taken; a tap on the cell takes it or takes it again. When every field is filled, a green tick shows over the frame before the card opens. Receiving used things in a stream takes a new shot only after a hand has moved in the frame, so a still table is no longer photographed again and again, and the price list after it shows every thing whole, with a note while the AI is still naming one. «Accept» stays at the foot of a new product's screen from the start, and the buttons that throw work away are terracotta.
Qiksy Shelf cameras get 0.5, 1 and 1.5
The cameras that photograph goods have three steps at the foot of the frame, as on the phone's own camera: 0.5 for the wide lens where the phone has one, 1, and 1.5 a step closer. Every camera opens at 1, and the step that is on is lit in amber. What the camera reads is what the frame shows at that step.
Qiksy Shelf: safer invites, sign-ins and payment settings
An invite link now keeps its code in the part of the address a browser never sends anywhere, so it no longer lands in server logs or in a messenger's link preview; links made before still open. Only the shop's owner can change its name, its register and its payment settings. Face ID is added only right after a sign-in, and «Sign out everywhere» no longer counts as a fresh sign-in. The app takes updates of its screens only from our own address, with a checksum.
Qiksy Shelf: pictures on the first screens, and a deeper navy dark theme
The first question, what the shop sells, now shows a picture for each answer: a basket of groceries, a hoodie with trainers, a toolbox, a teddy bear, each on its own pastel square, the same in both themes. The two ways Shelf can work, a shop with a till or a stock room, have pictures of the same kind, and Settings shows the small ones beside each kind of goods. The dark theme leans further into the header's navy. Deleting an account can now be confirmed with Google or Apple, with the code by e-mail kept as the other way, and starting over after a Google sign-in goes back through Google instead of asking for a code.
Qiksy Shelf: a seller joins by the owner's QR, with just a name
The owner shows the QR from Settings, the seller points a phone at it, types a name and the stock opens. No e-mail, no code, no account of their own. The Shelf app reads the QR with its own camera too. The owner sees that phone by the seller's name among the members and takes it out with one tap; a phone that signs out needs a new QR. Sellers who want the same stock on several phones still sign in with an e-mail, Google or Apple. The first screen now says «Second-hand and used tech», since phones and laptops have the fields they need: model, spec, colour, IMEI and condition.
Qiksy Shelf: a wider lens, and a card with the fields the thing has
The cameras that photograph goods have a 0.5× button on phones with a wide lens, so a pair of shorts laid on the floor fits without holding the phone high. A product card now shows the fields that hold something, one to a row, and «Add a field» brings any other: a barcode with its scanner, a colour, a material, an IMEI, the condition, or a field the shop names itself. Stock has «Edit the card» for adding one later. The camera reads a device's colour, a garment's fabric and a phone's IMEI, and stops asking for a barcode when it sees the goods with no box or tag at all.
Qiksy Shelf: signing in opens your stock on any phone
A shop in the cloud used to ask for its recovery key on every new phone, even right after signing in with Google or Apple. Now we keep that key on our server, sealed with a key of its own for each shop, and any sign-in opens the stock at once. The recovery key stays in the settings as a spare. A phone that is used stays signed in, since the session renews itself, and it ends after half a year of silence. The privacy policy now says plainly that we hold the key and so can open the stock.
Qiksy Shelf: light by default, a cooler page, and copy that says it copied
Shelf now opens in the light theme until you pick dark or «as on the phone» in its settings. The page behind the cards is a light blue grey that goes with the navy header, instead of a warm paper that read brown beside it. Copy and Share became two tiles with their marks, and a copied key or link turns its tile green with a tick for a moment. The button at the foot of the first screens sits as high as the tab bar does.
Qiksy Shelf: sign in with Google or Apple
On the website, Shelf's cloud now opens with «Continue with Apple» or «Continue with Google», next to the code by email. It is the same account either way: an address that already has a shop lands in that shop, and a seller's invite works as before. A hidden Apple address gets its mail too. The phone apps get the two buttons with their next versions.
Qiksy Shelf: the feed has its own tab, and open pages update by themselves
In Turkey, where Shelf Line is open, the feed is now a tab at the bottom of the app instead of a button deep in the settings. A shop page and the feed that are already open now change the moment the owner sells something, brings in something new or changes a price: the sold piece leaves the page and the buyer's pick, the new one arrives, without reloading. An order being filled in is never redrawn under the buyer's fingers.
Qiksy Shelf: the sign-in code waits for you while you fetch it from Mail
In the iPhone and Android apps, going to Mail for the sign-in code could bring you back to another screen with no field for the code: the app put in its newest screens the moment it went to the background. New screens now go in only when the app starts, and a code that is on its way keeps its field for a quarter of an hour, even if the phone restarts the app meanwhile.
Qiksy Shelf: 500 recognitions of used things a month, and «Shelf» under the Android icon
A shop now has 500 recognitions of used things a month: the AI naming a thing, its condition and what such a thing usually goes for. The stream camera shows how many are left once fewer than 50 remain, and when they run out it keeps taking the photos and leaves the names to be typed. Reading packages is not counted. The Android app 1.3 is on its way through Google Play review and is called simply «Shelf» on the home screen.
Qiksy Shelf: a wrong shot of the stream leaves no trace on Stock
When the stream camera took something that is not a thing to sell, «Not a thing, remove» wrote it off but left a «0 pcs» row on Stock for good. It now leaves every list and stays only in the history, where the report names it «Wrong shot» instead of an internal code.
Qiksy Shelf gets a new coat: warm paper, the shop's own colour, and posts that sell
The app now sits on a warm light paper by day and a soft graphite by night, with a breath of the shop's colour in both. That colour is picked once in Settings, from twelve shades, and the storefront and its posts wear it too. A post's product photos now fill their tiles, prices are larger, a marked-down piece shows its old price and the percent off, and the feed post points to the link in the profile instead of a QR code nobody can scan from the same phone. A storefront's product page shows the size and the condition, its photos are swiped with a finger, and «Buy» and «Ask on WhatsApp» stay at the foot of the screen. Shelf Line got a tidier first screen, a heart to keep a thing for later, and the report moved to the thing's own page. On Stock, a post is made from the list's own heading, and the cameras keep one row of buttons and say what is wrong in big letters.
Qiksy Shelf speaks Turkish, and Shelf Line opens in Turkey
Shelf now works in Turkish and knows Turkey: prices in lira, product cards written in Turkish, and the receipt left to the shop's own certified register, as the law there asks. Shelf Line is new: one feed of what the storefronts of a country have on their shelves right now, open first in Turkey at qiksy.app/line. A thing sold leaves the feed at once, a buyer orders on the shop's own page, and a shop can leave the feed with one tick. A storefront can also show a WhatsApp button, the way most buyers there write to a shop.
Qiksy Shelf for second-hand and consignment shops
A sack of used things can now be taken in one after another: lay each under the phone, the camera takes it by itself, and the AI names it in the background and suggests what such a thing usually goes for. Then one list to put the prices in. A shop can mark things down by their time on the shelf, 30% after two weeks and 50% after four by default; the till and the storefront follow, with the old price struck through. A consignment shop marks whose a thing is and that person's share, and the report says what is owed to each.
Qiksy Shelf posts: more settings for those who want them
The picture for Instagram stays as designed, and under it «More settings» opens the finer choices: a grid or one main product, the font, the background (the shop's colour, dark, light or your own photo), a sticker such as «New» or «Sale», what to show, and how each product photo is framed. The product photos themselves can be put in order and any of them made the main one.
Qiksy Shelf: a camera that walks round a second-hand thing
A used jacket is bought by its back, its label and its scuffs, and one photo shows none of them. The new camera asks for one side at a time: the front, the back, the label, the flaws up close. It checks the light, the glare and the shake on the phone and takes the shot by itself once the frame holds still, since one hand is busy with the thing. The first frame is read once to tell what the thing is, its brand, colour, condition and visible flaws, and the card fills itself. The smart camera for packages got the same thrift: a blurred frame or the same view again no longer goes to the AI.
Qiksy Shelf storefront: ten photos a product, and a post picked right from Stock
A product on the storefront now shows up to ten photos, each kept small enough that a whole shop stays light, and its own page shows its description with the condition and the flaws. A post for Instagram or Telegram is made from Stock: tick up to four products and the picture is ready. The shop's logo now stands by its name on the post, and the coloured boxes that stood in for a missing logo are gone from the page.
Qiksy Shelf is on Google Play, and a fresh install opens on the newest screens
Qiksy Shelf can now be installed from Google Play. The app takes its screens from the site, and a phone used to show the newest ones only from the second start. A fresh install that has not been touched yet now switches to them at once, so the first look is the current one.
Qiksy Shelf reads a barcode only inside the aiming frame
The camera used to take a barcode from anywhere in its view, so a pack lying beside the one in the hand could be sold or counted. Now only the part of the picture inside the frame is read: at the till, when a delivery is counted by scanning, and in the smart camera.
Qiksy Shelf shows how it is used, in pictures, and a lost recovery key is no longer a dead end
The first screen and Settings now open «How to use Shelf»: the app's own screens one at a time, each saying what to tap and what to type, in all seventeen languages. A shop with a till, a stock room and a Shopify store each see their own steps. The first screen also shows the shop's country and money, the country guessed from the phone and changed with one tap, so the first product card comes out in the right language and the first price in the right money. Signing in with an email that already had a shop used to ask for its recovery key and offer nothing else. That screen now says where the key can be found, lets the owner start a new shop instead after a warning that the old one will be deleted, or take another email.
Signing out of Qiksy Shelf on a phone forgets the storefront and the Shopify link too
A phone signed out of one shop kept that shop's waiting storefront order, with the buyer's phone number, and the next shop on the phone saw it. Signing out now clears the storefront and the Shopify link along with the stock. On the first screen, «Next» stays at the bottom edge while the tiles scroll under it, and so do «Return» under a long receipt and «Apply» under a long list of stock to sync with Shopify, Prom or Rozetka.
A new Qiksy Shelf shop starts with an email, so its stock is never only on one phone
After «What is on your shelves?» and «How will Shelf work for you?» comes one more screen: «One last step: your email». Sign in with a code from the email, keep the recovery key, and the shop opens by itself. The step can be skipped, and Shelf still works on the phone alone. The cloud card now says what it means in plain words: only you can see your stock, and not even we can look into it. A shop with no till is reminded of an unsaved key over its stock, and is no longer offered the Till plan.
Qiksy Shelf finds what the camera received, and explains the recovery key in plain words
A product received with the smart camera could be missing at the till. The camera sometimes took the digits printed under the barcode, read by AI, before the phone had decoded the bars, and one misread digit made a product the till never found. Such a reading is now checked against the barcode's own check digit, and a wrong one is dropped. «Save the key» on the till opens the recovery key right there, says in plain words what the key is for and where to keep it, and the Copy button shows that it copied. The language menu in the header wears Shelf's colours, and neither the first screen nor the receiving form above the keyboard ends in an empty band any more.
The Qiksy Shelf page says how a Shopify store connects
The Shopify half of qiksy.app/get-shelf now has «How to connect» in three steps, in the words of the buttons the store will see: add the app from the Shopify App Store, start in the admin or link the phone with a QR code, then receive with the camera. No code goes into the theme.
A Qiksy Shelf shop on Shopify no longer sees anything of a till
The report of a shop selling through Shopify no longer splits its takings into cash and card or counts receipts, and its Subscription no longer offers the till or mentions fiscal receipts. The country's hint no longer speaks of registers and banks, and «How Shelf works» with its «Stock with a till» is gone from such a shop's Settings on the phone too. Orders from the Shopify store still count in the takings, the profit and the taxes.
Qiksy Shelf inside Shopify no longer offers other marketplaces, and posts have their own card
A shop that sells through Shopify, and Shelf opened in the Shopify admin, no longer show the Prom.ua and Rozetka cards: the store already is the place it sells. A marketplace linked before the store stays on the phone, so it can still be disconnected. «A post for social networks» moved out of the online store and storefront cards into a card of its own in Settings, with a line on what it makes.
Qiksy Shelf pictures for social networks get a new look
A post, a story and the preview under a shop's link now stand on the shop's own colour, with its name large in white, the products on white tiles with the price as a tag on each photo, and a white ticket with the QR code at the foot. A story keeps the same margins as a post. In the post window the title and the Share button stay in place while the rest scrolls, the window follows the dark theme, and a post with no product picked cannot be shared.
Social posts and the storefront cover work in Qiksy Shelf on the web
Opened at qiksy.app/shelf, the post window showed a broken picture instead of the post, and a cover or logo picked for the storefront was quietly not taken. The site's security rules did not let the page show a picture it had just drawn itself. The phone apps were not affected.
Jig 1.15.0: the first minute says what it is doing, and the window speaks your language
A first question used to look like a hang: Jig was fetching its engine, some three hundred megabytes, and the only thing on screen was the word «working». The live line now carries the megabytes, and it shows up whenever the engine itself says it is thinking, not only when the window thinks so. The offer to pick a project folder no longer jumps in front of the answer: it rides at the foot of the answer that explains why a folder is wanted, and it goes quiet once a folder is there. Steps are named in words in every surface that shows them, so «select:mcp__bench__project_list» reads as «reading the list of projects» in all seven languages. The undo buttons for Jig's own edits appear on the first real edit rather than at the start of every run, so a plain question stays a plain question. The profession funnel now rises when work actually begins — a folder pulled in, a page acted on, a finding written down — and stays out of the way of general questions. And until a language is chosen by hand, the window follows the one you write in.
A shop connected to Shopify draws social posts that lead to its own Shopify store
A shop that sells through Shopify has no Qiksy storefront, because its buyers order on the Shopify site. Its Shopify card in Settings now has «A post for social networks» too: the same pictures for a feed or a story, with a QR code that opens the Shopify store. A post with one product opens that product's page with the right variant picked. Only products that are on the store's website can go on a post.
Every product in a Qiksy Shelf storefront has its own page, and the shop sets how its page looks
A product's page shows its photo large, the price and a Buy button that goes straight to the order, with the rest of the shop below. A post with one product now leads there by its QR code. In Settings, «Storefront look» shows the real page as buyers see it and changes it as you go: a cover photo and a logo, a line about the shop, the address and hours, Call, Instagram and Telegram buttons, a light or dark page, and products as tiles or a list.
The Qiksy Shelf storefront gets a short address and pictures for social networks
A shop's storefront now opens at qiksy.app/s/ and its name, short enough for an Instagram profile. Sent in Telegram, Facebook or LinkedIn, the link shows a picture of the shop with its products and prices, and a product's own link shows that product. From Settings the owner draws a post for a feed or a story: the shop's name, a line of their own, up to four products, a QR code and the address, ready for the share menu. The shop picks one of six colours for its page and its pictures.
Qiksy Shelf for iPhone is with Apple's review
We ran the whole app on an iPhone simulator before sending it, and fixed what came up. Expiry reminders now arrive on their own day instead of all at once, a card with a text field stays above the keyboard, and the first screens open at the top after the account is deleted. The Prom and Rozetka cards stay off the store apps until we have checked them on live shops.
Sharper photos on the Qiksy Shelf storefront, and a picture pastes straight in
The storefront now shows product photos at 480 px instead of 160, so they stay sharp on a buyer's phone. A picture copied on any website goes into a product with the new Paste button, without saving it to the phone first. And the category list in a product's card now opens over the card instead of being cut at its edge.
Qiksy Shelf opens a storefront for your shop
A shop in the cloud can now open a public page of what is on its shelf, with prices and photos, and share its link or show it as a QR code at the counter. Buyers pick, send the pick to a friend or order it. The order is sealed in the buyer's browser, so only the shop's phones can read it. It waits at the top of Settings with its number on the gear: accept it and the goods come off the shelf, or decline it. The page follows the shelf by itself. The first screen now asks what you sell with a grid of colour cards.
The till in Qiksy Shelf keeps every receipt in view
When a fiscal receipt does not go through, the sale now shows it with two buttons: send it again, or mark that you printed it on your own register. The till warns before a sale when there is no connection, and keeps working for seven days after its plan runs out. The evening report gains the day's closing and a Dates card with what sold in time and what was lost, and a batch close to its date can be marked down right from Dates.
Qiksy Shelf has sounds, and a delivery opens right in the list
Shelf now makes short sounds: a code taken at the till, a code it does not know, each field the smart camera reads (a little higher every time, so you hear the card fill up), a finished card and a sale. They were made with ElevenLabs, play at half volume and can be switched off in Settings, under Screen. On Receiving, a product from the recent deliveries or the search opens its delivery right in its row, the way a product opens in Stock, and the next one you pick takes its place. Every card that opens now comes to the middle of the screen with a short animation. The smart camera panel is one compact card with the card language and the Done button in a single row, the scan tile sits on the header on every screen, the till shows barcode bars instead of stars, the search box is a card like the rest, and the buttons in the dark theme are a deeper blue. Questions such as «Save the delivery?» now have the same buttons as every other screen, focus frames are the buttons' blue, and a product sent to Shopify no longer repeats its brand, flavor and size in its name.
Qiksy Shelf reads what is inside the frame, and every screen is calmer
The smart camera now reads only what is inside its frame, so a jar standing next to the one you aim at no longer lends the card its name. The hint and the Done button moved down into the panel, and the frame runs from the top of the screen to the panel, so nothing covers the picture, even with long names. It also waits a moment longer for the size and colour of a garment, the model of a device and the author of a book. It takes the product's barcode, never a phone's IMEI, a link in a QR code or the serial number on a medicine pack. A cream gets a shade or scent field instead of a flavour, and a medicine gets its strength and pack size. The till is one column, as wide as every other screen. Expiry labels have four clear colours. An opened product in Stock stands out as its own card, write-off reasons are proper radio buttons, and buttons are a step lighter than the header. Inside the Shopify admin, Shelf keeps a narrower column, and a shop linked to a Shopify store sells through Shopify.
Higher contrast in Qiksy Shelf
Settings now have a Screen card with a higher contrast switch: darker grey text, firm edges on fields, cards and buttons, underlined links and a solid focus ring, in the light and the dark theme. It turns on by itself when the phone already asks for more contrast. Every main screen of the app was checked with axe in both themes and has no contrast or labelling errors left. The landing shows the app in its new colours.
Qiksy Shelf sells the till apart from the stock
Stock and the till are now sold separately, $10 a month each or $100 a year. The free month covers Stock; fiscal receipts start once the till is paid, from that day. The register account itself, Checkbox in Ukraine, stays the shop's own and is paid to Checkbox. Shops that paid for the old Stock and till plan keep both until the end of what they paid for. The app also looks calmer: the header and the buttons share one colour in both themes, there are two kinds of button instead of three, and a field says in red what is wrong with it.
Household appliances get their own category in Qiksy Shelf
An iron, a kettle or a vacuum cleaner is now filed under household appliances, apart from phones and electronics, and goes to Shopify as Household Appliances rather than Electronics. The camera recognises one out of its box too, as it would come into a second-hand shop: the kind of device, the brand and the model from what is printed on it. A second-hand shop now sees appliances, electronics and toys at the top of its categories.
Qiksy Shelf works for any shop now, not only food
Clothes, shoes, electronics, household goods, toys and books keep no expiry date, so Shelf no longer asks for one: such goods are received with a quantity only, and the Dates tab appears once something with a date is on the shelf. A new shop starts by saying what it sells, and its categories come first. The camera files a book by its ISBN and looks it up in Open Library, is asked for sizes and colours on clothing tags and for the model on a phone's box, and no longer takes a phone's IMEI for the product barcode. A product sent to Shopify now carries Shopify's own category.
Qiksy Shelf: returns and the end of the day at the till, and a year for the price of ten months
With a Checkbox register in Ukraine the till now sends the receipt to the buyer by link or e-mail, takes goods back with a return receipt, closes the shift with a Z-report and records cash put in or taken out. Stock is $10 a month and stock with the till is $20, and paying for a year gives twelve months for the price of ten.
Jig 1.14.0: a request that answers 200 and fails anyway is no longer invisible
Most failures in a web application arrive with a green status code. The server answers 200 and the body says the order did not go through, so the tester sees an error on screen, a healthy looking network log, and has nothing to show for it. Jig now keeps the body of such a response, and only of such a response: an application request, parsed JSON, under 32 KB. Images, fonts, scripts and documents are left alone, which is almost the whole weight of a page, so reading the network does not slow down the thing being measured. The project survey had a quieter version of the same fault: it capped each folder at forty entries before discarding node_modules and dist, so on one real repository sixteen folders were never looked at and the report said nothing about it. It now counts what it skipped and says so. And the work journal carries the commit the work was done on, written as a marker when the build changes rather than on every line, so a report can finally answer whether a change was checked by a human on this version or on the one before.
Qiksy Shelf: sign out on every other phone, and take back what a removed seller broke
If a phone is lost, one button in the cloud settings signs it out along with every other device, and unsent sales on them are kept. An owner who removes a seller can also take back what that seller deleted or changed in the last 7 days, while the sales they made stay. An invitation now shows whose shop it is before you join, a Shopify link asks before it connects a store, and deleting the account asks for a code first. In the web version today; the Android app gets it with its next update.
Qiksy Shelf: a seller who leaves no longer takes the register and bank keys along
A shop in the cloud now keeps its register and bank keys on our server, encrypted, instead of on every seller's phone. Each till uses them for its sales without ever receiving them, and only the owner can connect, change or remove them. Keys already on the owner's phone move there by themselves with the next sync. A shop on one phone keeps them on that phone, as before.
Qiksy Shelf after a security review: the camera's AI and the sign-in mail can no longer be worn out by strangers
A shop in the cloud now reads labels from its own daily allowance, so nobody outside it can use up the AI for everyone, and sign-in codes are limited per network and per hour. The Android app no longer copies its data to a phone backup, erasing a phone also disconnects its register and bank, and the privacy page now names every service a scan or a receipt passes through.
Qiksy Shelf after a second round with eight sellers: fewer taps at the till and in receiving
A scan made while the last sale can still be undone no longer sells from a batch that is already gone. The undo lasts 15 seconds with a countdown, today's total counts the sale at once, and both pay buttons show the sum. Scans that arrive while a date is being picked wait in a queue the screen shows, and scanning the same product again picks the oldest batch. A quantity can be typed into a sale line, a removed line comes back from a note above the pay buttons, and the first tap on a search result works with the keyboard open. In receiving, the accept button stays out of the way until the batch is complete, Back asks before dropping what was entered, and a product received from the till goes back to the same sale. Counting stock by scanning counts the first scan, and windows close with a cross.
Qiksy Shelf opens in the language of the shop's country and takes the shop's own categories
The app and qiksy.app/get-shelf/ pick the language from the country the visitor is in, and it can still be changed. A shop can add its own category with its own warning window. The settings have a section to check that a barcode scanner works, and lists such as the category and the country open the app's own list instead of the phone's wheel.
Qiksy Shelf warns about an expiry date as early as the product needs
The warning window now follows the kind of product: three days for fresh food, ten for chilled, a month for groceries, drinks and frozen, two months for baby and pet food, three months for sports nutrition and cosmetics, half a year for pharmacy. Each window can be changed in the settings, and the AI suggests the category when it reads a label. The dates screen groups batches into expired, this week, this month and later.
Qiksy Shelf has its own page in 17 languages, and an iPhone gets guided install steps
qiksy.app/get-shelf/ walks through the till, receiving, dates, stock and the report, with screens in the visitor's language and money. Apple lets only the person add a page to the Home Screen, so on an iPhone the install button now opens the three taps it takes, with an arrow toward the browser's Share button.
Every Qiksy Shelf screen opens with its own number, and Android installs it with one tap
Receiving, stock, the report and the settings now open with the same blue header as the till. Receiving shows the delivery being taken in, stock shows the pieces on the shelf and their value at cost, and the report keeps its period and revenue in the header. On Android, Chrome can put the app on the home screen from a button on the till and in the settings.
Qiksy Shelf sells tub after tub with the camera open, and a sale can be undone
The till camera now stays open for the whole sale and shows the running total, and a product with several dates on the shelf asks for the date at once instead of waiting for the AI to read it. A sale can be undone for five seconds, a receipt the register refused is kept until it goes through, and the last piece of a line can be put back after removing it. In receiving, each date keeps its own quantity on one line, the next date is read by the live camera, the accept button stays at the bottom and the supplier carries over to the whole delivery. A purchase price can be added to a batch later, and the report lists what was written off.
Qiksy Shelf: the open sale survives a stray tap, and a scanner cannot accept a delivery
Fixes from a walk through the app as a seller, an owner and a first-time user. A barcode scanner no longer adds to a sale while its QR code is waiting to be paid, and the open sale stays when another tab is touched by mistake. In receiving, the Enter a scanner sends moves to the next field instead of accepting the delivery, a typed total is split evenly across the dates, and tapping a year moves the chosen month with it. The report says plainly when batches without a purchase price make the profit look higher than it is.
Qiksy Shelf reads each further expiry date in a delivery from one photo
A delivery that holds several dates no longer means picking each month by hand. Another expiry date opens the camera straight away and reads the date and lot off the next tub, and the new line starts with as many pieces as the one before, so ten, ten and ten is three photos. A date that is already on the list adds its pieces to that line instead of repeating it. The total at the top now starts at one and follows the dates below until it is typed in.
Jig 1.13.0: a tester who works on the code can undo, accept and find the build that broke it
Jig edits a file in your project and then asks. The feed offers three answers: show me the diff, accept the work, or put everything back. The safety point is taken before the first edit, not after. A finding now carries the build it was found on, and the card asks when this broke: name a build that worked and one that does not, and Jig raises them one at a time and lets you judge each by eye, then names the commit. It refuses honestly instead of guessing, whether the revisions are the wrong way round, the address is already answering or the good build will not come up, and the search has a stop button. The developer profession says all of this out loud, in a fourth direction called Work on the code. On macOS both Apple Silicon and Intel are signed and notarised by Apple.
Qiksy Shelf will not sell an expired batch, and profit counts the losses
The till used to offer an expired batch as the one to sell first. Now it marks it as expired, will not ring it up and sends the seller to write it off. Profit in the report now subtracts write-offs and stock found missing at a recount, so a day that threw away expired goods no longer reads as a good day. Demo stock is left behind when a shop moves to the cloud. A recount takes digits only, a delivery is capped at 9,999 pieces, and search finds a product by its barcode.
Qiksy Shelf has a Report tab: takings, profit and markup
The fifth tab now shows what the shop earned. It opens on today, the check an owner makes at closing: takings split into cash and card, profit and markup, the number of receipts and the average one. A month view adds stock valued at purchase price, from the opening figure through goods bought in, cost of goods sold and write-offs to the closing figure, and checks that the money adds up the same way the pieces do. It exports a CSV for the bookkeeper. Nothing extra is typed in: every number comes from the deliveries and sales already recorded, and batches entered without a purchase price are named, so the profit never quietly overstates itself. Settings moved behind a gear in the corner of every screen.
Qiksy Shelf says what is missing, and knows goods without an expiry date
A form no longer greys out its button without saying why: pressing it with a gap scrolls to the gap, outlines it and says what to fill in. Goods that have no expiry date at all, such as spirits or accessories, can be received as having none, and they stay out of the expiry list. The smart camera now names the next thing to show, the front, the barcode or the date, and offers No expiry when it has looked long enough and found no date on the package.
Qiksy Shelf signs in with Face ID or a fingerprint
After the first sign-in by email, the phone offers a passkey: from then on a glance or a fingerprint signs in, with no code to wait for. On a phone that supports it, an iPhone on iOS 18 for example, the same glance also opens the shop’s encrypted stock on a new phone, so the owner no longer needs the recovery key there. The key that opens the stock stays sealed on our server by the passkey itself, and we cannot open it.
Qiksy Shelf keeps the stock in the cloud, sealed on the phone
A shop now signs in with its email and a one-time code, and its stock stops living in one phone only: a lost or broken phone loses nothing, and every seller of the shop works on the same shelf. Everything is encrypted on the phone before it leaves, with a key the server never receives, so nobody else can read what a shop sells, us included. A second seller or a new phone joins by an invite link or its QR code, and the owner sees who is connected and can disconnect anyone. The phone is still the working copy: a sale goes through without a network and reaches the cloud when the connection is back. The till got two connections in More. A Checkbox software cash register turns each sale into a fiscal receipt with a QR code for the buyer, and monobank acquiring takes a card payment by QR: the till shows a code for the exact amount, the buyer pays from their phone, and the payment confirms itself. The money goes straight to the shop’s own account.
Qiksy Shelf reads the tub while you hold it
The camera now does two jobs at once. The barcode is read on the phone, instantly and without a network, and about once a second a frame goes to the AI, which reads what a barcode cannot carry: the name, flavor, size, expiry date and lot. Each field lights up on the screen as it is found, the frame shows when the AI is looking, and the camera closes by itself once everything it needs is in. At the till this removes the one question the app used to ask. When a product has several dates on the shelf, the AI reads the date printed on the tub in hand and picks that batch, and the older-batch warning follows from it. Receiving got faster too: the quantity comes first after a scan, with the box sizes supplements ship in, and a delivery can be counted by passing the tubs under the camera one by one. One box with three expiry dates is entered as three batches on one screen.
Qiksy Shelf: stock with expiry dates for small shops, on the phone
A new product for a counter that sells things with a best-before date: sports nutrition, supplements, cosmetics, pet food. Stock is kept by batch and expiry date in the browser of the phone the seller already has, iPhone or Android, with nothing to install and nothing lost when the internet goes. The part other shop software skips is the till. A tub carries the same barcode in every batch, so a scan alone cannot tell an old tub from a fresh one, and the usual answer is to write off the oldest batch on paper while the fresh one leaves the shop. Shelf asks the seller which date is printed on the tub in hand, and when an older batch is still on the shelf it says so before the sale. Selling the fresh one anyway takes a reason, and the reason lands in the journal. A new product can be added from one photo of the package: name, flavor, size, expiry date and lot number are read from it and only need checking. One screen shows what expires in 30, 60 and 90 days and what that stock cost. It opens at qiksy.app/shelf/ and is free while the first shop runs it as a pilot.
Qiksy Bridge 1.65.0 · the agent can open the page it needs
The bridge refuses to steer one of your tabs onto a different site, and that refusal is right: it is what keeps an agent out of your mail and your bank. But it ended at «open it in a tab yourself», and the only reliable way to do that lived in one person’s notes rather than in the product, so every fresh agent rediscovered the dead end and stopped there, and what the person saw was the bridge giving up. There is a verb for it now. It opens the address as a NEW tab, beside the ones already open, losing nothing; the boundary is untouched, because steering an existing tab off-site is still refused and a new tab costs nothing if the agent was wrong about needing it. The hard part is which browser it lands in, and that is solved by construction rather than by care. A machine has several Chrome profiles, the extension lives in exactly one, and a tab opened into any other is invisible to the bridge, so every reading afterwards is then about a tab nobody can see. Naming the profile is not an option: a running Chrome ignores the flag, the command still exits 0, and no error exists to diagnose. So no profile is named at all. It takes a tab the bridge can already see, finds the window holding it, and inserts the new tab beside it. Two smaller things carry the rest of the weight. The refusal itself now names the verb, because a rule an agent reads while calm does not survive the call where it is stuck. And the answer distinguishes «open and yours to drive» from «open, but not in the session»: once any tab has been switched on for the agent, the session is that explicit set, and reporting plain success there would leave the agent measuring a tab it cannot see and blaming the bridge for it.
Qiksy Bridge 1.64.0 · the finish signal stopped guessing
The sound that says a run has ended was going off in the middle of one. Since 1.46 the bridge announced a finish by itself once nothing had touched the browser for ninety seconds, on the reasoning that asking an agent to call the verb is a request rather than a mechanism. But an agent that leaves the browser to read files, edit code or think is silent for minutes while working flat out, so the signal arrived mid-run, and again at the next lull, and again. The defence of that design only ever covered half of it. It was called safe to be wrong because any later call cancels the pulse. A pulse can be withdrawn; a sound that has been heard cannot. And a signal that is right most of the time is worse than no signal at all, because it gets learned as noise and switched off, taking the true ones with it. So the guess is off by default. The mark pulses and the sound plays at a real full stop: the agent calling the verb, or the finish hook that the setup command writes into your client. Once either has been seen, the process stops estimating for good, because a setup that reports its own endings is never guessed at, even if somebody switched both on. The estimate remains available for a client that has neither, in seconds, twenty at the lowest; below that it would fire inside an ordinary pause for thought. Also in this release: a report names the time zone beside the moment it was taken. Those conditions were already collected for the agent and were simply not reaching the document a person reads, which carried the browser string instead. The browser string is identical for the two people arguing about a bug; the zone is what settles «works on my machine».
Qiksy Bridge 1.63.0 · reports land in the project they are about
A report is the one thing this tool makes that somebody else reads. It gets attached to a ticket, sent to a client, referenced from a commit. It was landing in the browser’s download folder, where a week later nothing says which report was about which product. The bridge already knew the answer and was not using it: the agent process is started from the folder you work in, and it already tests that folder for the marks of a project before writing its own guide there. The same test decides this. A report built with no path named is now filed under «qiksy-reports» in that folder, named by date and subject, beside the code it describes, and the panel’s own Report button goes to the same place while the bridge is connected, falling back to an ordinary download when it is not. The toast says which of the two happened and names the folder, because a file that went somewhere you were not told about is a file you have lost. That needed a direction the protocol did not have. The bridge asked and the extension answered; the extension could not ask for anything, and a document a PERSON builds is exactly that kind of request. One frame each way was added, and kept deliberately narrow: the browser side sends a file name and the bytes, and the agent side chooses the folder. A name that tries to climb out of it is reduced to a plain file name, because a directory chosen by the browser side is a directory chosen by a web page one bug later. QIKSY_REPORTS_DIR moves the folder; «off» writes nothing unless a path is named. Outside a project nothing is written either: a home directory is not a project.
Pricing says what is actually paid: the bridge, and nothing else
Since September the extension has had one paid thing, the bridge your coding agent reads this browser through, and everything a tester does by hand has been free, with no meter and no cap. The extension said so, the landing said so, the store listing said so. The price list and the terms still carried the sentence from before, «all Pro features of the extension», which is not wrong so much as useless: it does not tell you what your money buys. Both pages now name it. Paid: the MCP bridge and Agent control. Free and not part of the purchase: filling, findings, audits, the tour, multi-login, the session recorder, bug capsules, scenarios, mocks and the client report. Nothing about the price changed: $49 for a year, one payment, 28 days to try first. The product catalogue was saying the opposite by omission: its card had no sign of a free layer at all, and it advertised «v1.0, July» while the store was serving 1.61. A version frozen nine releases back reads as a product nobody is working on. The number now lives beside the other public figures, in one file, and moves when a release goes live.
Qiksy Bridge 1.62.0 · a long release note fits in the popup
A release note is as long as the release was, and the toolbar popup is a narrow strip of window. There is no length that can be assumed, so a long note simply ran past the bottom edge and pushed everything else out of the popup with it. The cap is on the TEXT, not on the note. Capping the whole block would have carried «What’s new» and the × away with the first scroll, and the way OUT of a message must never be the first thing to scroll away. The foot of the text fades instead of being cut, because a line stopped dead reads as the end of the paragraph while a line that dissolves reads as «there is more», and the hint disappears once the end is in view. The first attempt made it worse, and only a screenshot showed it. The text was capped while the controls were left floating beside it, and a scrolling box is a block formatting context, which does not flow around a float but stands next to it for its whole height. The note rendered in a column nine characters wide. Every measurement still reported «bounded and scrollable», and every one of them was true: there are defects that numbers cannot see, and this is the shape of them. The check that covers this note’s layout already existed and was not wired into the build, so it had nothing to say about any of it. It runs on every build now.
Qiksy Bridge 1.61.0 · the button is back in its corner
The setting that remembers where the button was dragged to read an absent value as zero. So on every browser where nobody had ever moved it (which is every browser, the day the feature ships) the button was parked at the very bottom edge of the window, with the usual gap on its right and none underneath. It is the oldest shape of bug there is: a default that becomes a value. «Nobody has set this» arrived as the number 0, which is a perfectly good position, so nothing anywhere could tell the two apart. An unset setting now leaves the stylesheet’s own corner alone, and the check that guards it compares the gap below with the gap beside rather than with a number, so the next person to change one cannot quietly break the other.
Qiksy Bridge 1.60.0 · the button moves out of the way
The floating button had one corner, bottom right, and on the real web that is the busiest corner there is: the chat widget, the cart badge, the cookie bar and the «back to top» arrow all live in it. A control you have to work around is a control that covers the thing you came to test. So it can be dragged, and on release it flies to the nearer edge and keeps the height it was left at. Free vertically, magnetic horizontally, for two reasons on the second half: a button stranded mid-screen sits on top of the form under test, and «which side am I on» is a fact the panel, the callout, the recording frame and the update notice all read, so an arbitrary position would leave every one of them guessing. A press that travels less than five pixels still opens the panel, the click that ends a drag does not, and Settings keeps the plain left/right choice for anyone who would rather not drag. Fixed in the same release: after an update, the «Qiksy updated itself» strip came out on the LEFT for everybody, whatever side the button was on, because a second logo on the far side of the screen, which reads as a stray panel rather than as your own button speaking. The side was measured off the extension’s container, and that container is a zero-sized box pinned to the corner of the window by design. Its position was therefore always the same number: the line that looked like it was reading the button was reading a constant.
Jig 1.12.0 · three tools are free, and dictation stays on your machine
Checking a page against a mockup, the overlay and the accessibility report used to ask for Pro. All three run on the tester’s own machine and cost us nothing to run, so they are open to everyone now. Dictation no longer leaves the machine at all. Until the local model finished downloading, a recording went to our server; that was the last path by which anything spoken travelled, and it is gone. With no model yet, Jig says so and shows where to get one. Two things that were quietly wrong are right now. A refused tool, and the line that says a run was interfered with, were always written in English regardless of the language chosen in Jig; both are translated into all seven. And a page that answers by moving focus into new content is no longer marked silent: Jig allowed a spoken answer half a second longer than a focus move, and correct applications were being told they changed and said nothing.
Off-Duty · the sound is on unless you turn it off
The page used to open silent and wait for somebody to find the sound control. Its own owner came to it three times and heard nothing, the third time saying plainly that he had not seen the button. A page whose whole claim is that it makes a sound cannot open muted behind a control people do not find. No browser lets a page play before the visitor has done something, and there is no permission to ask for, so what is on by default is the WISH: the button reads «on» from the first frame, and the sound itself starts with the first gesture anywhere on the page. The button now follows what it says rather than what the browser has released, because otherwise the first press on a button reading «on» turned it on again, which to the person pressing it is a mute button that does not mute. An explicit «off» is still silence, and a private window behaves like a first visit. Also: the two columns of the opening block are aligned by their tops instead of their bottoms. The old way lined up the last lines of two texts of unequal length, a tidy edge nobody looks at, paid for with a ragged one everybody does.
Qiksy Bridge 1.59.0 · following a link no longer throws the agent out of the session
Switch the agent on for a search page, ask it to find a product, and the click that opened the shop was also the click that ended the run. The tab had left the site you switched the agent on for, so it dropped out of the session, and everything after that answered «this tab is not in the session», which reads as a broken bridge and is not one. The rule it hit is the right rule: an agent works where you put it, not wherever a tab happens to go. What was wrong is that the one exception to it was decided by somebody else’s markup. A link with target="_blank" opens a NEW tab, and a new tab inherits its place from the tab that opened it; the same link reusing the tab did not. Nothing about that difference is visible to the person, and nothing about it is about safety. So a hop the agent itself made keeps its place, as a guest, and on narrower terms than a site you switched on. Only a tab already in the session, and only right after the agent ACTED on it: a page you typed an address into yourself still drops out. The site is not remembered, so no other tab on it joins and nothing survives the browser closing. The seat is named in the popup and in qa_tabs, and the tab’s own switch takes it back. Reading never extends a session, only acting does. That is the line that keeps «the agent may look here» and «the agent may work here» two different permissions.
Qiksy Bridge 1.58.0 · closing a message no longer takes away the way out of it
The «Reload the page» button lived inside the «updated to» note, and that was the wrong place for it. A note is NEWS: you close it and it never comes back. «This tab is still on the old version» is a STATE: it stays true until the page is reloaded. One accidental × and the way out was gone, with nothing left to say it had ever been there. The reload now has a row of its own in the toolbar popup. It has no ×, and it disappears by being fixed rather than by being dismissed. Settings → Appearance also carries the version and a «What’s new» button, so dismissing the news does not lose the news. And two sentences were English in every language, in a panel that is otherwise translated into seven. Both were spelled out in the source while their translations sat unused in the dictionary: one under multi-login, one under the tab-order overlay. The check that exists precisely to catch that was looking the other way: it treated a bare «=» as a sign of code, and «each Ctrl+T tab = its own login» contains one. The rule is narrowed to what code actually looks like, and it found the second sentence by itself.
Qiksy Bridge 1.57.0 · the keyboard shortcuts are yours to change
Qiksy’s three shortcuts (screenshot, panel, command palette) are declared to the browser now, so they appear in chrome://extensions/shortcuts and can be given any combination you like. Until now they were caught by a listener inside the page: that works, and nobody could change it. It matters most on Windows. There, Alt+Shift is the operating system’s own keyboard-layout switch, so a fixed default is a default that somebody with two languages simply cannot use, and no amount of guessing from our side tells us which combination is free on their machine. Making the key changeable is the answer that does not depend on guessing. They also fire now when the focus is in the address bar rather than on the page. The defaults are unchanged: ⌥⇧S or Alt+Shift+S photographs the page and opens the markup editor, Alt+Shift+Q opens the panel, Alt+Shift+K opens the command palette. What could be checked without Windows was checked: on a non-Mac the buttons say Alt+Shift+S and Ctrl rather than ⌥⇧S and ⌘, and the tool letters stay single letters. Whether Windows itself takes Alt+Shift can only be seen on Windows, which is precisely why the repair is not a better default but a key you can change.
Qiksy Bridge 1.56.0 · a screenshot of the page is two keys now
Press ⌥⇧S on a Mac, or Alt+Shift+S anywhere else, on the page itself, with no panel to open first. The whole page is photographed and lands straight in the markup editor, which is where a picture was going anyway: crop it, put an arrow on it, copy it into the ticket. Two repairs came with it, and the first is the kind that only appears once you add a shortcut. A capture that could not be taken used to say nothing at all when the panel was closed, and closed is exactly what it is when a key starts the capture. Pressing the key then looked like a dead key, whatever had really gone wrong. The reason is shown every time now. The second: shortcuts are read by the POSITION of the key rather than by the letter it produces, because holding Option on a Mac turns Q into «Œ», and a check written against the letter is a shortcut that works on one platform. In the markup editor the tool letters are drawn as keys and the row says «one key». Nothing about them changed (a bare B always selected Box) but beside ⌘Z and ⌘C a lone grey letter read as half of a combination whose first half had gone missing, which is exactly how it was reported to us. And the session recorder stopped starting by itself. It was tied to the History block, and since 1.53.0 every block is on from the start, so it began for everybody, unasked, with a blinking red REC sitting over their employer’s live application. That is the one thing this product says it never does. It now asks first, in the same box that guards saved logins and the bridge, and names what it writes down, where it stays and how long. The mark is still there so you can see it running; it just no longer blinks in red, and it says «Recording» rather than «REC», which is what a video camera says.
Legato 0.3.94: the first sentence on every page was never heard, and three doors were ajar
A screen reader announces only changes to a region it is already watching. Legato's region was created with its text already inside it, so the very first thing the browser said on a page was skipped. Every page, every site, since the region was introduced. It is created empty at load now and speaks from the first sentence on. Continuous reading used to say "end of page" in the middle of an article, because it walked a snapshot taken once while the page kept drawing itself. A hand-made dropdown used to freeze its name: you picked Germany and the reader went on saying "choose a country" for the rest of that page's life, which is worse than not repairing it, since the author's own text was working. And LinkedIn now works like any other site: until today nothing worked there at all, which was our own caution pointed the wrong way, on the one network where work is found. Three doors, found by a ten-person review of the previous build, none of them ever used against anyone. A local file in somebody else's folder named "ui" could pose as one of our own pages and reach the system clipboard. An open page could speak in the browser's voice: announce "page repaired" where nothing had been done, and ask for the file panel to open. And a voice package arrived with no signature at all, while inside it is a model the browser then runs; all 49 packages now carry a sha256 checked before unpacking. Each door is shut behind an instrument that has been proven able to fail, because a green check that cannot go red is not a check.
Legato: the page now says what really happens to a name you fixed
Legato keeps a shared memory of names for controls that have none, and every browser asks it for free. Our page promised something more: that when you repaired a page, the names you got went into that memory, and the next blind person arrived to a page already fixed. It stopped being true on the seventeenth of September, when we decided the shared memory should have exactly one writer. Until today the page still promised the old thing, in all twenty five languages. What actually happens: our own crawl walks the web and puts the names it finds into the shared memory, so a great many pages really are named before you ever arrive, and that part costs nothing. When a page is not in there and you ask for a better name, the answer is worked out for you and it stays yours. Nothing about the page you are standing on leaves your machine: the shared memory is something Legato asks, never tells. Nothing in the product changed today. The page caught up with the product.
Qiksy Bridge 1.55.0 · the bridge waits while you sign in, instead of calling it a failure
Point an agent at something behind a login and it used to come back with a refusal: no permission to be here, switch something on. It said that while you were calmly typing a password. The rule that recognises a sign-in was being asked about the bare domain, "google.com", while it reads addresses, so it answered no every single time and the whole hand-off was dead in the shipped build. Its own checks stayed green throughout, because they called the rule the way it reads best rather than the way the product calls it. Now the agent is told the sign-in is yours to do, waits up to five minutes for you, and carries on where it stopped. If nobody starts, it says that plainly instead of retrying. And for the logins that never move the address (Apple opens its form inside a frame, so the address stays the same from beginning to end) it names the second way to wait rather than waiting for something that will not happen. The other half of this release is the notice you get after the extension updates itself. It is part of the round button now: it slides out from under it, folds back with the arrow and leaves a small tab, so the reminder never quietly disappears. One reload clears every open tab at once instead of one at a time, and the update can be finished straight from the toolbar popup, which keeps working even when the page it is about does not. On npm as [email protected]; the extension is with the Chrome Web Store reviewers.
Off-Duty · the extension that gives any site a doorbell, and one name for it everywhere
Pick a sound, pick what makes it ring: a customer reply, a paid order, a price crossing your level, an appointment slot that just freed up. The sound plays the moment it happens, even when the tab is buried behind everything else. A rule is caught in thirty seconds: press "Catch it", make the thing happen once, and press one button on the line that matters. No code, no account, and nothing leaves the browser. It is called Off-Duty. Until today it also answered to Qiksy Chime, because the extension and the page header said one name, the copy and the catalog said another, and the address said a third. One name now: the page lives at /off-duty/, and the old /chime/ redirects to it permanently, so anything already linked still arrives. What it cannot do is printed on the page rather than in small type: sites that take their deliveries through a worker or send them as binary (WhatsApp Web, Telegram Web, Bybit) are silent to any extension, and we name them instead of letting you find out after installing. The install button is honest in the same way: the listing has not passed the Chrome Web Store review yet, so the button says "in development" and cannot be pressed. It starts working the day the extension is published. Free while in beta.
Jig 1.11.0 · every kind of work now has its own shape, and the paperwork follows it
An accessibility audit in Jig has always been organised around fifteen NAMED DIRECTIONS, and that is the reason its report gets read: you see coverage, what was looked at and what was not, instead of a heap of ticks. Every other kind of work got a flat list of five or six items. The work existed; a shape for it did not. Now it does. Someone testing by hand has four directions: getting in, forms both ways, menus and routes, the narrow screen. Someone taking a failure apart has three: reproduction, what screamed at that second, and what was handed to the developer. An analyst has the screen inventory, the business’s own words, the comparison against the live system, and the summary that all of it was for. You see them above the checklist as you work, with a word and a count each, and every document (the one for the team, the spreadsheet, the file your CI reads, the one you hand to the client) opens with that same coverage. A direction nobody touched says so in plain words rather than counting as zero, because in a bad report "we did not check this" and "we checked it and there was nothing" look identical. In the CI file it is a skipped test, not an absence: otherwise a run comes out green on work nobody did. Ten defects found by a ten-person review of 1.10.0 are fixed in this release, and three of them lost people’s work. "Export and delete" promised the file would carry your passwords in the clear, said "7 exported", and wrote a file stating there were none, because the passwords had already left the keychain with the project, and there was nowhere to get them back from. A failed write of a finding was swallowed whole: a full disk, a read-only volume, a folder carried off on an external drive: in every one of those you were told "finding saved", and the observation window closed and threw away both fields you had typed. And a finding made while Jig itself was answering for the application (a mocked 500) travelled to the developer and to the client as a real defect of their site: the conditions were recorded, but only one document out of five ever printed them. The rest: a saved widget procedure is now read on the path that writes it, so the promise "the first pass is slow, the next ones are not" finally holds where the chat actually works, field by field; a checklist in the model’s answer says "done" and "failed" out loud instead of leaving it to a tick and a colour; and the first minute of a blind tester no longer undoes itself, because the document used to say "press Option A", which switched the guidance OFF for anyone who had just answered "with a screen reader" in the wizard.
Jig 1.10.0 · a saved scenario now fills the form it filled the first time
Replaying a saved scenario across a nine-step wizard restored 31 of 45 fields. The other fourteen were the ones behind a dropdown, a date picker or a combo box: Jig picked the value, the list stayed open, and the next field was typed into a page that was still busy with the previous one. It now closes that layer the way a person does: the key goes into the open list itself and into the control that owns it, not only into the document, and the same run restores 45 of 45, across seven different interface libraries. Nothing about the scenarios you already saved changes; they simply arrive complete. Four more things that were plainly wrong. A control that opens the operating system's own file window used to leave the run stuck against a window nothing can close, so Jig now refuses it by name and says to attach the file instead. The delete button on a scenario card deleted nothing; the card carried five buttons where two belong, and the three rare ones moved under the disclosure. "How to repeat" called one field by two different names whenever an error message was hanging off its label, and a cleared field printed as an unfinished sentence, so it now says "clear" and names the field the way the screen does. The practice form, which had quietly vanished from an empty window, is back for anyone who wants to try the panels before pointing Jig at their own product. Every check was run on both Mac chips and on a real Windows machine: the Intel build was driven through the full round under Rosetta, and the Windows installer was installed and launched on Windows Server 2022 rather than assumed to work.
Jig 1.9.0 · a screenshot that shows only what you meant it to, and work you can hear finish
Ask for a shot of the page and name the parts that matter: the rest of the frame goes dark, the named controls stay lit, each one can carry a caption, and anything that must not leave the machine (an account number, a customer name, somebody else's inbox) is blurred out. It is a layer on the FRAME, not on the page: nothing is inserted into the document, so the screenshot is of the product as it really is, and the next step of your run sees exactly the page it would have seen anyway. A zone is named the way the screen names it; a name that matches nothing, or matches two controls, is refused and listed rather than guessed. One thing follows from the blur and is worth saying out loud: when you hide something, Jig stops writing the page's text beside the picture, because that file is searchable, and Ctrl+F in it would find precisely what the blur covered. The second half of this release is about a long task you are not watching. Jig now has a voice: sixteen short sounds, and you choose which one marks a finished step, a finished job, an answer, or a problem, and they are deliberately different from each other, so you can tell from the next room which one it was, and they stay quiet while you are actually looking at the window. Queued work got fairer too: when several projects are running at once, the ones at the end of the list no longer wait behind the ones at the front, and a task the engine pushed back now says "queued" in the conversation instead of sitting there looking started and unanswered. And the track under a screen recording keeps the server's own words on a failed request even when the machine is short on memory, because "payment does not work" and "500 {"error":"tax_id required"}" are two different tickets.
The radar stopped losing coins, and says plainly what it does not know
Typing FETC returned "search unavailable". Typing FE returned nothing. Typing F found something. Two causes, both real. Search had no second source: the coin profile has fallen back to a spare reference since the beginning, but the suggestions only ever asked one, and a single rate-limit refusal silenced them for a minute, so the first keystroke answered and the rest did not. And the suggestions never looked at our own list, which knows FET, TON, PEPE and a hundred more by name. Now our own list answers instantly with no network at all, the second source covers the rest, and "unavailable" appears only when both are silent and we know nothing ourselves. The 483 coin marks now ship with the site instead of being fetched per coin from a rate-limited service, which is why Ethereum had a letter E where its logo belongs. The eleven tokenised stocks were not loading on the live site at all: the security policy listed one address of the exchange and the code called another. A new gate checks that every outside address the code fetches from is on that list, the same mistake had been made three times, and it is invisible on a development machine. The hundred largest coins are now one click away, as a market map rather than a hundred-line dropdown: ten tiles to a row across the full width, each tinted by how far it moved today, so what kind of day the market is having reads before a single ticker does. Order it by rank, by the biggest gainers or by the biggest losers. Two things the screen used to leave unsaid. A marker on the chart was called "buy zone", while it sits on PAST bars where price was deeply down, so a description read as an instruction, by exactly the person who cannot tell the difference. And when the reference source is rate-limited, the coin profile is served from storage and can be up to a day old while the price beside it is live; the screen looked identical either way and now says the age. Added: what the order book holds within one percent of the price, so "will my own order move the price" has an answer that a day's turnover cannot give; and how closely the coin repeats bitcoin, because the most common beginner's mistake is reading a whole market rising as this project doing well.
The About page has a header, so you can leave it
People arrive at /about/ from a link in a letter or from search, and the page had nothing around it: the text started at the first line, the product was not named, and there was no way onward. It now wears the same header as every other page: the mark that leads back, the style and theme switches, the language switch and the way into the app, full width, like the rest. The other documents stay bare on purpose. The till and the Chrome Web Store link to /pricing/ and /terms/, and those pages are meant to load with as little as possible.
Qiksy Bridge 1.43.0 and 1.44.0 · a switched-off site says so, and a tab stopped acting twice
A tab that was open at the moment the extension installed or updated received the content script TWICE: Chrome injects the declared one, and the worker separately adopts open tabs so they are not left with a dead context. Both copies answered commands: one click pressed the button twice, two milliseconds apart, and nothing in any answer said so. On somebody’s logged-in application that is a form submitted twice. The page-ownership mark already existed; it is now checked when a command arrives, not only when the listener is registered. Switching Qiksy off on a site stops everything inside the page, and the agent switches did not know it. They still answered yes, so a tab could sit in an agent session with no Qiksy in it at all: no panel, no mark on the favicon, and every agent call saying “not running on this tab” with nothing on screen to explain why. Found on Gmail, where the site had been switched off weeks earlier. The popup now says which of the two is in the way (the site being off, or the bridge not being connected) and the agent’s own answer names the real reason instead of asking for a reload that cannot help. Setting it up is also one command now: `npx qiksy-mcp init` picks a free port, mints the token and writes the config of every agent already installed, leaving other people’s MCP servers in the file alone. No new permissions in either version.
Legato 0.3.93 · a sign-in form built out of a table is no longer silent
Legato names an unlabelled field from the caption written beside it. That rule looked for the caption only inside the field's own cell, and only to the left of the field. In a table the caption always sits in a different cell, so a sign-in form built that way was read as «edit text» and nothing else, however plainly it reads on the screen. A blind tester sent us a site where the whole form was silent; the same markup signs people in on Hacker News. Three layouts work now: the caption in the cell to the left, the caption in the row above (one column or two), and the text to the right of a tick box («Remember Me») which nothing had looked at, because a text field is captioned on its left and a tick box on its right. The name is the author's own text, and the rule speaks only where there was no name at all, so it cannot overwrite what the site already said. The rule had lived for six weeks with no check on it at all, which is why the gap reached a person before it reached us. It now has one: a fixture carrying all three layouts plus two that already worked, wired into the release gate.
Legato 0.3.92 · a site that reads badly can be handed to us, and we take it apart by hand
Legato repairs pages on the spot, by guessing. Some sites are built so that guessing is impossible, and until today a blind person who hit one had no move left. There is now a menu item, «This site reads badly», that opens a short form: which site, what goes wrong, how deep to look, with the address of the page they were on already filled in. We take that site apart ourselves and put the rules into the shared memory, so it then reads properly for everyone who comes to it. This is the replacement for guessing at scale: the crawl used to wander the web hoping to land on something useful, and now the addresses arrive from the people who need them. It also serves the people who declined the local model, because rules weigh bytes and run on the weakest machine. The limits are on the form, not in a FAQ: we reach only pages visible without signing in, and a site takes a day or two. What reaches us is the address and the person’s own words; the words are seen by us alone and never enter the shared memory, other people’s browsers or the model, so this door cannot be used to feed us content. Five requests a day per installation. The signals are recordings now. All sixteen were sine waves, clear, but they sound like an instrument panel to someone who hears them hundreds of times a day. One wood for all of them keeps them a family, and the meaning stays in the direction, so the vocabulary does not have to be relearnt. The landing plays the very same files, pulled from the browser at build time, because a copy beside the site is exactly the drift that once had it playing «error» on the wrong note for months. And an update now announces itself properly: the browser opens the What’s new tab once per version, with buttons leading straight to what it describes. A tab rather than a modal: it does not trap the keyboard, and the menu brings it back any time. Also: the start page lost the padding it was reserving for an empty screen, including 84 points under the pin area that a dragged tab never needed, because that zone opens to full width by itself.
Legato 0.3.91 · the local model finally reaches the machines it was written for
The browser can work out a name for a button the site left unnamed, and that work is done by a small language model running on the person’s own computer. It had never reached a single one of them: the model was not in the package, no button fetched it, and no line of code downloaded it. Nobody noticed, because a missing model is indistinguishable from a silent one, because the rules and the icon dictionary keep repairing the page either way. It is now offered on the first run and sized to the machine: the 4B model names about 7 of the 10 hardest cases, the 1.7B one about 6. Those numbers are measured on 200 deliberately hard findings, because the easy ones are already solved without a model, so this is the remainder, not the web. Four gigabytes or under two, fifteen to twenty minutes, and declining is a complete answer: everything else works without it. On Windows it would not have started at all. The native part is built with MSVC and needs the Microsoft runtime, which a clean Windows does not carry; the loader reports “the specified module could not be found”, which is false: the file is there, its dependencies are not. Four libraries, 765 KB, now ship inside the package. Proved on a stand with the Microsoft redistributable deliberately uninstalled. And the choice is reversible: the settings list both models, switch between them, and remove either to get the disk space back.
Jig 1.8.0 · a run you did by hand becomes a test your build can run
Walk through a flow with the recorder on, then press one button and Jig writes a Playwright test of it. The steps are named the way the screen names them ("City", "Submit") so the file reads like the flow and survives a change of markup. The password is never written into it: it travels as an environment variable, because the file goes into a repository and a repository is read by everyone. This release also closes three holes we found by auditing Jig against the list somebody used to break another product of ours in one evening. Jig learns how to drive unfamiliar widgets and shares what it learns between installations, and the shared note could carry the class names of the customer's own internal admin. It no longer leaves the machine: only widgets built from a known component library are shared, a page you are signed into shares nothing at all, and a procedure that arrived from somebody else stays marked as theirs for as long as you keep it. Tokens for connected tools now live in the operating system keychain instead of a file.
Code blocks in our docs can be reached with a keyboard
A long command overflows its box and the box scrolls sideways, with a mouse. Without a tab stop there was no way to reach the second half of the line: the text was on the page and out of reach at the same time. Four blocks on the Bridge docs page, caught by our own accessibility gate before the deploy. Every code block in the docs now takes a tab stop, announces itself as a code block, and scrolls with the arrow keys.
Shift says what the pilot costs, and names two kinds of work it had left out
The landing said we take the load off manual testing. That was narrower than what we actually do: an accessibility pass walked page by page, and going through an unfamiliar product screen by screen, are the same shape of work, a person repeating themselves for a week, and both are now named on the page. The pilot terms are on the page too, instead of being explained in a call: our own tools, Jig with Bridge bundled, free for a month, a quarter if the pilot needs one. Nothing to license before you know whether it helps.
Legato 0.3.90 · a security release, and four of the five holes were ours
A full census of what the browser exposes, surface by surface. The engine moves from 43.4.0 to 43.7.2: five Chromium security releases we had not shipped. A published fix also describes the hole it closes, so the builds that get attacked are the ones that did not take it. An extension package downloaded from the Chrome Web Store was checked against the name written inside it: plain text, put there by whoever built the package. The only thing standing between a user and somebody else’s code was the connection to Google, and a company proxy sits inside that connection. The CRX3 signature is verified now, over the header and the archive together, and only a key whose fingerprint is the extension’s id counts, before a byte reaches disk. Passkey private keys and saved route values were written to disk in plain text whenever the system keystore is unavailable (normal on Linux without a keyring) while our own text promised ciphertext. Keys are not stored at all now; a route keeps the path and asks for the values again. Four of the twenty-six bridges from our pages into the main process matched the page address by substring, so any local file in a folder named “ui” got through; behind one was write access to the system clipboard. And the last open item in our egress ledger is closed: when you ask for a picture to be described or a page rewritten in simpler words, and the site itself has sent a stranger away to sign in, the browser says so, once per site, inside the sentence it already speaks. A statement, not a gate.
A live count of what the crawler has walked, and what it found with no name
Since August a crawler has been walking public sites and recording one thing: places that reach a screen reader with no name: a button that announces itself as «button», a link that says «link». The accessibility page now carries the running total, refreshed every hour: sites walked, pages read, nameless places found, domain zones covered. The figures are not computed for the page. They come from the same script that produced the static report at /access/data/, run on the lab machine and forwarded as-is. Two pages on one domain quoting different totals is the kind of thing a reader screenshots, and re-implementing the definitions (what counts as one site, what counts as a country, what counts as nameless) would guarantee that the first time one of them was refined. The sentence that matters most sits directly under the numbers rather than in small print: there is no denominator and there cannot be one. The crawl records what is broken and never counts what was already right, so none of this is a share of the web, and the site list is a queue we assembled rather than a random sample. It also admits when it is not moving. On 15 September all three crawler lanes went quiet for two and a half hours before a watchdog restarted them, and a page showing only totals would have looked perfectly healthy throughout, because the accumulated figures do not shrink. A lane that has started nothing for an hour and a half is now named out loud. A public number that quietly stands still is worse than an admitted gap.
Qiksy Bridge 1.33.0 · the tab itself says when an agent may act in it
A tab you have handed to your coding agent now marks its own icon: four magenta corner marks around the site’s favicon. That is the one place a browser lets a tab speak about itself, and the only one that keeps speaking while the tab is in the background, which is exactly when an agent is driving it and you are looking somewhere else. The logo is not shrunk, covered or cut. The page itself is not marked at all: a border round your application would be our furniture in your room. The colour is deliberately not a verdict. Green, red and amber already mean passed, broken and warning in the findings list, and «the agent may act here» is a state that deserves attention rather than reassurance. Two more in the same release. The panel’s Audit button now runs the full axe-core rule set (the same one our site checker uses) and keeps the results axe could not decide as their own group, because in an audit those are precisely the places a human has to go and look. And an agent can now work a canvas: click and drag by coordinate in Figma, Miro, maps and chart editors, where everything is drawn inside one element and there is nothing to name.
Qiksy Bridge 1.32.0 · one switch for the site, not one per tab
Switching “Agent drives this tab” on has recorded the SITE for a while, so a tab that lands on it joins the session by itself. But that was hooked to navigation, and a tab already sitting on the site when the switch was flipped was never re-examined: it stayed outside, showing an off switch. That is the case that matters: a person spreads the app across tabs first and switches the agent on afterwards, so the tabs the feature existed for were exactly the ones it missed. The gesture now reaches every tab on that site at once, in both directions. Two blind spots of the same kind are closed with it: tab numbers die with the browser while the remembered site does not, so after a restart the site read as “on” with an empty session; and bringing a tab to the front (the moment you actually look at the switch) was never a checkpoint. The key stays the site rather than the domain. One deliberate gesture on a dev host must not quietly grant a company’s whole web estate, so a sibling host, the other scheme and a different port each stay separate.
Jig 1.6.0 · the report you hand over, and the evidence that makes a ticket reproducible
A test session now ends the way an audit already did: one self-contained HTML file, with the screenshots inside it. You write your own conclusion into the report itself, sign it, and turn it into a PDF a screen reader walks as a document rather than meeting as a picture. The text lives beside the report as markdown, so it survives every rebuild. Jig asks whether a report is wanted before the work starts, not after, because a report is built from what was collected along the way, and the honest moment to decide is at the beginning. Evidence got the two things a returned ticket asks for. A shot of Jig itself (panels and all, with the page inside) shows WHERE the failure is visible: the network row that came back 500, the open finding. A clip of the last twenty seconds shows what the person DID; it is a ring rather than a recording, because you remember to record after something breaks. Both go to the developer’s ticket and never into the client report: pixels are not redacted and cannot be. Any screenshot also copies to the clipboard as an image now, so it pastes straight into a chat. One security fix worth naming: a finding’s console lines and failed requests were not being redacted at all, so a token could ride into a ticket, a clipboard or Jira in the clear. They are cleaned now, the same way the rest of a finding always was.
The measurement, published · ten million silent places, and the 299 shapes they come in
We swept 275,292 pages across 30,541 sites in 93 country domains and counted every element that reaches a screen reader with no accessible name. There were 10,390,627 of them. The useful part is not the size: they collapse into 1,937 shapes, and 299 of those recur across twenty-five sites or more. The most common one is an icon-only control, a button whose entire content is one svg: 2,220,904 times on 16,699 sites. A number that large is unusable; a shape is something a developer can go and fix. A second and smaller corpus records what the engine actually repaired, with the name it produced: 277,197 repairs. We drew 200 at random and judged every one by hand. 77.5% were correct, 19% were harmless but useless, and 1% were wrong. Both wrong ones are named on the page, because they are a class and not an accident. Everything is on /access/data/, including what the numbers cannot mean: neither corpus has a denominator, so no share of the web follows from either. The raw files and the script that prints every figure are there too, so anyone can disagree with us using our own data.
Qiksy Bridge 1.31.0 · the full-page shot follows what actually scrolls
On an application shell (fixed header, fixed sidebar, content in its own scrolling block) the document does not scroll at all. Asked how tall the page is, it answers “one screen”, and it answers truthfully: that is its real height. The full-page capture believed it, took one screenful and reported success, which is the worst shape a bug can have. Found on a live admin portal. The shell is now let out of its box for the capture: the height limits come off the scrolling block and off every ancestor holding it, the whole page lays out in the document, and the picture comes back with the header and the sidebar in it: the page as it would print. Everything touched is inline style, remembered exactly and put back. Where a shell cannot be let out, the block itself is photographed at full height and the panel says so, because a picture without the sidebar is correct and reads as broken when nobody mentions it.
Qiksy Bridge 1.30.0 · a picture of the whole page, marks on it, and screen recording
A new Screenshot tab in the panel takes the page as a picture: the WHOLE page, top to bottom, however long it is. The browser only hands an extension the visible area, so the page is photographed the way a person would do it: scrolled, a screenful at a time, stitched into one file, with a sticky header kept once at the top instead of printed down the side. Password and card fields are re-covered on every screenful, because masks drawn once would drift with the scroll and photograph a real password two screens down. On top of that picture you can draw: boxes, arrows and captions in five colours, with undo. The marks are burned into the file when you save, so what you attach to the ticket is what you drew. Beside it, screen recording, straight to MP4, which plays in Slack, Jira, Teams, QuickTime and Windows’ own player with nothing installed. Two minutes maximum, pause and resume, your voice through the microphone if you want it, and while a take runs the Qiksy button becomes the stop button with the clock and the file’s size on it. Ask for “this tab only” and the browser films the page and nothing painted over it, so Qiksy itself is not in the video; the panel says which of the two you actually got rather than promising it. Nothing is stored: a picture and a recording live only while they are on screen. And no new permissions: screen capture and the microphone are asked for by the browser itself, with its own dialog, at the moment of use. Agents can take the full-page picture too, through qiksy-mcp 1.30.0; recording deliberately cannot be driven by one, because both cameras open the browser’s own picker and a person answers it.
The report a tester hands over, and what it costs
The Jig page has a new section about the thing the work actually ends in: the report. Three steps of one file: a self-contained HTML document, the tester’s own conclusion written into it by hand, and a PDF a screen reader can still walk. Each profession gets its own version of it: the auditor reads about coverage of a whole site, the developer about JUnit sitting in the build, the analyst about CSV. The same page now also says where the paid line falls in accessibility, because until today it said the WCAG audit was free and left it at that. An audit of a page stays free forever, and so does the Tab-order walk, contrast, the form map and the crawl of the whole site. What is paid is the conformance report for the whole project, the one an auditor sells on. And a line about the second run, which is where Jig stops being a browser. Playwright opens a fresh empty browser and works the page out again every time; Jig drives the page already open in front of you, already signed in, and remembers: a procedure per control, the order a form takes values in, the scenario with its steps. When a scenario stops matching the page it says whether the scenario went stale or the build broke, instead of failing red either way.
Jig 1.5.0 · the first screen stopped talking about itself
On a first launch Jig used to show four tiles, three of which asked about Jig: what can you do, where do I start, show me how you work. The fourth, “show me what you see on this page”, could not be carried out, because there was no page yet. Now it asks for an address and shows what it sees: how many forms and fields, how many controls the keyboard can reach, what the first Tab lands on, how many accessibility problems and where contrast is worst. No project, no folder, no choice of profession, and no AI needed, because Jig measures all of that itself. It never modifies the page. Two more things opened up. The setup ladder now lives inside a project, because that is what it orders: that project’s folder, roles and report signature; outside a project there is nothing to ask, so an empty screen is just a chat and a browser. And a project can be named in words: “call this project Payments”, after which the name is also its address from any other chat. Fixed along the way: the starter checklist was never created for an auditor; a new project’s profession did not reach the window if you had answered that question before; the focus ring was clipped at the bottom of the conversation and in three places in the markup view; a draft report overwrote a finished one. Also fixed here on the site: the Windows update channel had never answered at all. An installed copy asked on every launch and was told “nothing new”, because the release manifest only carried the two Mac builds, and a silent channel looks exactly like a healthy one.
Legato 0.3.89 · the hole in the loop was the cure, not the disease
Looping backgrounds in the Atmosphere (rain, wind, a brook) had a hole at the seam: the sound dropped almost to nothing and came back. What made it was the fix. A layer played as two voices crossing over by volume, and two independent voices add up by POWER, not by amplitude: half of one plus half of the other is three decibels quieter than one whole. The crossfade WAS the hole, once every cycle. Now the tail of each recording is mixed into its own beginning once, the buffer closes on itself, and the loop joins sample by sample. Measured on a steady signal, so the recording’s own breathing could not confuse the result: the old way dipped 3.2 decibels, the new one stays within 0.4. The second fix is about answering what somebody picked. Choosing more animals did not make them speak more often: the pause shortened for one or two voices and then stopped changing, so forty chosen animals sounded exactly as rare as four. The pause is now divided by the square root of how many were chosen, while a single bird keeps its own pace so it does not disappear into silence.
You could select all forty-four animals and hear only the brook
Three faults, each measured rather than guessed. The room was mixed far too quietly. At its loudest, midday, the leading layer peaked at −38 dBFS (about one and a half percent of full scale) and the brook, at −32, was the loudest thing in the valley. That this was a mistake and not a taste is settled by the valley’s own output chain: it ends in a gentle compressor set at −24 and a safety limiter at −8, both built for a signal in that range, and at −38 the first one never engaged at all. Everything is now 15 dB louder, with the balance between layers untouched; the loudest burst in the whole library arrives at the limiter at −11.7, so nothing clips. Animal voices did not get more frequent as you added animals. The gap between them shortened only when one or two were selected; from four upwards it was fixed, so forty-four animals sounded exactly as sparse as four: one voice every two minutes. The gap is now divided by the number of residents that are awake at this hour (by its root, not the number itself, which would give a voice every two seconds). At dusk, with everything selected, that is 5.7 voices a minute instead of 0.5; a single animal on its own is unchanged. And some layers were below hearing. Distance costs a layer up to 14 dB before anything else applies, so frogs came out at −54 against the brook’s −32: twenty-one decibels apart inside one environment. A layer someone ticked, in its own hour, may now sit at most 12 dB below the leading one. Further still means quieter, but not absent.
The birds sang without pause, from one fixed spot
Daytime birds and the dawn chorus ran as an unbroken layer, always at the same distance and the same place in the stereo picture, so what you actually heard was a pattern repeating. Birds do not do that. The distinction that was missing is between a surrounding and a creature. Crickets, cicadas, a brook, rain, wind genuinely are continuous: there are thousands of sources and not one of them is separable. Birds come in ones, each is heard on its own, and so each has an arrival, a song and a departure. Those two layers now work that way. Each of their two voices keeps its own cycle: quiet for seven to twenty seconds, singing for nine to twenty-four, quiet again, and the cycles are independent, so sometimes two overlap and sometimes there is real silence. While a voice is quiet it is given a new place in the stereo picture and a new speed, which is heard as another bird settling somewhere else rather than the same phrase again. Nothing changed for rain, wind or the brook, which were right as they were.
Forty-four silhouettes, and now each one says what it is
The valley is populated by pressing little drawings, and a badger in outline is not a badger to anybody. Each tile did carry its name, but only in the browser’s own tooltip: it waits about a second, is drawn in the system font rather than the studio’s, and on a number of setups never appears at all. The tiles now use the same hint the rest of the studio uses, which shows straight away and looks like everything else. Hints are for a mouse. On a touch screen they stay off on purpose, because a bubble left behind after a tap is litter on a small screen, and the name is on the tile for a screen reader either way.
The rain went quiet twice a minute, and you could hear where the recording joined
Background layers (rain, wind, a brook) loop, and the loop was audible: a moment of almost-silence, then the sound again. Two separate faults, both in the machinery meant to hide the join. Each layer plays as two voices spread apart for width, and the two were cross-faded against each other so that whichever one was at its join would be turned down. Adding two unrelated sounds does not work that way: half of one plus half of the other is three decibels quieter than either at full, so the crossfade itself was the dip, twice every loop. And it was aimed at the wrong moment anyway: the two voices run at slightly different speeds, so their joins drift, while the fade was timed off the scene clock and hit them only by accident. The join is now closed inside the recording instead of over it: its tail is mixed into its own head once, when the layer is built, so the sound meets itself exactly. The voices then simply hold steady. Measured on the real files, the seam on the bare-wind layer was six times the size of an ordinary step between neighbouring samples; it is now the size of an ordinary one.
An iPhone was playing none of it · the side switch was silencing the whole page
Sound on an iPhone was simply absent: no animals, no weather, no melody. The cause is a rule of the phone rather than a bug in the page. Safari files a page’s Web Audio under the ringer, so the little switch on the side of the phone (the one people leave on for meetings and forget) mutes it along with the ringtone. Meanwhile the same person has music playing in their headphones and every reason to think their sound is fine. There is an official way to say «this is playback, not a ringtone», and the page was already using it, but it only exists from iOS 17, and even there it does not always carry. What does carry, on every version, is an audio track that is actually playing: while one is running, the phone files the whole page as playback. So the page now keeps four tenths of a second of silence looping, seven hundred bytes of it, for as long as the sound is switched on. Switch the sound off and it stops, because otherwise the phone would keep showing a silent site on the lock screen as if it were a song.
On an iPhone the menu would not close, and the contact form opened see-through
Two faults on the phone, one cause between them. Safari on iOS only sends mouse and click events from an element it judges to be clickable, and a plain overlay is not one. So tapping beside the open menu did nothing at all: the menu stayed put, with no way out of it, and tapping outside the contact form did not close that either. Both now listen for the press itself rather than for a click Safari may never send. The contact form also opened transparent, with the page showing straight through it. Its entrance animation faded the whole card in, and under an iOS blur that fade can stall partway, leaving a half-visible window and nothing the reader can do about it. The card no longer animates its own transparency, and its background is now declared twice, so a colour the browser cannot work out leaves a plain one standing instead of nothing.
The six background melodies stopped throbbing, and moved further off
The melodies you can put behind your reading (pentatonic, raga, hang, Japanese, choral, singing bowls) had an unpleasant wobble on every long note, and they sat closer than they should. The wobble was beating. Each mode carried a partial almost in unison with the note (1.004 to 1.011 times its pitch) at almost the same loudness, and two close frequencies at equal loudness swing the sound in and out by 99 percent. The ear does not hear that as shimmer, it hears it as out of tune. Those partials are quieter now, so the swing is half to three quarters instead of all of it. The singing bowls keep more of theirs than the rest: the beating is what makes a bowl a bowl. Distance is not one number either. Turning only the volume down gives you the same music beside your ear, played softly. So the melody is quieter, darker at the top, arrives more by reflection than directly, and starts a little later than the sound around it, which is what far away is actually made of.
The About page now says where we are from, instead of what we are living through
The page used to mention that the work happens during a war, and then said nothing else about the country. That is a poor trade: it asks for sympathy and tells you nothing you can use. It has been replaced by a section about Ukraine: the largest country entirely within Europe, with a software industry among the biggest on the continent, the first state to give a digital passport the same legal standing as the paper one, and the place the tune you know as «Carol of the Bells» was written in 1916 as Leontovych’s «Shchedryk». That carol is on the page now, with folk ornament drawn alongside it: kalyna, the endless line, a paper-cut. It does not start by itself: you press play, and there is a button to stop it. Autoplaying audio is a plain accessibility failure (WCAG 1.4.2), and a studio that sells accessibility tools does not get to make that mistake on its own About page. One fix that reaches further than this page: Tailwind’s reset was flattening every heading weight to normal across all five legal pages, so a top-level heading and a section heading read as the same thing. They have their own weights back.
Legato 0.3.88 · the thirty steps you walk every month, walked for you
Paying a utility bill, ordering the same groceries, sending a meter reading: thirty or forty steps walked by touch every single time, because the layout cannot be seen and a screen reader remembers nothing between visits. Walk that path once with the recording on, give it a name, and from then on the browser leads: it opens the pages, presses what you pressed and fills what you filled. It is a guide, not an autopilot. It knows the way; it does not know the decisions. So it stops at every place where you are needed (a password, a sum, a code from a text message) and it never presses what cannot be undone. Passwords are not stored at all: it stands on the field, says that your password goes here, and waits. A routine can be saved to a file and handed to somebody else; the file holds the path and nothing you typed into it. Sites get rebuilt, and a routine recorded in March can stop in April when “Pay” becomes “Go to payment”. The browser used to stop dead there. Now it can name the closest thing it found and ask whether to use it: it asks, you decide, and it still refuses to press anything irreversible. One fix that mattered for sighted people: the browser announced that a screen reader was running when none was. It asked a flag that only means somebody requested the accessibility tree (a debugger or an automation tool will do) and the flag never went back down. It now asks the system itself, on macOS, Windows and Linux. And the Atmosphere got quieter in the right way. Four background recordings were made again; the old wind was not louder than the rain, it was hissier, and a broad hiss is heard as something right beside your ear however far you turn it down. Rare voices also stopped arriving on a beat, because an even interval is worked out by the ear after three repeats, and after that you are waiting for the next one, which is your attention taken.
Jig 1.4.3 · a blind auditor can now reach the violation, not only hear it named
An accessibility audit names what is wrong, and for someone who cannot see the screen that is where the work used to stop. They heard «two blocking issues» and had no way to get to them: between the list and the element on the page there was nothing. Findings now sit in a list one at a time, and Enter takes you to the finding on the page itself. About half of them are nodes that cannot take keyboard focus at all: an image with no alternative text, a heading at the wrong level, a table cell. Giving those a tab stop would change the page under test, which is the very thing the auditor is measuring, so instead such a node says the way to itself out loud: which landmark it sits in, and which tab stop comes after it. Measured on real NVDA on Windows, the sentence reads: «h4, not a tab stop. It sits in main. Nearest stop after it: 39 of 55.» Coming back works too. The panel key pressed from inside the page used to close the report. People press it to return to the list, so now it only ever takes you in. Separately: settings, open tabs, window size, connected servers and the mailbox were written straight over the live file and silently fell back to defaults if the file could not be read. An interrupted write lost all of it without a trace. Writes are atomic now, and an unreadable file is kept aside instead of being overwritten. Sites behind Cloudflare also stopped refusing Jig, including w3.org, the source of the accessibility rules themselves.
The valley has seventy-four voices, and now says so
The voice board announced forty-four while the valley had long had seventy-four. On a phone the valley was silent altogether, and the board drew squashed squares instead of tiles. A yard you have built can now be saved under a name and brought back with one press, so the one you liked is no longer lost the moment you make another. The beast’s volume is set from the recording itself rather than from a guess.
The manual now covers Atmosphere, and says the Windows keys once instead of never
The reference at qiksy.app/legato/docs described four things on the browser’s fun shelf and left out the fifth. Atmosphere shipped, was written up in the release notes, and then had nowhere that said where it lives, what the three buttons above the list do, or that the sound keeps playing after you close the page it was chosen on. It has its own entry now. The same page named fifty keyboard shortcuts and gave the Windows equivalent for five of them. Every one of the browser’s sixty-eight shortcuts is bound as Cmd-or-Ctrl, with no exceptions, so the rule is now stated once at the top (where this says Cmd, Windows and Linux use Ctrl in the same place) and the brackets after individual shortcuts are gone. Read out loud, those brackets doubled the length of every instruction. Inside the browser, the Help menu now has a way in: How to Use Legato opens the manual in the browser’s own language. Until today it had no link to it at all, so the only way to find a hundred pages of instructions was to happen upon the website. The release notes page also gained a version index, and the paragraphs across the Legato pages are no longer capped at a narrow reading measure. All of that is now in every one of the twenty-five languages the manual is written in, not only in English. The translated files are positional, so a section added in the middle could not simply be topped up, so all twenty-four were built again.
Legato 0.3.87 · a place to sit in, and a card number that is no longer read out loud
Two things were broken and are now fixed. A card number typed into a checkout form was read aloud and written into the browser’s own notes: only fields marked as passwords were masked, and card fields are not. They are masked now, by name and by the browser’s autocomplete hint, in the reading and in what is stored. And a slider (volume, speech rate, zoom) said nothing at all while you dragged it with the mouse; the value only arrived when you let go, which is the one moment it is no longer useful. It now names the value as you move, starting from where you grabbed it. The new part is Atmosphere: eighty-three recordings (rain, a brook, wind, crickets, an owl somewhere far off, animals from a farmyard and from far away) that play quietly while you read and go quiet while the browser speaks. Press one and you hear it once, close and clear, which is also how a child can learn what a cow or a lion sounds like. One button assembles a set from your own clock and keeps following it: dawn birds in the morning, crickets and an owl at night. We never ask where you are, because the clock already knows your time zone. Six melodies are made up as they go, so they never repeat and never end. Your own sets can be saved by name. Reading also got two things it lacked: a list of the page’s headings you can jump from, and a shelf of what you started reading and did not finish.
Jig 1.4.2 · a working day driven with the keyboard alone, and an audit that can be handed to a client
This release was written against a screen reader rather than a checklist. Moving between the page under test and Jig is now one key that swings back to where you were, the focus returns to the control that opened a panel instead of the top of the window, reading mode belongs to the file it was started in and steps aside when you leave, and the shortcut list says how to get out of itself, because NVDA keeps Escape for its own use, so a dialog that only closes on Escape does not close at all. More than half of the spoken announcements used to interrupt each other mid-word; they now wait their turn. On the audit side a WCAG criterion number now reaches the finding it belongs to, a defect found in somebody else’s embedded banner no longer leaves as a defect of the client’s site, and the audit no longer reports as satisfied the very criterion it just found broken. For teams: what Jig remembers about widgets can now be carried between machines without the client’s internal host names leaving the building, or, with a company exchange address, without leaving the company network at all; every verb the assistant runs is written to a local, non-optional action log that keeps no query strings; and reports and Jira tickets can now be taken from an editor rather than only from the dialog in front of a person. The first screen now also asks how you prefer to work (screen and mouse, with a screen reader, or poor sight) and turns on what that answer needs, because a switch nobody knows about does not exist. On the download page every row of buttons now offers the Microsoft Store beside the direct installer: the direct file meets a Windows warning screen, the Store package is signed by Microsoft and does not.
A Qiksy link sent into a chat now looks like the product it opens
Every landing had a link preview, and every preview was a photograph of its own first screen. That answered "what am I about to open" with the look of the page, which is honest but not recognisable: at the size a chat draws a card, one dark hero looks much like another. All nineteen are now the branded card the videos open with: the mark, the name, one line about the product and the address. The two products a person installs rather than visits carry no prefix: Legato comes with its own mark, and Jig with its own name, because that is what they are called. The lines on the cards were not written for the occasion: each is the sentence the catalogue and the studio already use, so a card cannot promise something the product page does not.
A link you can send to one particular person, and every preview picture re-shot
The Bridge landing already read four ways, but only for a human who clicked: a query string cannot carry a title or a picture into a chat, because Telegram, Slack and LinkedIn read the HTML of the first response and run no JavaScript at all. So each reading now has an address of its own (/qa-copilot/for-developers/, /for-manual-testing/, /for-automation/, /for-accessibility/) with its own head, its own preview picture and its own line in the sitemap, the same machinery the Jig landing has. The page reads the profession from the path before the query and before what it remembered, because the path is what the crawler was served. And while we were there: every link-preview picture on the site was a photograph from 14 August, taken before half of this year’s heroes existed. All twenty were re-shot, plus the catalogue card for Bridge, which was still showing a headline the product no longer uses.
The page now asks what you do, and answers that question instead of the average one
One product genuinely answers four different questions, and a single headline can only answer one of them: a developer wants the agent in the tab they are already signed into, someone testing by hand wants thirty fields filled in one press, an automation engineer wants the runs a script cannot reach, and an accessibility auditor wants the page as a screen reader actually receives it. Above the headline there are now four chips, the same idea the Jig landing has had for a week, and picking one swaps the headline, the lead and the accent colour of the page. The choice is read before the first paint, so nothing swaps in front of you, and it is remembered, and a link can carry it: ?for=coder, ?for=manual, ?for=sdet, ?for=access. Written in all seven languages rather than English with six machine copies. The old "Build FAST · Test SMART" badge came off the hero while we were there: the same line already sits in the footer, and two rows of pills above one headline were arguing with each other.
QA Copilot is now Qiksy Bridge, and the pages finally say so
The extension was renamed in the Chrome Web Store and passed review, but the landing and the documentation kept the old name, including the documentation page we link in every letter we send, which greeted people with a product they could no longer find in the store. Both now read Qiksy Bridge, in all seven languages. The word "copilot" is gone from the copy as well: it was the reason for the rename in the first place, so leaving it as a figure of speech on the first screen made no sense. The documentation header also carries the real Qiksy logo now, instead of a lightning bolt drawn inline in the markup that matched nothing else we ship.
Two switches promised silence and did not deliver it, and without sight you cannot catch that
A switch that does not switch the thing off is worse than no switch at all: you turn it off, hear the same phrase again, and the only conclusion available to you is that you pressed the wrong thing. "Announce repair status out loud" silenced five neighbouring announcements and never the one named under it, because the phrase was built in one place and read out in another, and the second place had never heard of the setting. The tick that steps you through the page menu ignored the sound switch entirely, so turning sound off in a library or beside a sleeping child still left you hearing it. Both are fixed, and so are two more places where the browser talked into an empty room: Control now clears the announcements a page had queued, instead of falling silent and then speaking again a second and a half later, and a background tab no longer chimes at you from a page you are not reading. You can also ask a site which words you gave it, since naming someone else’s button "the cart" has worked for a while, but forgetting your own word got you "nothing here is called the cart", which tells the person who did the naming that the work never happened. An unfinished postcard now survives the tab it was written in. And the seam between the pieces of a spoken phrase is even, so the voice stops going in jerks where nothing was wrong with the page.
The extension changed its name, because the old one put it on a shelf with nothing on it
It is called Qiksy Bridge now, and the store title says what it does: a browser MCP extension for Claude, Cursor and Codex. The old name led with manual QA, and the page led with it too, so people read it as a form filler and left. The bridge, which is the whole point, was the hundred and first word; MCP was the six hundred and sixty-eighth. We measured before renaming rather than after: the store search for "qa copilot" carries sixty-two installs across six cards, thirteen of them ours, while the search for "mcp" carries around a hundred and twenty-six thousand. Our own phrases for what we do, "use my logged in browser" and "existing chrome session", return no search suggestions at all. Nobody types them. The front page now opens with the thing itself: an MCP server for the tab you already have open, with your session and your logins, and the honest difference from Playwright MCP, which starts an empty browser and signs in from scratch. Nothing about the product changed, and the extension keeps working with no agent at all. The new listing is with Google for review.
The Legato reference now speaks the twenty-five languages the browser does
The feature reference was English only while the landing beside it shipped in twenty-five languages, and the gap was not a matter of politeness: a screen reader picks its voice from the page’s declared language, so English text under a Polish or Japanese code is read through the wrong phonetics. Somebody could read why the browser exists in their own language and hit a wall the moment they wanted to know how it works. The page also doubled, twelve sections to twenty-two, because a good deal of the browser had never been written down: reading a page with the arrow keys existed only as one line in a table of shortcuts, and copying a piece of a page, the mouse wheel that walks instead of scrolling, the shelf of games, the shop card, the braille setting and the seventeen page fixes for low vision were not there at all. Two faults turned up in the translating and both were the same shape. The browser says «reader» out loud in Russian and the translation wrote the technical loanword instead: correct, and a different word for the same thing than the one the product uses. And the page quotes seventy-five menu items while promising you will find them under exactly that name: agreement ran from 38 % in Japanese to 70 % in Hungarian, so a sighted reader would have checked against the screen in a second and a blind one would have hunted for an item that is not there. Both are now taken from the browser’s own dictionary rather than translated afresh, agreement is 96–100 %, and a gate holds it there.
Copying a piece of a page, without being able to see where the piece ends
Selecting text is a mouse gesture, and every workaround a blind person has for it is awkward: a text cursor whose keys clash with reading, the screen reader’s own markers, or select-all, which takes the menu and the cookie notice too. None of the three tells you what you took; you find that out after pasting it somewhere else. Legato 0.3.84 answers the copy shortcut itself, and only when nothing on the page is selected, so the ordinary behaviour is untouched. Draw a frame with the mouse around a piece and it works out the block from what fell inside, with no need to hit the edges of a paragraph you cannot see. Or press S where the piece starts, walk to where it ends, and copy. Then it reads back what it took: a short piece in full, a long one by its first words and its last, which answers both “is this the right piece” and “did I take too much”. While a start is marked, each step makes a quiet click: the mark is alive and the step counted. The same release fixes something the work uncovered: on a page that grew above where you were standing, the down arrow moved you up.
The globe on the Route page did not exist for a screen reader
The planet is the first thing on that page, you can click cities on it and watch a route stretch between them, and to a screen reader it was nothing at all: a canvas marked as decoration, on the grounds that the city names underneath were being read out anyway. Those names were, but the thing itself was not, so someone listening heard “Kyiv to Barcelona” arrive from nowhere. It is now described the way a person would describe it: a planet turning slowly, blue water, milk-coloured land, and no continents or borders drawn on it: one Earth, the same for everyone. The description also names what is missing rather than leaving it to be discovered. And the cities are reachable now: the same ones the globe shows are real buttons, one stop on the keyboard route with the arrow keys moving between them, invisible until focus lands on one. They call exactly the code a mouse click calls, so both ways of picking a route can never drift apart.
Every Legato release that ever reached anyone is now written down
The notes page went from eleven versions to twenty, all the way back to 0.3.52, published on 19 August 2026, which is the first build that reached a person at all. Nothing is missing before it, and the page says so instead of trailing off. Versions that were built and handed to nobody are named and excluded, because they are not part of what anyone has. The biggest entry is 0.3.64, with two hundred and forty-nine changes, and the release where the browser stopped only reading pages out and started having things to do in it: a shelf of games with backgammon built to be played by ear (both dice in one keypress, a refused move that explains itself, network play that Windows and a Mac completed against each other), a family tree walked with the keys, routes that replay a path through a site, and a large-text switch. Forty-six topics and a hundred and fifty-one lines in total, each one traceable to a build somebody actually received.
The lower half of the landing page now uses the width it was given
Those sections ran in a column narrower than the header above them, with the right third of the page empty. They are on the full container width now, the same line the header sits on. The width went to the BLOCKS rather than to the prose: what Windows and what macOS say on first launch now stand side by side instead of one under the other, the three checksums are three cards in a row, and the list of what the browser cannot do runs three across. Paragraphs keep their reading measure of about 65 characters, deliberately, because filling 1080 pixels with prose would mean lines of a hundred and fifty characters, and this is a page for people with low vision. So the page fills its width without a single line getting longer.
The lower half of the landing page looked like a column had fallen off
It had two faults and they compounded. The narrow column (six consecutive sections, everything from "How to install" down) was pinned to the left edge of the wide container, on the reasoning that a centred column would make the text jump sideways while scrolling. True, but the price was worse: the whole bottom of the page sat against the left edge with the right third empty. It is centred now, and the jump happens twice, at the two joins, instead of being permanent. The second fault was inside that column: it was 680px wide while the text in it is capped at 68 characters (measured live, 476px) so cards and quote rules ran two hundred pixels past their own content. The container now sits on the width that actually lives in it; the line length did not change by a single character. And one section had a short note beside a tall column of text, leaving six hundred pixels of nothing under it; the note is centred in its column now and reads as the aside it is.
The release notes page now covers twelve releases, not two
It started at 0.3.82 with a note saying the earlier ones had never been written down and that reconstructing them from commit messages would produce something plausible rather than something true. There was an honest way to do it after all: go by the release tags rather than the branch, by what people actually received. So 0.3.72 is absent, because the version was bumped and never shipped to anyone, and the quit-key fix sits in 0.3.83 even though the branch would file it under 0.3.82, because it landed after 0.3.82 was already out. The nine reconstructed entries are deliberately shorter than the two newest: a fault is named, not narrated. Among them are pages freezing for seven seconds, a Portuguese page read with Russian sounds, a screen reader handed the bare word "collapsed" with nothing to say what was collapsed, and Arabic arriving as the twenty-fifth language and the first read right to left.
A release notes page, because a blind tester had no way of knowing what to re-test
Mehdi Malakane updates the browser and then has to guess what changed. He asked for the model NVDA uses: a What’s New item in the Help menu that opens a versioned page, with the version number as a heading so a screen reader’s heading list becomes the table of contents. It is now at qiksy.app/legato/whats-new/ and the menu item opens it at YOUR version rather than the top. It starts at 0.3.82, which is the first release whose notes were actually written down, because reconstructing the earlier ones from commit messages would produce something plausible rather than something true, and the page says so out loud. 0.3.83 is on it and is out: the ring menu no longer swallows the quit shortcut, it no longer hides the whole browser on the light theme, and the backdrop behind it is dark enough to see.
A release notes page, because a blind tester had no way of knowing what to re-test
Mehdi Malakane updates the browser and then has to guess what changed. He asked for the model NVDA uses: a What’s New item in the Help menu that opens a versioned page, with the version number as a heading so a screen reader’s heading list becomes the table of contents. It is now at qiksy.app/legato/whats-new/ and the menu item opens it at YOUR version rather than the top. It starts at 0.3.82, which is the first release whose notes were actually written down, because reconstructing the earlier ones from commit messages would produce something plausible rather than something true, and the page says so out loud. 0.3.83 is on it and is out: the ring menu no longer swallows the quit shortcut, it no longer hides the whole browser on the light theme, and the backdrop behind it is dark enough to see.
Engine 1.12.0 · the first build an update can actually reach
Published to the registry. It is the first version that tells the tools which version it is, which is what makes the new update notice possible at all: until now nothing on the page could tell a current engine from one installed months ago. It is also the first build whose autostart cannot be left pointing at a directory that gets cleaned: installing with npx used to pin the entry inside the npm cache, and when that cache was cleared the engine quietly stopped starting. Anyone already running an older engine will not be told about this one, because being told requires the version reporting that arrives with it; from here on the notice works. Update it with one line in a terminal: npx qiksy@latest.
On dark backgrounds the accent colour was being used as text, and it was too dark to read
A palette has two blues in it, not one: a fill colour, judged against a lower bar because nobody reads a button’s background, and a text colour that has to clear the full contrast threshold. Across the Route and Offer pages the fill colour had been used for text in a dozen places (step numbers, badges, links in the product strip, the duration label in a timeline) and on a dark background it landed between 2.8 and 4.4 against a requirement of 4.5. Every one of them now uses the colour meant for text, which lightens in dark instead of darkening. The worst of the set was the product name beside the logo: white on a light blue pill, 1.76 to 1, the first thing anyone reads on the page. Its fill had been switched to a light one without switching the ink to match. And the check itself got better at explaining: it already knew the two colours and the exact ratio for every failure and printed neither, so fixing one started with half an hour of hunting through tokens. It says the numbers now.
The walkthrough’s steps were invisible until their animation had played
Each step of the demo on the Route page faded in, and it did that by starting at zero opacity and animating up. That is fine while the animation plays, and the trouble is that "while" is an assumption. A tab that has been throttled, a machine saving battery, a mistake in a neighbouring rule: any of those and the step never becomes visible at all. The accessibility check caught the page in exactly that state and counted 392 elements with no contrast across fourteen pages: text on top of invisible text. The movement stayed; the fade went. It looks the same and it can no longer leave content that nobody can read.
Updates to the local engine were reaching nobody who had already installed it
The engine runs on your own machine, and once it was installed it stayed exactly as it was, for good. Three separate reasons, each enough on its own: the autostart entry pins the absolute path of the copy that installed it and runs that file forever; there was no version check anywhere, not in the engine and not in what it tells the page; and the install command only fetches a newer build when somebody types it, which the person who set up autostart never does again. So a published fix sat in the registry and never travelled. The engine now reports its own version, the page knows which one it expects, and when they differ it says so once: a line you can dismiss, and a permanent one in each tool’s settings for when you come back to it. It still never updates itself: it is holding running searches and your Claude sign-in, and software that quietly replaces itself underneath a search in progress will one day cost somebody an hour with no explanation. Two things that made this worse are gone too. Rebuilding the engine refreshed its tools but never the supervisor that starts them, so a fix to that half could not reach an installed engine at all. And for anyone who installed with npx, the autostart pointed inside the npm cache (a directory that gets cleaned) after which the engine silently stopped coming up and the tool simply said the local server was not running.
The live search feed flickered a new border into view every second
While the agents hunt, the feed adds a line every second or two, and each new line arrived carrying two fresh borders with it: a divider above itself and a box around its icon. On a still mockup that reads as a tidy grid. In a feed that is actually moving it reads as flicker, in the corner of the eye, exactly where someone is waiting for a result rather than admiring the layout. Both are gone; the one piece of movement that means something (the pulse on the line being worked on right now) stays. The feed also ends where it should now, with no doubled line at the seam where it meets the results below, and the button that adds a country is the same height as the country chips it stands beside, instead of eight pixels taller than the row it belongs to.
Opened outside the studio, Route and Offer looked like somebody else’s products
The colour you pick applies to everything, background, borders, every active element, and it was reaching only the pages the studio shell draws. Open the same tool on its own address and a different palette took over: not a worse arrangement of the same colours, a different set entirely, written years apart and hardest to read in dark mode. Both tools now carry the colour, the light/dark choice and the classic/modern style outside exactly as they do inside, and they carry it from the first painted frame rather than repainting it in front of you. Two things that only existed in the shell came out with it: how much of the Claude subscription is left, in the session and weekly rings, with the real figures Claude itself reports, and whether the agent is answering at all, which Offer had never shown anywhere. And because four appearance switches in a row had grown wider than the tool’s own menu and had started colliding with it, they now live together under one settings button, leaving the header to say what a working tool should: is it running, and how much is left.
Legato 0.3.83 · the ring menu you could not get out of
Open the ring menu with the right button, then try to close the browser: nothing happened, and the menu would not close either. The ring lives in a frameless window of its own that takes the keyboard, and application-menu shortcuts were not reaching past it: Escape worked, because the menu handles that itself, but Command-Q did not. Measured with a clean control: same window, same state, the ring open and Command-Q does nothing; press Escape and the same key quits. Fixed for all five of our own windows, the ring, the menu card, the tour, the account card and the extensions card, because all five had the same hole, and it quits the ordinary way, so the session, history and downloads are written to disk exactly as on a normal quit. Closing the window now takes the ring with it, and whatever asked for the menu gets its refusal: a site that had requested to share your screen used to wait forever. Two things about how the ring looks, both reported from a real screen: on the light theme it was painting a solid sheet over the entire browser: no toolbar, no tabs, no page, just a blank field with the circles in it, measured at full opacity across the whole window; and the disc behind the circles was tinted with the theme’s own background, which on a dark page is dark over dark, so it was not visible at all. It is darkened with black now, which works on any page, and the page still shows through. And the Help menu has a «What’s New» item that opens the release notes at YOUR version, since the update channel has existed since 0.3.20 and had never once said what it delivered.
While the engine was being checked, the status pill said nothing at all
The pill in the Route header had two states, connected and not connected, and the first seconds of every page load belong to neither: the answer has not come back yet, so nothing is known. The label was simply left empty in that gap, which meant a grey dot with no word beside it, and the honest-looking alternative would have been worse, “agent disconnected” announces a fault that may not exist. The gap is longest right after a reload, because that is when the engine is still starting the Claude CLI. There is now a third state that says what is actually happening: connecting, with the dot breathing quietly, a button that does not offer to repair something that has not broken yet, and nothing promised to a screen reader that the button cannot do. The pulse stops for anyone who asked for less motion.
The header stopped talking about money and started answering the question people ask
On a subscription the dollars in the header meant "this is what the work would have cost", an answer to a question nobody asked. What people actually want to know is how much of the plan is left. So the money is gone and two rings took its place: the current five-hour session and the week, with the reset time for each. These are Claude’s own percentages, not our estimate. There is no usage endpoint a subscriber can call, but the binary answers its own /usage locally and that read costs nothing, so nothing is invented and no request is spent asking. They refresh on their own every two minutes, and a screen reader is told when the state changes rather than every time a digit does.
Signing out of Claude threw you onto an installer for an engine that was already running
Route asked the machine one question, can you run the agent, and treated every answer that was not «yes» the same way: by showing the install screen. But an engine that is installed, running and merely signed out answers that question with a polite «no», so a person who signed out was handed a «Download for macOS» button and the line «we will connect as soon as it starts», on top of an engine that had already started. That is a dead end in the literal sense: the screen waits for an engine to appear, the engine has appeared, and the only place in the whole app where you can sign in to Claude sat behind a branch you could no longer reach. The other half of the same trap was in Settings, where the account card could do exactly one thing, sign out, and offered it to people who were already signed out: press it, confirm, hear «signed out», see nothing change. Somebody whose limit had run out wanted the opposite thing, and there was no way to do it from there at all. The button now says what will actually happen: not connected gets «Sign in with Claude», which starts the Anthropic sign-in on this machine and waits for the engine to come back green; connected gets the old «Switch account», still behind a confirmation, because signing out takes Claude away from everything else on the computer. The wording comes from the shared dictionary rather than new strings of its own: the same button is already named there in seven languages for the gate, and two editions of one sentence drift apart.
Settings could sign you out of Claude but never back in
The account card in Route’s settings had one button and it always meant the same thing: sign out. That is the right offer when an account is connected, because the Claude CLI has no switch and changing account really is a sign-out followed by a sign-in. It was the wrong offer to everyone else: someone whose spending limit had run out, or who had already signed out, was invited to sign out again, asked to confirm it, told it had worked, and shown no change at all, because there had been nothing to sign out of. Signing in from settings was not possible in the first place. The button now says what will happen: it offers to connect an account when none is connected and starts Anthropic’s own sign-in, and it keeps offering to switch when one is.
Signing out of Claude threw you onto an install screen for software you already had
Route asked the machine one question, can it run the agent, and treated every answer that was not yes the same way: it showed the page that explains how to install the engine. But an engine that is installed, running and simply signed out answers that question with a polite no, so anyone who signed out of Claude, or never signed in after installing, was handed a download button and the line "we connect the moment it is running", over an engine that was already running. It was a dead end in the strict sense: that screen waits for the engine to appear and it had already appeared, and the only screen in the whole app that carries the sign-in (the button, the link and the field for the code) sat behind a branch the code could never reach. Route now separates the two answers: no engine, and here is how to get one; an engine that is signed out, and here is the way in. Offer was repaired this way in July and Deal was never wrong; Route was the one left behind.
The one button on two landing pages that opens the tool opened nothing
On the Offer and Route pages the main call to action pointed at the hub with a hash, and a hash here is an id in the app registry. Both products had been renamed, so the id in the link no longer existed: the hub looked it up, got nothing back, and quietly stayed on its own home page. No error, no 404, nothing to notice: the button simply did not do the one thing it exists for, and it had been that way since the rename. The same defect was found on Route earlier the same day and this is the rest of it. The links now go straight to the product’s own prerendered address rather than through the hub, which also removes a flash that was there even when the id was right: the hub would paint its home page first and only then navigate away.
You could update the browser and have no way of learning what changed
The update channel has been in Legato since 0.3.20. What it never had was a way to say what it had just delivered: the menu item installs the new version and then goes quiet. For a sighted person that is curiosity; for a blind tester it is work with nothing to check it against. Mehdi Malakane, who tests through AppleVis, asked for the fix in one sentence and named the model himself: NVDA’s. So there is now a release notes page at /legato/whats-new/, and a «What’s New» item in the browser’s own Help menu that opens it. The structure is the whole design: the page heading names the page, every VERSION NUMBER is a heading one level down, and the topics inside a release are one level below that, so a screen reader’s heading list is the table of contents, and jumping between releases is one keystroke repeated. The menu item does not open the top of the page either: it builds an anchor from the version actually installed and lands you in your own release. We already had a changelog, this one, the page you are reading, and it is the wrong instrument for that reader: it runs by date across every product, Legato appears in it about ninety times, and no heading names a version, so answering «what is in 0.3.82» would mean listening to the whole feed. The new page starts at 0.3.82 and says so out loud rather than pretending to a history it does not have: earlier versions shipped with no notes written down, and reconstructing them from commit messages now would produce something plausible instead of something true, and this is the text people re-test against. The menu string went into all twenty-five dictionaries in the same commit, Russian and Ukrainian by hand: the menu is rebuilt from scratch on a language change, and one English line in someone else’s menu is a dead stop for a person walking it by voice. The page also carries the NEXT release already, marked in a sentence as not yet shipped, because preparing before the update arrives is the whole reason it was asked for, but somebody landing there after updating has to be able to tell «I have this» from «this is not out yet» in one line, so it is said in words rather than shown with a badge or a colour.
The page promised three minutes and blamed a finished trip for someone else’s failure
Three places where the interface said something other than what was happening. The red plate above a trip took the LAST job of any kind and printed the wording written for a failed search («the agent ran out of time, try again or narrow the trip») while the search had long finished and eight options were sitting right below it. What had actually timed out was the how-to-book lookup for ONE of them, which has a clock of its own. There was nothing to narrow, and a finished trip was being painted as a crash; the plate now names the option it is talking about and leaves the results alone. Then the numbers: «about 3 minutes» under the search button was met by NONE of the fifteen runs in the log (median 8.2 minutes, spread 6.6 to 18.2) and «usually under two minutes» on the booking lookup was met by 2 runs out of 14, median 3.8. Both are now the measured figures. That is not admitting to being slow, it is refusing to promise what we cannot keep: at the third minute of a three-minute promise a person starts believing the tool has frozen. And the last one is about language. The contents of a trip (the options, the summary, the boards) are written by the agent during the run, in the language of that run; switching the interface language moves the labels around them and deliberately leaves that text alone, because translating what an agent already said would show a retelling instead of the answer. The product never mentioned this, so a Ukrainian trip under a Spanish interface simply looked broken. It now says so twice: a quiet line on the card explaining that the contents are in the language of the search and that a fresh search brings them over, and one explanation at the moment of switching, shown only when the open trip really does contain the agent’s text, because warning about something that is not on screen teaches people to dismiss warnings unread.
Access is a page now, not a workbench, and it changed colour
The audit workbench is gone from this site. It was five screens of a tool nobody was meant to use here: the audit is work we do, and the instrument for doing it now lives in Jig, where there is an engine, projects and roles for it. What is left on qiksy.app is the page that explains the service, which is what somebody arriving here actually wants. The colour moved too, and by measurement rather than taste. Access and Check were literally the same teal, with Jig, Route, Shift and Deal a few degrees away: six products sharing one hue, so the accent had stopped telling anything apart. Red was tried and dropped for a specific reason: its hue sits one degree from the red the report uses for the instrument’s own mark, and the single red anomaly on the page would have become a shade of the brand. Green means «passed» in the report, which is a strange thing to paint a product that sells finding what did not. Plum sits in the one arc of the palette nobody else occupies, and clears the contrast threshold with room to spare. On a page that sells accessibility audits, its own page passing its own audit narrowly would be the wrong kind of close call.
Route checks the paperwork before you pay, not after
The trip you book can be the one you are turned back from. A passport that expires before the return flight; a Schengen destination that wants three months of validity after you leave, or six months in most of the rest of the world; a traveller who is still seventeen on the day of departure; a departure date closer than a visa appointment usually takes. All of that is arithmetic on dates you have already typed, and it used to surface, if at all, in a checklist generated after the booking. It now stands on the itinerary, before the payment step, because whether the passport is valid decides whether the person flies at all. What it deliberately does NOT do is rule on whether you need a visa or a vaccination: that depends on citizenship and on the whole route including transits, and the cost of a confident wrong answer is somebody stopped at a border. So instead of a verdict there are sources: CDC and WHO, both opened and checked. IATA’s Travel Centre is not among them: it answers a real Chrome with a Cloudflare interstitial and a 403, and a link that turns into a robot test for half the people who follow it is worse than no link at all. The first screen now asks whether this is business or leisure. Border rules are shown to everyone either way; the region’s recommended vaccinations are offered only on a leisure trip, because a «check your shots» panel on every business trip to Barcelona devalues itself and the warning beside it. Health is raised at all only for destinations where a certificate is genuinely asked for at passport control.
The auditor’s workbench has left the site
Qiksy Access is one page now: what an accessibility audit is, what it costs, what you get back. The workbench (the register of states, the templates, the report builder) moved into Jig, where there is an engine, projects, roles and a door an agent can work through. On a storefront it was in the way: somebody arriving to find out what an audit even is landed on an empty desk with a «new audit» button. Access sells the WORK, and the tool that work is done with had no business standing next to the price. With the workbench gone the product is also open to everybody: it had been admin-only and kept off the launcher for exactly one reason: the tile promised a click it could not honour. What stayed in that folder is the report builder’s source, and a README saying so, because Jig carries a copy of it.
The borders were different colours because they were transparent
The line down the rail, the line under the header and the lines between the chat columns all come from one token, and they still came out three different colours. The cause was not three tokens: the line was a translucent layer, so it took the colour of whatever lay under it: frosted glass under the header, the page under the rail, its own surface under a column. One colour over three grounds is three lines, and no amount of adjusting the percentage repairs that. The paint is now mixed INTO the ground rather than into nothing, in both styles. The theme still shows through, since the tint comes from the accent, so azure reads blue, violet reads lilac, garnet reads red, and it no longer washes out over glass. The same change made the third step opaque as well, which is not cosmetic there: that step draws the outlines of inputs and buttons, where the contrast is set to 3:1 for WCAG 1.4.11 and a transparent outline over glass was falling below the threshold. Then everything except that step went to half strength on the light theme, which is where the lines were loud; the dark theme is untouched. And the Access icon lost the ring around the figure, because the ring was read first and the arms inside it collapsed to a stroke, while the product header was showing a different icon from the rail for the same product.
The accessibility audit is now free, and you pay for the code work after it
We were selling the diagnosis twice: a report, then a second report about how to fix the first one, with the remediation itself in the smallest print on the page. That is inverted. The audit now costs nothing: every page type and every state, behind the login included, and the report is yours whether you fix it with us, with somebody else, or not at all. Remediation is priced per state ($120, less above 25 and above 100, minimum 20 states), acceptance is a round walked by hand and by voice by a blind specialist, and there is an hourly rate only for work outside the register. Not per hour for the fixes: one change to a design token repairs every page of its type at once, and billing that by the hour would mean charging less the better our tooling gets. The sample reports doubled in length, and it is the sections that grew rather than the prose: what states were actually opened, every page template with the defect that repeats on it, the keyboard route, the five checks no scanner can answer, an inventory of third-party frames with what to request from each vendor, a 30/60/90 plan and a draft accessibility statement. The audit of our own site came off the gallery, because every finding in it was fixed the same day, but on a storefront «13 critical» is read first and «fixed» second. Two new illustrations, and the one on the first screen is the point of the whole page: a caret walks a page fragment while the line underneath prints what a screen reader announces, and on the button with no accessible name that line goes empty. Both stop moving under prefers-reduced-motion and both come to rest showing the defect, not the happy frame.
The button that opens Route was opening the storefront instead
The link still carried the product’s old name, so the hub could not find that id and quietly showed its own home page: the one button whose job is to open the trip planner went somewhere else. Fixed. Three more things on that page, all of which had been true for a while: the route boards are no longer buried at the bottom but explained as their own section, because they answer a different question (what runs this route at all: one answer for everybody, so it is computed once and asks you for no date, no account and no engine of your own); the page now says out loud that running the agent needs a PAID Claude plan, which it had never mentioned; and the tab title finally comes from the dictionary instead of being baked in, so the Ukrainian page no longer announces itself with an English title, so a screen reader was naming the tab in one language and reading the page in another. The «copy the install prompt» button also used to rename itself to «Copied», and a label changing under focus is not announced: somebody using a screen reader pressed it and had no way to know whether it worked, on the one step without which the engine cannot be installed.
The «back to Qiksy» button on the Route pages led nowhere
The one control whose entire job is to get you back into the studio was pointing at an address that stopped existing when the app was renamed, on all seven language pages. Google found it before we did: Search Console mailed twice overnight about pages it could not index because a link 404ed. Fixed, and the build now refuses to ship a page whose internal links lead anywhere that is not in the deploy. That check was simply missing: the page rendered, its bundle was its own, its images resolved, and only the link was dead, and nothing was looking at links.
The accessibility audit is free now, and you pay for the repair, not the diagnosis
The old ladder sold paper twice. An Access Report was a verdict on what is broken; a Fix Pack was a second document about how to fix it, and it said in as many words that we do not go into your repository. The actual repair sat underneath the prices as a footnote. That is backwards, so we turned it around: the audit costs nothing, every page type, every state, and the report is yours to keep even if you fix it yourself or never fix it at all. What is paid for is the work: changes in your source, a round of acceptance with a blind specialist who actually uses a screen reader, and support after later releases. There is deliberately no price on the repair here, because the size of it comes out of the free audit, and naming a number before anyone has looked at your site would be a guess.
A trip card showed «Event: {name}» instead of the event
The badge on a trip card printed the raw placeholder rather than the name of the event. Route passes values into a phrase as a function, and this one line had been written as a plain string, so the value handed to it was dropped on the floor, in all seven languages. Fixed, and an ampersand in an event name no longer arrives doubly escaped.
Jig 1.4.1 · Enter now sends a form, and your own project instructions are read
Two of these matter more than a version number. Enter pressed in a field did not submit the form: the key went in, the reply said it had worked, and nothing happened, which meant the one tool built for accessibility work could not test the way a keyboard user actually sends a form. It does now. And a project folder that carries its own instructions (a CLAUDE.md, a set of skills under .claude/skills) is finally read: those files were invisible before, cut off together with the settings that can carry hooks. Hooks are still not loaded, and never will be: a hook is a shell command, and somebody else’s repository does not get a terminal on your machine. The text is read as text. Also in this build: a site behind a bot shield can be mapped at all (it used to come back empty), the conversation is written to disk while a run is going rather than only after it, and closing the window no longer leaves an engine running behind it.
Legato 0.3.82, and the Windows installer is not signed yet
Three installers for this version: macOS on Apple silicon and on Intel, both signed and notarized by Apple, and Windows. The Windows one is NOT signed, because our code-signing certificate has been paid for since August and is still stuck in validation. Windows will therefore show its blue «Windows protected your PC» screen, and getting past it means pressing «More info» and then «Run anyway». We would rather say that here than let you meet it without warning: for somebody using a screen reader that screen is a dead end, because nothing on it announces that a second button exists. If you are on Windows and cannot get past it, the previous signed version still works, and we will replace the file the day the certificate arrives.
A seat used to mean one more person you were allowed to help
In Qiksy Offer a seat bought one more CANDIDATE. So a recruiter with ten job seekers paid for ten seats, and a recruiter with a budget for four had to decide which six people to turn away. We were charging money to make somebody say no, and charging it for something that costs us nothing, because the searches run on the customer’s own Claude plan and never touch ours. We were rationing what is free to us, and the rationing landed on the person looking for work. Qiksy Route had the opposite fault: no seats at all, so a travel agency with five agents paid the same $290 as one person planning a family holiday, while that same five-person agency in Offer paid five times over. One kind of buyer, two contradictory logics, and neither of them measured what the customer actually gets. Both now count the same thing: a seat is a PERSON WHO DOES THE WORK, not a person who is helped. One licence carries as many candidates, clients and travellers as that person can carry; you pay for how many people at your company use the tool. Nothing about this needed inventing, because the licences worker has enforced exactly this axis since August, a seat being one person with three machines, and reassignable. We were simply selling a different thing from the one we were enforcing. Offer’s prices did not move: $129 a year for one person, $99 per seat from two, with the volume steps unchanged: only what you get for them did, and it got larger. Route gains Team at $229 per seat from two, stepping to $159 from ten seats, $109 from twenty-five and $79 from fifty, and the single-person year stays at $290. One trap surfaced while making the change and would have shipped silently: with the candidate cap lifted to unlimited, the old line that let a Team licence RAISE the cap started LOWERING it instead: a five-seat licence would have returned five where Pro now returns no limit, so buying Team would have made the product stricter than not buying it. A second was caught only by re-reading the finished diff: the sentence describing Offer lives in two places on the pricing page, the card and the prose above it, and with one of them updated the page would have promised unlimited candidates and, three lines higher, insisted Pro keeps the same single one.
A cap of five results is how a search stops offering you a choice
Kyiv to London was coming back with one road: a night coach to Warsaw airport, a Wizz Air flight to Luton, the flight back, the coach back, and a hotel. Five cards. The server kept the first five options the agent returned and dropped the rest, so the second road never appeared, not because nobody looked for it, but because there was nowhere to put it. The overnight train was found. It was mentioned, in one line inside a note attached to the coach: cheaper by about fifteen euros, longer by two and a half hours. A line in somebody else’s note cannot be chosen, cannot be compared and cannot be booked, so from where the customer sits it did not exist, and the whole thing read as a tool that does not know how to connect two legs. It knows. It ran out of room on the first connection. The cap is now derived from how long the road is: five for a one-way hop, eight for a return, up to sixteen for a chain, and the agent is told to give two or three whole competing roads that differ in kind: the fastest, the cheapest, and the fully overland one where it exists, and told plainly that naming an alternative in a note is not offering it. The first screen also asks how you want to travel: plane, train, coach, ferry, as four buttons that turn themselves on and off from the pair of cities. That happens on the machine, in under a millisecond, with no network and no model call: the city list is already loaded for the globe, and the rest is three rules and a great-circle distance. Asking a language model whether a train runs from Kyiv to London would mean a spinner while somebody is still typing the city name, and payment for an answer that follows from geography. Kyiv to Lviv switches the plane off by itself and says why: one country, 467 km, the ground wins door to door. Kyiv to London leaves all four on and says the sky over Ukraine is closed, so “plane” here means overland to a hub and a flight from there. Touch a button and the set is yours; the cities stop overriding it. The last one on cannot be switched off, because an empty set is a paid run with no possible answer. Checking twenty city pairs caught three things the first version of those rules got wrong: London to Dublin lost the coach, which really does drive onto the ferry; Madrid to Marrakesh lost the ferry across Gibraltar and was handed to aviation; and Sydney to Auckland was offered a ferry across two thousand kilometres of open sea, where no passenger line exists. Driving the finished screen in a browser caught two more: the explanation was describing a flight through a hub on a route where the plane was switched off, and the cities were being named in Latin script inside a Russian interface.
The board that cost every customer a run of their own now costs nobody anything
How do I get from Kyiv to Rome has one answer, and it is the same answer for everybody who asks: a timetable does not depend on who is reading it. Until today every customer paid for that answer out of their own Claude subscription and waited about three minutes for it. We compute the boards ourselves now, once, and serve them free and instantly. Twelve city pairs to start; adding one is a line in a list and a command. Computing them rather than collecting them from customers’ runs was a real choice with a real price: roughly $0.41 of our own inference per board. Harvesting would have been free and would have grown by itself, but it would have meant the tool sending its results to us, and “runs on your own subscription, we store nothing” is the sentence this product is built around. The lookup keeps that literally: the engine downloads the WHOLE bundle of published boards rather than the one it wants, so the request carries no information about where anybody is going. Each board is also a public page at qiksy.app/route/kyiv-rome/, and that is the point rather than a side effect. Somebody searching for how to get from Kyiv to Rome is asking a question we can answer; every landing we own answers “what does this product do”, which is not what they typed. The pages are static HTML with no bundle, no prerender and no hashed asset, so there is nothing on them that can fail to load, and they read the same to a crawler and to a screen reader. They are not orphans either: the sitemap entries and the link grid on the Route landing are generated from the same folder, and the build fails if either drifts from it. Two faults surfaced only because a page was printed and read. The frequency column had been showing the agent’s PROSE while the machine rule sat unused beside it, so a row could hold “odd days” in the data and say “daily” on screen, and the screen would win, which defeats the entire reason the rule exists: nobody should arrive at a station on a day nothing leaves. The rule is translated and printed now, and the prose is a fallback for a rule we cannot parse. The duration column was worse: it showed the FLIGHT leg, “2 h 25 min”, for a route where you first spend fifteen hours getting overland to that airport, with the fifteen hours explained in a note underneath. People read the column, not the footnote. It is door-to-door now, legs included. A third fault never reached a page: the function that decides two spellings are the same city stripped accents from everything, and Ukrainian Київ decomposes into і plus two dots, so it became киів, and a Ukrainian typing his own city name missed his own cache. Accents come off Latin only.
No date is a question of its own, and it now gets its own answer
Leaving the date empty used to be a refusal: the search asked for one and stopped. But “when” and “on what” are different questions, and the second one is the one people ask first: from Kyiv to Rome, what is there, is a train even possible, how long does the bus take. With no date Route now builds a board instead: what runs on that route at all, grouped by air, rail, coach, ferry and car, with the journey time, the frequency and a price range on each line. It is free and it needs no engine key, because a board is about a route rather than about a day, and the same route answers the same way for everybody. Three rules keep it honest. Frequency is stored as a rule rather than a phrase: daily, odd days, even days, weekdays, a list of days, seasonal, because flattening “odd days” into “often” is how somebody ends up at a station on a day nothing leaves. A price is a range and never a single figure with a button beside it: the board has not seen one live seat, and “from €60” is the outer limit of what it may claim. And what the agent could not find out is printed in its own line at the bottom, because a short board with a stated gap is worth more than a full one that filled the gap in. The board also lives in a separate field of the trip from the options and is deliberately drawn unlike an option card: no frame, no big price, no right-hand total, so a board row cannot grow a “Book” button by accident. That was not a matter of care: separating them makes the mistake impossible instead of unlikely. The single button on the board leads to a date, not to a purchase. Two things after that were found only by looking at it. With no date at all, the trip header printed a calendar icon and then a separator with nothing in front of it: visual litter, and to a screen reader the sentence “calendar, dot, one way”. It says “no date yet” now, in all seven languages, which fixed the header, the trip card and its spoken label at once. And two paragraphs of the same kind sat under each other at wildly different line lengths: the intro was held to a reading measure and the agent’s summary was not, so on a wide window it ran to 140 characters a line. All four blocks of prose on the board share one measure now; the table rows stay wider, because they have a price at the end and the eye follows the column.
A captcha is a wall for a blind tester, and we stopped pretending otherwise
A run that walks into a «prove you are human» page used to keep walking. It read the verification page, filed findings about it, and the client got a report about a site nobody had looked at, which is worse than an empty report, because it looks like work. Jig now recognises the wall, stops, says which kind it is, and asks in the chat instead: pass it yourself, tell me what it is and where, or there is no check here. «What is it, and where» counts the Tab stops to the check, or says plainly that it sits in a frame of its own and cannot be counted to. For a grid of pictures it looks at the nine squares and names what is in each; then, as you move the mouse, it calls out the square under the pointer by row and column with what is drawn on it. What it never does is answer the challenge. That is not a policy we could relax later: the challenge question goes straight to speech and never reaches the model, the tiles arrive already cut, and there is no code anywhere that presses a square. A person who cannot see the grid can now work it with a mouse, the way a sighted person does, and the site is still being asked to trust a human, because it is one.
A key that says what is on the screen
The accessibility tree tells you what a page is BUILT of. It cannot tell you how the page LOOKS, and «the text sits on top of the picture», «the button is off the edge» and «this is an image of a table, not a table» are all questions about looking. Option-I photographs the open page and reads it back in reading order, in the interface language, and puts the same text into the chat so it can be re-read later. It runs on the tester’s own Claude subscription and the picture never goes to our cloud. It works in every profession, not just the accessibility one. The first version of it shipped nowhere: we bound it to Option-D, which already opens the per-page tool, so the function was never once called, while the keyboard list promised it. That is the expensive kind of bug for somebody who cannot see: it does not break the window, it breaks trust in the list you learn the product from. There is now a build gate that counts the claimants for every Option-letter across all three files that hand them out, and checks in the other direction that every key the list promises is handled by somebody.
The client report was signed by somebody who did not sign it
The document a client pays for named an evaluator it had inferred, counted the same defect several times over, and let raw markup entities through into the text, so a finding could reach the client reading «the "Send" button». Three separate lies in the one artefact that leaves the building. The signature line now carries only a name somebody explicitly signed with, and a separate line says which machine ran it: two different facts that were being collapsed into one. Duplicates merge on the criterion and the element together, so the same broken control in two places still counts twice and the same control found twice counts once. And auditing a folder on your own disk works: a local page was refused by nine separate doors in the code, each with its own hand-written test for what an address looks like, and eight of them had never heard of file://. There is one predicate now. Alongside it, the funnel stopped eating what you say to it: send a link while it is still asking its questions and the link stays in the chat as a queued task instead of vanishing, and several tasks thrown in at once become a checklist with a state on each line rather than a race. Dictation moved onto the machine and got faster, measured against the same recogniser without the change, in the same conditions, not against a number we liked.
Booking no longer starts by opening a browser you did not ask for
Pressing «Book» used to launch a Claude agent with a browser attached, and when the Qiksy extension was not connected the product opened a visible Chrome window of its own. For a sighted person that is an odd flash. For a blind person it is a window that appears outside the focus, announces nothing, and immediately asks for a system permission they cannot see. In the owner’s words: «they will not understand that some browser opened somewhere and some allow needs confirming». That branch is gone. The product never opens a browser window of its own again; filling a supplier form automatically is now a switch in settings, off by default, and it works only through the extension in the browser the person already has open. Underneath, the honest path was already written and hidden: a second worker that uses no browser at all and pulls the supplier’s phone, the languages they answer in, chat, email, address, opening hours in YOUR clock, the ordering steps, where you pay and the cancellation terms. It ran only from a button, the button appeared only after everything else had failed, and the result sat in a collapsed block called «Other ways to order»: the main path of the product named as the alternative one and kept as the fire exit. Now the collection starts by itself after a search, the block is called «How to order #N» and is open whenever there is something to order with, and the card leads with one action that never opens a browser: call, or a letter with the subject and body already filled in, or copy the number and the text for chat, chosen by which languages the supplier answers in. The link to the supplier site stays, last, and says out loud that it opens a separate tab. On the way there we found nine buttons that were drawn, pressed, and did nothing at all: among them the only trigger of that no-browser path, both «Copy» buttons, and «Stop search», which left a running trip with no exit except deleting it. All nine had one cause, so the hand-audit that missed it twice in one day is now a build gate. A screen reader on a real Windows machine then caught two more that no eye can see: a note telling the person to press «Edit» next to a button called «Pick who is going», and a trip header that ran two facts together into the non-word «one waytransfer». And a group booking quietly lost people: the form snapshot keyed every tick box by field name, and the «who is going» boxes all share one, so a family of two came back as a family of one, or of three, with nothing said aloud either way.
We took it somewhere Booking does not work, and the real data broke it
Testing this on Vienna to Madrid proves very little. So we pointed it at Bulawayo to Hwange in Zimbabwe and Kigoma to Mpanda in Tanzania: rural routes where the international aggregators simply are not present and half the operator sites answer an automated request with a 403. The agent did well: it found phone numbers with the page they were printed on for four options out of five, said plainly which sites it could not read and why, invented nothing, and, having read the note on the traveller’s card, rejected the cheaper overnight coach on the grounds that arriving at 04:52 is not safe for a blind passenger travelling alone. Then it broke our code, which is the whole reason for going there. Rural timetables are not published, so a real answer comes back as «around 14:30», or as «daytime, exact hour unconfirmed». Our clock parser assumed a clock. The arithmetic downstream turned that into NaN, the number vanished into null on its way through JSON, and the STRING «NaN:NaN» survived all the way to the person: a screen reader read out «you will be there around N-A-N colon N-A-N» on the one line that answers «when do I reach the guest house». Four blind testers walking the real result found it independently; it was the only defect all four filed. Alongside it, the gap before the meeting quietly became empty on exactly the cards where the summary promised «a whole evening before nine in the morning». Both are fixed, and the rule underneath them is the interesting part: silence is not a safe default. «We could not work this out: the arrival time is only approximate» is an answer; nothing at all is indistinguishable from «everything is fine». Every travel card now carries exactly one line about the meeting: you make it, it is tight, you are late by this much, or we could not tell. Twenty-nine more dead ends came out of the same walk. Recording a booking you made yourself by voice existed only after the agent had already failed, which is useless on a route where tickets are sold at a bus station counter and there is no point running an agent at all. The sentence to say on the phone had the same condition, while the facts for it sat on three different screens. WhatsApp was in the data and in the ordering steps («call or message on WhatsApp») and nowhere in the interface: not one wa.me link existed in the whole app. Cancellation terms were silent on four cards out of five, because «not checked» was treated as a reason to say nothing rather than as the answer it is. An estimated price, worked out from neighbouring fares because the exact one is not published, was spoken as a firm figure, with the caveat arriving several lines later, and at a cash desk the difference between «$20» and «about $20» decides how much you draw from the machine.
Where the tool used to end outside itself, and a page that rebuilt itself once a second
Seven specialists walked the trip tool: corporate and agency travel bookers, two high-end tour operators, a transfer organiser and two screen-reader experts. Three of them independently filed the same thing as their number one blocker, and they were right about it. The page that shows a trip carries a fingerprint whose job is to skip a repaint when nothing changed; during a search it could never match, because the string being compared carried a stopwatch that ticks every second, a fact that rotates every twenty-five, and the tail of the agent’s log. So the whole trip page (hero, pipeline, the options found so far) was replaced once a second for the entire multi-minute run. For a sighted person that is a flicker. For somebody reading with a screen reader it is impassable: the reader builds its own buffer from the markup, and replacing the DOM resets it along with the reading position. Reaching the payment button that way is not slow, it is impossible. The three moving values are now patched as text, which the buffer survives. Then the options board itself: four roles found, separately, that it had exactly one heading, the hero. Transport, Stay, Transfer and every leg of a chain were rendered as plain divs with a colour per kind, so the eye got the structure and the ear got nothing; the fastest way to move around a long page, jumping by heading, did not work at all. A booking filled in one passenger out of three and no line anywhere said so. The confirm dialog and the report now name who is going. «You would not make the meeting on this one» was printed on perfectly good options, because the meeting field kept its date and the code read only the clock: land at 22:40, meet at 10:00 the next morning, and the arithmetic condemned the flight by fourteen hours. A false accusation is worse than silence, because people throw away what suits them. And the client proposal, which is the paid deliverable, turned out to be a poorer product than the screen it was taken from: a fifteen-leg door-to-door chain reached the client as three unordered buckets, there was no total anywhere, the honest «what we could not find» was never rendered, after payment it still invited you to pick an option, printing it to PDF produced a blank first block, and in any language beyond three it silently became English.
When the supplier’s own site cannot be used at all
A question worth asking out loud: what happens to somebody who cannot see, when the hotel or the taxi company on the other end has a site their screen reader cannot touch? Until today the answer was that the tool quietly stopped being useful. The agent would fill in what it could, hit a captcha or a sign-in wall, and hand back a link labelled «continue manually». The reasons that page stopped the AGENT, a captcha, a modal that never takes focus, a booking widget with no labels, are precisely the reasons it is impassable for a screen reader. We were walking somebody to the door and pushing them into a wall. Six specialists went through the code on this one question, two of them blind. Fifty-nine findings survived an adversarial check, and all six arrived at the same dead end independently. So the agent now takes the offline path BEFORE it gives up: at that moment it is standing on the supplier’s own page, and that is the only moment those contacts are reachable, because afterwards the card has no internet at all. The report gained a heading you can jump to, the reason for stopping picked from a machine-readable code (six different texts where there used to be one), the phone as a real number in a tel: link and as text, a ready sentence to say on the call with a copy button, what is still left to do, a button that records a booking you made yourself by voice, and only then, last, the link, named honestly: the page the agent stopped on. Two more things came out of it. The product had been calling a captcha a success: the status flipped regardless, so a trip sat in «waiting for payment», the card said «booked», and under a report with nothing filled in there was a button marked «Paid». And every option now carries how to order it AWAY from the site: phone with a status and a source, opening hours converted into the caller’s own clock, address, how you are met, the channels, the steps, the cancellation deadline. Copied character for character from the page, never from memory: a number a machine remembers is a number somebody dials blind.
The same mistake in four places: a colour meant for decoration was doing the work of text
A contrast gate stopped a deploy with 217 failing elements, all on one route, and the interesting part is that we had checked. We had checked the pairs of TOKENS we chose ourselves; the gate measures what the page actually paints, and those are different things. Four of the failures turned out to be one mistake wearing four hats: a tone documented as decorative, judged at 3:1, had been used as INK, where the threshold is 4.5. The duration chip in a leg’s timeline measured 3.47. The default section colour measured 3.89. The per-kind section colours (the amber one that says «transfer») measured 3.10 as a bold heading. The fourth was the pipeline step we had fixed the day before and filed as a one-off; it was not a one-off. Three more, each its own story. The «recommended combination» badge took its ink from a gold token that this page does not own: the studio shell declares its own amber, so the badge rendered amber on a hard-coded white at 2.08: the cause was not in the product at all. The line that says «you would not make the meeting on this one», the single most important sentence on a ticket card, was unreadable in the dark theme, because the danger token it referred to had never been declared and the fallback was a light-theme red at 2.29. And in the classic dark skin the semantic green and blue, the ones that mean «paid» and «found», sat at 4.01–4.08 on their own washes. All of these are defects in the TOOL, not in the page that exposed them: the classes are shared. The tool lives inside the studio, where the gate does not reach; the public page ran its cards past a checker for the first time. Thirty-one failures on the route, then zero. Said plainly, because it matters: axe sees about a third of the standard. Meaning, focus order and keyboard paths are still a human’s job, and that pass has not been made yet. Separately, the product stopped speaking as one role. It used to say «HR enters the card»: in the booking confirmation, in the combo confirmation and in the payment note. That is wrong for an agency, and wrong for somebody arranging their own trip. It now says the card is entered by you, and the setting called «HR timezone» is called «your timezone». The first screen says both jobs out loud: one ticket from here to there, or the whole chain, for an agency, for a company, or for your own trip.
«Try again in a minute» was a lie, and it was covering eighteen different refusals
Press Book on a trip that has no traveller card and the tool said: it did not work, try again in a minute. Waiting would not have helped at any hour: the trip simply had nobody to book for. The mechanism is worth writing down because the cure was worse than the disease. The engine answered in plain Russian sentences, and the interface deliberately never shows the engine’s own words, because English and Ukrainian readers were getting raw Russian toasts. So the interface translated four machine codes and swallowed everything else into one sentence about a minute: eighteen distinct refusals, including «there is no traveller card», «that option is no longer in the selection», «the traveller needs a full name» and «this trip was deleted in another tab». Every reachable cause now has its own code from the engine and its own sentence here, in the reader’s language and with the action in it: «Nobody to book for: this trip has no traveller card. Add a person on the Travellers tab: the passport is entered once and fills itself into the ticket.» There is not one Russian sentence left in the engine’s answers. An unexpected refusal no longer promises that it will pass by itself; it says the engine refused and quotes what it said, which is at least diagnosable. Verified by calling the API rather than by reading the code. The loading screen was fixed in the same pass: it was pinned to the WINDOW, so inside the studio it sat in the middle of the whole screen, exactly half a sidebar to the left of the area it belongs to. It now centres in its own section, and Travel greets you with its own carriage racing on the spot, the same frame the agent draws while searching, instead of a generic three-dot mark. Then the surfaces, judged by four senior designers who were handed four real screenshots (both styles, both themes) rather than a description. The dark ground was raised in LIGHTNESS, not merely de-blued: a card differed from the page by 1.11:1, which is not enough for it to read as an object at all; it is 1.19 now. The light ground became milk: the same lightness, but the red channel above the blue rather than under it, because a de-blued grey is still grey. Three petrol radial washes were deleted outright: they put a different luminance under every card, so no card could sit a known distance above the page; one symmetric horizon replaced them. In the classic light skin the console panel was a GHOST at 1.09:1 against the page with shadows switched off, so its edge was literally invisible; its hairline is 1.41 now. In classic dark two ink tokens were the SAME COLOUR, so body text and captions sounded alike. And two things the council caught that we had missed: the dotted texture in the background was painted in rgba(15,80,80,.045), a dark TEAL, the last green left on a page where green is banned, and it had survived every token swap because it did not live in a token; and one shell token arrives from the kit at 2.39:1 on the light bar against a 4.5 gate: a live accessibility failure, recomputed by hand before believing it, and now 4.94.
The globe was not flickering in colour · it was flickering in a fill rule, and three rounds of fixes had gone to the wrong cause
The planet on the Route landing changed colour while it turned: continents went white, then the ocean did, dozens of times a minute. Three rounds of work had gone into the palette, the night side, the city lights and the theme switch, and none of it was the cause. The land was drawn as ONE path across all 126 coastline rings, filled even-odd. A coast that passes behind the horizon has to be closed with an arc along the limb of the sphere, and every one of those closures needed a decision: which way round. Get it wrong and the path gains almost a full circle, and even-odd from one extra circle inverts the whole disc: land becomes water. While the globe turns, those closures happen dozens of times a frame. The direction had been taken from the tangent of the coast, then from the orientation of the ring; we built a rig that runs a full rotation of 120 frames outside the browser and compares the share of land on the disc against an independent oracle: a land mask in longitude and latitude, which agreed with the known figure that land is 29% of the Earth’s surface. The tangent rule was wrong on 29 frames out of 120, the orientation rule on 24, both by up to 65% of the disc. So the choice was not nearly right; there was no choice to make. There is no decision now at all. A land mask is built once, and it is built by scanning parallels rather than by filling outlines, which matters, because four of those rings cross the 180th meridian, and in a flat map such a ring draws a chord across the whole width and flips the parity behind it. That is why the first attempt at a mask filled the Arctic with land and lost Antarctica entirely, and why our own first oracle agreed with it: both were built the same wrong way. Now each parallel is cut by the coast where it actually crosses, and the phase is carried down from the north pole, where the answer is known: there is ocean there. Every point of the disc then asks the mask whether it is land. Measured against the oracle: 0.09% disagreement, and the largest change between two neighbouring frames is 1.08%, which is just geography turning. It used to be 34%. Then the colour, because the owner said plainly that he does not like the green: the whole environment is petrol blue now, deliberately pulled toward cyan because Offer already owns indigo and two products a hue apart read as one product in the launcher. Removing the green took six places, not one: four palettes, the kit’s environment accent, the page’s background gradient, a scrollbar, a pipeline step and a hard-coded colour on the product pill in the header. Recomputing every pair against the new grounds turned up five real AA failures, four of them inherited from the teal era: a token used in 47 places, almost all of them body text, at 2.92:1, white text on a tone documented as decorative at 4.05, a signal chip whose ink measured 3.80 on its own wash, a ghost button whose border fell back to a 1.28:1 hairline outside the studio, and, the one that matters most, the route caption under the planet, which sat ON the dark edge of the globe and was marked aria-hidden, so the only text describing the main object of the first screen was read by nobody. It is in the flow under the globe now, in a live region, and it is spoken. axe-core reports no violations in either theme; the keyboard walk closes in 22 steps with all 21 interactive elements reachable. Last, the page stopped illustrating itself. Beside the drawn window with its invented trip there is now one real search, made by the engine on 3 September 2026: Kyiv to Munich with Ukrainian airspace closed, so a bus to Warsaw, the EuroNight Chopin sleeper on to Munich, a hotel, and the same way back: about €465 against a €600 budget, and with the caveat the agent refused to smooth over, that the hotel price is an estimate because Oktoberfest moves it and that the bus alone would arrive four hours after the meeting. It is a real table with row and column headers, so a screen reader hears «sleeper train, Warsaw to Munich, 14 h 14 m, 40 euro» as one sentence instead of columns of numbers.
A critical finding called itself a blocker, and the crawl never admitted where it stopped
We wrote the accessibility auditor a guide and put it in front of seven blind reviewers before putting it in front of a real one. They named six things. Two of them were wrong, and saying so is the point: one reviewer worked out from the text that the page verdict grabs the focus once per page, so a forty-page walk would grab it forty times. Reasonable from the text, and not what the code does: nothing focuses the score line, the re-announcement only fires while the focus is still inside that same panel, and a site walk runs in another process that never reaches the code at all. We had already written the confession into the guide before checking it. The other four were real. The worst of them: the store produces a severity called critical (it is what an axe result of serious becomes) and the severity picker had no such option. A widget handed a value it does not offer shows the FIRST one instead, silently, so a critical finding called itself a blocker and the screen reader said the wrong word. The same level printed as a bare key, sev_critical, in the ticket that goes to the client, in all seven languages. Second: the result of a check rode to the reader as an accessible DESCRIPTION. NVDA speaks object descriptions only when that setting is on, the people most likely to have turned it off are the fast readers this is built for, JAWS treats them differently again, and unlike a live region it fails without telling anybody. It rides in the accessible name now, which every reader speaks in every mode. Third, from the one reviewer using a braille display rather than speech: an announcement is a queue for a voice and a flash for a display: it lands on top of whatever the fingers are reading, and it can be switched off entirely. So anything whose only trace was an announcement now also lands in the conversation, where you can go back and read it: which file an export wrote, which scenarios an import rejected, how many checks the report left untouched. Fourth: the site walk has three ceilings (pages, link depth, wall clock) and named only two of them. The depth cut-off was invisible because the queue simply ends by itself, so «we walked forty pages» read as a census when it was a cut at the second link from the front page. It says so now. Two more found by looking rather than by being told. The library that does the walking declared default limits nobody ever received, because every live caller passes its own: four different sets of numbers across the codebase, and we had already written the wrong pair into the documentation. The dead defaults are gone and a missing limit now fails loudly instead of quietly returning zero pages. And one file declared two different functions under one name; the later won, so a URL that was meant to be shortened to its path was read out in full. Forty characters instead of two words, to somebody listening. Underneath all of it, the thing that made this possible to check at all: the profession had no acceptance test. Five professions, and the three acts that judge them mention four. The one we are handing to a blind auditor was the only one nobody was testing. It has its own act now, and it is built so that it cannot be passed by doing nothing: engine mechanics must be hidden from the auditor and visible to the tester, and the promise to open his checklist must be recorded before the welcome finishes and kept after it.
The accessibility reader was shown an empty panel, because the camera was pointed at the wrong wall
Pick «I audit accessibility» on the Jig page and the picture beside the headline was the Accessibility panel saying «The audit has not been run on this page yet»: an untouched form, two unpressed buttons, and one grey sentence. A frame containing nothing that happened. Two separate things had gone wrong. The panel moved from the bottom strip to the side column on the first of September, and the rig that shoots these pictures still clicked into the bottom, so it pressed nothing and photographed the empty state; it now presses the real button and waits for the result card rather than for a fixed two seconds. The deeper one is that the panel was the wrong subject entirely. It audits ONE open page. The profession is a whole site: mapping it, walking the layers that have no address of their own, filing findings, building the conformance report, and every one of those is a verb the chat drives, not a control in the window. We grepped the window code for the report verb and found zero uses of it. So the auditor now has a frame of his own, and it is the only one in the set where the picture is a conversation: the ask, the findings with the WCAG criterion each one breaks, and the plan of six audit directions with three passed, one running and two untouched. Also fixed, and the reason this took a second pass: the stand server that serves the pages in these pictures had lost an import and crashed on its first line, so the whole shoot could not start. And inside the chat, the tick and the cross in a checklist sat low in their boxes, because a line-height equal to the box centres the LINE, not the glyph, and the two have different metrics. They are centred by grid now, like the checkbox two hundred lines above them that had been done properly all along, and a size smaller. One last thing on the same page, and it is the kind of gap you only see once somebody points at it: the four profession chips sat in a two-column grid, and a grid column is as wide as the widest chip in it, so the short one on the second row left forty pixels of air before its neighbour, and the pair stopped reading as a pair. Two real rows of two instead, so the second chip sits against the first the way it does on the row above.
Jig is in the Microsoft Store, and the Windows warning screen now has a way around it
Jig Browser passed certification and is listed. That matters for one specific reason: the direct Windows installer is still unsigned (our certificate is in identity validation) so Windows shows the blue «Windows protected your PC» screen and you have to choose More info, then Run anyway. Plenty of people stop there, and they are right to. A package in the Store is signed by Microsoft itself, so there is no warning at all, and it updates itself. Both routes are on the page now, side by side, each with a sentence saying what it costs you: the Store has no warning but needs the Store; the file needs nothing but shows the screen. We did not replace one with the other, because a machine with the Store switched off by policy is exactly the machine that needs the file. The listing itself is free, in all 240 markets, rated 3+ everywhere except Brazil, and the one page of it people read was written against the code rather than from memory. The voice track for the accessibility reader was re-recorded the same day and for a duller reason: we rewrote the transcript and the seven recordings still read the old one, so the page showed one text and spoke another. The first re-take ran fifty-one to sixty-four seconds against a page that promises forty, so it was thrown away and the script cut by a quarter. Thirty-six to fifty seconds now, in family with the other three readers.
The accessibility reader was shown somebody else’s page, and nobody could see it
The Jig landing asks who you are (I test apps, I write code, I write requirements, I audit accessibility) and rewrites the headline, the five windows and the four figures for the answer. The fourth answer was added last month and never worked. The line that picks the override knew three readers and asked one question: is this the coder? If not, use the analyst’s. So choosing «I audit accessibility» painted the green accent over the ANALYST’s page. The copy written for auditors sat in all seven dictionaries and was read from nowhere. It is a table now rather than a chain of questions, so a new reader either has a row or has nothing: taking somebody else’s silently is no longer possible. The text that finally appears is not the text that was written for it either. The old block promised «a report with a score»; the report a client receives has no score at all, and we grepped the builder and found none. The score belongs to a different thing, the markup panel. That was the one outright false claim on the page and it is gone. What replaced it is what an audit actually is here: fifteen directions land in the checklist on the first call, findings are filed as you go, and the report is built from them: by WCAG criterion, with the node each finding sits on, the passport of the run beside it, and a plain count of what nobody looked at. Directions a machine cannot judge stay open until a person signs them, and a report with nothing measured refuses to print. Every sentence there was checked against the code before it was written. Three smaller things went with it: the green is a step lighter in both themes (the old one read as acid, and lighting it raised every contrast rather than lowering one), the four profession chips became a 2×2 grid because in a row they were the widest thing in the hero, 743 pixels against a 518-pixel headline, and each chip now hugs its own label instead of stretching to the column, which had «I write code» sitting in a pill three times the width of its words.
Four English pages told screen readers they were in Ukrainian
We ran our own accessibility check over every page of this site (110 of them, from the sitemap) and it found three things worth fixing. The first is the one that matters. /pricing/, /privacy/, /terms/ and /refund/ are written in English only; the rest of the site follows whatever language you have chosen, and the page was announcing THAT language rather than the language of its own text. So a reader with a Ukrainian interface got an English document declared as Ukrainian, and a screen reader duly read English words with Ukrainian phonetics: technically speech, practically noise. A page now declares the language of its TEXT, and the one phrase on it that IS translated, the skip link, carries its own language marker, which is what WCAG asks for and what we were not doing. Two smaller ones went with it: the investments radar gave the coin name an <h1> on a page that already had one, so a screen reader asking «what is this page» got two answers and no top; and the two silent screen recordings on the QA Copilot page had no names at all: they announced as two unnamed players. The obvious fix there would have been a subtitle track, and it would have been a lie: the recordings have no sound. They have words describing them instead, in all seven languages. Worth saying how the first one hid: fetching the page from outside shows an honest lang="en", because the swap happens after the page comes alive in a browser. Reading the file would never have found it.
A half-written trip survived a language change but not a reload
What you have typed into a trip (the city, the dates, who is going) is kept in a snapshot so that it is not wiped by things which rebuild the screen: switching language, going full-screen and back, moving between the panel and the full page. That worked. What did not was the ordinary case: hitting reload. The snapshot was only ever taken when the screen was being torn down, and a reload does not tear anything down: the browser simply ends the page, and there is nobody left to take it. So the city you had typed was gone. It is now taken when the page LEAVES as well, and by two different events rather than one: the browser’s own leave event is skipped when a page goes into the back-forward cache in Safari and is not always fired on mobile at all, so the second one catches a tab the system killed to reclaim memory. The storage stays per-tab on purpose: the draft lives exactly as long as the tab does, and never resurfaces a week later as «a draft from yesterday that I never started». Checked by doing it rather than by reading the code: typed a city, reloaded, the value was still there. Before the fix the field came back empty.
Walking away mid-search now asks you, and a run nobody is watching switches itself off
Every product in the studio is its OWN page, so clicking the rail loads a different one and this screen goes with it. The run does not: it lives on the engine, on your own machine, and the product promises exactly that in four separate places: close the tab, the search keeps going. That promise stands. What was missing was the CHOICE, and it now appears when you leave a page with agents working: leave it running, end it and go, or stay here. Three answers rather than two, because ending a search and leaving it alone are both things you might want to do. The refusal is staying. We intercept the LINK rather than the browser’s own leave event, which cannot be given our buttons: it would show a generic «Leave site?» with no product name and no third option. Opening a link in a new tab, downloading a file, jumping to an anchor on the same page: none of those count as leaving, and none of them ask. In Offer, ending a run ends it across BOTH industries: you are leaving the page entirely, and a run on the other market is one you would no longer be able to see or stop. The other half of the request was to stop the agents when the site is closed, and doing that literally was the wrong thing. A tab closed by accident (the wrong window, the wrong shortcut, a laptop going to sleep) would cost fifteen minutes of an agent’s work, and the monitoring feature, which people pay for, exists precisely to run while nobody is there. So what is measured is not the closing but the ABSENCE. The panel checks in every two and a half seconds and holds a live channel; if nothing has checked in for ten minutes, there is nobody left to burn quota for, and the manual runs stop themselves with the reason written into their log. Switch tabs, walk away, close it by mistake and come back: your work is intact. The threshold is deliberately generous: longer than any «stepped out» and shorter than a full sweep. Monitoring is exempt, and telling the two apart had to be done honestly: the way a run is started does not distinguish them, so runs born from the monitoring tick are now marked as such. Without that, this rule would have quietly switched off the very feature that is supposed to work when you are not looking.
The agent was reading pages we were guaranteed to throw away, and Travel showed nothing until it had everything
Three architects read the search code today. Two findings shipped, and the first one explains where the minutes went. The agent was told which COMPANIES were already on the board, up to three hundred names, while the server discards a duplicate by its normalised URL. An agent cannot match a page it has opened against a list of names: «Acme Corp» against «Acme Corporation» already misses. So it fetched the page honestly, spent the seconds and the tokens, and we dropped the result in silence. Both lists now go into the prompt, because they cut at different depths: names cut in the search results, before anything is downloaded; addresses cut the one link the server would have binned anyway. The cost was measured rather than guessed: two hundred addresses are about fourteen thousand characters, and a single fetch of a vacancy page puts between two and ten thousand tokens into the context, so one prevented fetch pays for the whole list. Nothing is lost for a job that has CHANGED, either: the exact URL was already remembered forever and already refused the updated record. Re-reading what we know is the link-checker’s work, not the search’s. Route had two separate silences. Its agent streams options as it finds them, but the launch was missing the flag that delivers partial messages, and the parser was anchored to the start and end of a line, so the stream of fragments never matched at all. The person waited two minutes and got everything at once, although the first option had been ready at thirty seconds. And Route had no live channel whatsoever: an option landed in the database and reached the screen up to a second later, because the interface only polled. Both are now as they are in Offer, copied along with the three things that had already cost debugging there: telling proxies not to buffer the stream, dropping frames for a reader that is connected but stalled, and a sync frame so a tab joining MID-RUN knows a run is happening. Also fixed, and caught by a gate rather than by eye: the loading curtain was hiding the landing page’s own heading, because it now waits for the app to say it has drawn, and on a landing page the controller never runs at all.
The thing that shows a page is loading was hidden underneath the thing that hides a loading page
Reload Offer or Route while the agents are working and you got a half-assembled screen: the rail is there, the board is not, and skeleton cards blink in and out. Three separate faults, one after another. The waiting indicator was never visible: not rarely, never. It lived INSIDE the app’s root element, and the curtain that hides a not-yet-drawn app hides that whole element, so the curtain was covering its own indicator; React would also have wiped it on first render. It is an overlay above the page now, removed by hand when the reveal happens. The curtain lifted too early. It waited for React to MOUNT, which takes an instant, while the content is drawn by the controller after the engine answers, a second later or more. Everything between those two moments is the half-assembled screen. Now the app says when it has actually drawn: in Offer at both exits from waiting, the one where the engine answered and the one where it never did, because on a machine with no engine the gate is exactly what has to be shown; in Route after two animation frames, which is the point at which the browser has really painted. There is a six-second ceiling on top, without which a broken bundle would leave someone staring at a loader forever. Measured after the change: Offer holds the curtain 3.0 seconds until the board is ready, Route 1.6. And the indicator itself was a spinning circle, which says nothing about what is happening, and a reload in the middle of a run is waiting for WORK, not for a page. Offer now shows a briefcase in flight and Route a carriage, both with the wind streaming past them: the scene stands still and the world rushes by, so you do not have to follow anything with your eyes, and there is no point where it jumps back to the start and reads as a reset. Both are drawn in our own tokens and obey the theme, the style and the studio’s tint, down to the carriage window and the briefcase flap; both stop completely for anyone who asked for less motion, and the frame still reads.
Opening Offer repainted itself in front of you, and it was one letter
Every page here sets the theme, the design style and the tint in a small script that runs before the first paint, so nothing you chose ever flashes as something else. In Offer that script fell over. A variable in the block is called one thing and the line that applies the tint asked for another: a name that belongs to a SECOND boot script further down the file, and does not exist in the first. So the line threw, control went to the safety net, and the net can do exactly one thing: set the style to classic. Which means that on every single load Offer discarded both the style you picked and the tint, painted the first frame as somebody else’s page, and then React delivered the real values after it mounted: the repaint you could watch happen, with the tab labels briefly in the wrong colour. Finding it needed a trick worth writing down: the error is inside a try, so it never reaches the console, and four hundred milliseconds later React has already fixed everything, so an ordinary check reports a healthy page. It shows up only with the application’s own script blocked, leaving nothing on the page but the boot code. Measured that way, the live site set the style to classic and no tint at all while the choices were modern and emerald; with the letter corrected it sets both. Route never had this: the same block there is written consistently. Two more things on the same board. While the agents run, the search button is disabled (not broken, just nothing to press) and it was being painted white-on-pale twice over: once because a desk-wide rule dimmed every disabled primary button to forty per cent, and once because the same rule gives primary buttons white ink, which is right on a coloured fill and unreadable on the grey one a disabled button gets. Both halves are fixed and measured: the label now reads at nine to one on the classic theme and ten to one on the plain light. And the source chips (the domains the agent is reading right now) no longer sit flush against the moving progress bar above them.
The page hands you a code, and the field for it was hidden behind a link that called it rare
Signing in to Claude from a tool has nowhere to come back to: the command starts without a terminal, so the sign-in takes the code path: the page SHOWS you a code, every time, not occasionally. Our window had the field for that code folded away behind a link worded as an edge case, and the owner walked the whole path, pressed Copy code, and asked where he was supposed to put it. The field now unfolds by itself the moment it is clear there is no loop back, and it sits ABOVE the waiting line: first the thing you have to do, then the thing we are waiting for. The link stays for the case where a loop does exist. Worse than the layout was the silence underneath it. A sign-in lives ten minutes; after that the command is gone and nobody will accept its code, and the field simply stayed on screen: paste, press Send, nothing. A refusal now names its reason, telling «the sign-in expired» apart from «that code did not fit», with a Start again beside it that raises a fresh sign-in. And the line introducing the window promised the connection would light up here by itself, which on the code path is not true: it lights up when the code is pasted. Rewritten in all seven languages. Two colour faults went out with it. The toast’s backdrop was built from a literal white instead of the card token: invisible on the plain light theme, where the card IS white, and obvious on the classic one, where the card is cream: a cold white slab over a warm page. It uses the card token now, which already knows the style and the tint, so this is the toaster everywhere it appears. The share of status colour in the fill went from five per cent to three, and that is a measurement rather than a preference: on a cream card five per cent of blue pulls an info toast to the cold side of the page it sits on, which is the same complaint in different words. Status is carried by the border and the icon; the fill only whispers it. And the Go button on the travel globe took a plain white for its label, because the token that would have told it otherwise is not defined in every environment, and on the dark theme the accent there is light, so white on it measured 2.44 to 1 against a floor of 4.5. It now falls back to the environment’s own colour-on-accent, 6.66 to 1, which is exactly how that pair is declared in the design system.
The tools and your editor shared one login folder, and each was quietly logging the other out
Claude Code keeps its sign-in in a config folder, and the keychain record is tied to that folder. The tools never set the variable that moves it, so they were sitting in the same folder as the owner’s editor: two clients on one refresh token, each renewing it independently, and whoever renewed second was left holding a dead one. This is not theory: Jig walked into it on 20 August, an editor lost its subscription mid-session, and Jig moved to a folder of its own. The tools had been the second client on that folder the whole time. The other half of the same fault was the button: signing out here threw the editor out too, and signing out in the editor took the tools with it. They now have their own folder, one shared by all four, because it is one engine and one subscription, and a folder per tool would mean three sign-ins for one account. The old behaviour is one environment variable away for anyone who wants it. The first launch after this had to not look like breakage: the new folder is empty, and a person who is signed in to Claude two windows to the left would read a plain «not signed in» as a broken tool. So the check now reports whether the shared folder is signed in as well, and in that one state the gate says the tools have their own sign-in, it takes one login, and the subscription is the same one. Two smaller things travelled with it. The installer used to freeze the PATH it saw at install time into the startup file. Change your Node version afterwards and the engine looks for the command where it no longer is, then reports it missing on a machine where everything is installed and working; the PATH is asked of the login shell now, once per process. And the first screen said the quiet part wrong: while the tools picked up a login that was already on the machine, «nothing else to do here» was true, and after this change it is not. Between a running engine and working software there is now exactly one sign-in, and the setup screen says so in advance (as a third step, with no button on it, because there is nowhere to sign in until the engine is up) instead of springing it on the next screen. The text a person hands to Claude to do the install was corrected in both places it lives, so the instruction and the screen say the same thing.
The board showed one agent’s work under another agent’s name
Two searches can run at once since the end of August: switching industries no longer stops the one already going, which is the whole point of watching a developer hunt and a nurse hunt at the same time. What nobody noticed is that only half of the screen learned to tell them apart. The result cards were filtered by whose search they belonged to, and the code even carries a comment explaining why that filter has to exist. The live feed above them was not. So the board for an IT candidate ran a stream reading «Searching the web: Pflegefachkraft Stellenangebot Bayern», listed liv-pflege.de among its sources, showed a clock and a counter belonging to somebody else’s run, and titled all of it «two agents are looking for work: React / Frontend Developer, AI Systems Integrator». Those two agents were sitting in the queue at that moment and had not made a single request. The owner saw it and asked a reasonable question: why are we searching Germany for a front-end developer. We were not. We were searching Germany for a nurse and writing the developer’s name above it. A person reading that screen could only conclude their profile had the wrong country in it, and go looking for a setting that was correct all along. One condition, the same one the cards already had, now applies to the feed. The second thing on the same screen was smaller and older. While agents run, the search button is disabled, not because anything is broken, but because there is nothing to press. A rule for the whole desk dimmed every disabled primary button to forty per cent, and it caught this one too, so the label and the running clock faded into the button on the light theme. There was already a rule saying this particular button must stay at full strength; both rules had exactly the same weight, and the one written later in the file won. The fix went into the rule that was wrong rather than a fifth rule on top of four, and it was verified by measuring the rendered button in both themes and both styles rather than by looking at it. And the source chips (the real domains the agent is reading right now) sat flush against the loading bar above them, so a moving bar and a list of names read as one block. They are two different statements: that work is happening, and where it is happening. They have room between them now.
The browser could say a page was fine when it had not managed to look at the page at all
A blind tester in Morocco opened a Google web app, met button after button with no name, and was told by the browser: this page is fine, nothing to repair. Reproducing it in the live browser explained the sentence. The page’s main document holds seventy-eight nodes, ONE keyboard stop and zero characters of text; the entire application lives inside an embedded frame with four hundred and forty-nine nodes, thirty-two stops and nearly two thousand characters. Our repair walks the main document only. It honestly found nothing, and reported that as order. Five specialists were asked how this should behave, and they agreed on something that is not a matter of wording: for a repair that cannot see, «found nothing» and «nothing is wrong» are the SAME observation, and a verdict may not fuse them. There have to be three states, not two: looked and clean, looked and repaired, and could not look at all of it. The third did not exist, so everything that did not fit the other two drained into «everything is fine». This is not our invention either: in the ACT Rules format that accessibility checkers are written against, the outcome cantTell sits beside passed and failed precisely for «could not be computed», and returning passed in its place is a breach of the format rather than a stylistic liberty. So the browser no longer has that sentence in its speech. «No repairs were needed here» stays for the eye on the badge and for the report you ask for by key, where you asked; out loud it now says only what it can vouch for: what it repaired, and what it did not get to see. Being able to say the second one required counting: an instrument can only report what it did not look at if it keeps a register of it. Frames that carry real content and were never entered are counted now, and so is a failed measurement: fifteen hundred characters of visible text with a single keyboard stop means blind, not clean. The caveat travels with good news too: «repaired, twelve fixes» on a page whose application sits in a frame is the same untruth as «nothing to repair» on it. The subject of the sentence changed as well, and that was the specialists’ first pick. «This page is fine» is a claim about the world that the browser cannot back up; «I did not go through this whole page» is a fact about itself, true always. It matters most for the youngest users: a child who hears the tool say fine, and cannot make the page work, concludes that the failure is his. What is deliberately NOT claimed here: the browser now tells you honestly that it did not enter the frame, but it still does not enter it. On that Google app a blind person now gets the truth instead of a lie, not the application instead of the truth. Going into frames is the next piece of work and it is not one line. Four smaller things shipped with it, each found by somebody’s hands rather than by a check. A file picked in our own panel never reached the page when the site’s file field lived inside a frame: the answer went to the main document, where no such field exists, and vanished in silence. A file name in Latin letters was read aloud by a GERMAN voice on a Russian interface, because the panel took the first reading language that shared the alphabet, and German happened to be first in the list; a name written in twenty-six Latin letters is evidence of no language at all, so it is read in the neutral one now. Hovering the address suggestions did nothing whatsoever: no highlight, no voice; a hover rule in the stylesheet would have given the eye half of it and the ear none, so hovering now moves the same cursor the arrow keys move. And the address bar showed the address of an embedded frame instead of the site: the «navigated within the page» event arrives from ANY document of the tab, and the handler never looked at which one, so a companion frame calling history.pushState rewrote the bar and wrote its address into your history. For someone who cannot see, the address bar is the only place the name of the site is written.
How much the browser explains is now yours to choose · and three things it used to answer with silence
The browser now asks a second question on the first run: how much you want to be told. Three answers, and each one says a real phrase in its own manner instead of describing itself, so you hear the browser you are about to get before you agree to it. Detailed says roughly three times as much: it names the key that undoes what just happened and tells you where you have landed, which is what a child or a first-day user needs. Brief says the fact and stops. The middle one is the browser as it was, word for word, and a level only changes phrases we wrote a second form for, so nothing can be lost by trying one. It is changeable at any time in the settings. Building it turned up something worse than the feature was: the page reader had its own translation door and consulted the dictionary directly, so the levels worked in the menus and did nothing on web pages, that is, everywhere a blind person actually spends their time. Three other silences went with it. Pressing back or forward at the ends of a tab’s history did nothing and said nothing, in all six places that ask for it; someone who can see the greyed-out button never presses it, and without sight the only available conclusion is that the browser is broken. A new key answers “where am I now” with the page, the section and what is under the reading cursor, and the repeat key is deliberately verbatim and never answered that. And a refusal to send a page to the cloud, recorded once, was being spoken again on every new page, across the page’s own announcement; on a first visit a dialog about the cloud could even open by itself before anything was pressed. Schools and students now have a free key for ten years, with the paid features on and their own monthly allowance; a parent who buys Care has it ADDED to the school key rather than replacing it, because the gift is not something we take back in exchange for money.
One page in the studio kept its own copy of the language, and nothing else could reach it
Switching language in the studio’s top bar changed every page but this one. Shift held the language in its own state, read once when the page opened, and was subscribed to neither the switch nor the storage behind it, so a reader who chose Ukrainian went on reading English, with the language control cheerfully showing UK. The page carries seven hand-written translations, and none of them could be reached after the first paint. Looking for why, it turned out the language was not the only thing this page did differently. Four protections that every other landing has had for weeks were missing here, and each one was visible: the cloak that hides the page until it is ready hid the studio’s own sidebar and top bar too, although they arrive already drawn, which is why a reload of this page, and only this page, made the whole frame blink out and back; the opt-in that lets one page fade into the next was absent, so walking into Shift from the rail was a hard white-then-dark reload; a single line of styling was missing from the head, so the first frame was painted with the browser’s default margin and the whole page jerked eight pixels on every load; and a render that failed left a white screen where every other product shows a branded page. All four are in now, copied from the pages that had them. Two more were quieter. This was the only page in the whole site declaring itself Russian while rendering English: a link pasted into a chat previewed in one language and opened in another, and a screen reader picked Russian phonetics to read English text. And it was the last product page from which the privacy policy, the terms and the refund page could not be reached at all, while the visitor counter ran on it like everywhere else. The seven translations were not touched: not a word rewritten, not a word machine-made. What changed is where the page looks to find out which of them to show. And since the translations exist, they now have addresses of their own: six crawlable pages, one per language, with head copy written from the page rather than translated from the Russian.
A blind tester downloaded an Arabic voice, opened an Arabic page, and heard nothing at all
He did everything right. The catalogue showed the voice, the download finished, the page was Arabic, and the browser was silent. What he could not know is that the silence came from a guard put there on purpose a week earlier, for a good reason. Beyond the alphabets (Latin, Cyrillic, Greek) a synthesiser handed text it cannot read does not speak with an accent, it reads out the NAMES of the characters: an English voice on a Japanese sentence produces ten seconds of «Japanese letter, Japanese letter». So a phrase in a script the voice does not know is refused and handed to the person’s own screen reader instead, which is the right answer. The flaw was narrower and worse than a wrong rule. The guard asked whether ONE voice, the one chosen in settings, could read the phrase, while the speech engine had for a week been able to read a single sentence with SEVERAL voices, switching per fragment by the page’s own lang markup. The rule for «which voice reads this fragment» lived inside the function that splits a sentence up; the guard stood above it and knew its own, narrower version. Two places holding one rule differently: that was the whole defect. So the Arabic fragment was thrown away before anybody asked whether an Arabic voice existed, and the installed one was never consulted. A second, quieter hole sat underneath: the engine records «no voice for this language» inside the very function that was never reached, so he did not even get the sentence explaining what was missing. Silence, and no reason for it. Both are closed: the guard now judges each fragment by the voice that will actually read it, and a refusal records the missing language either way. The guard was not removed, it was taught: Japanese without a Japanese voice is still refused and still goes to the reader. What makes this one worth writing down is the instrument. There WAS a stand for Arabic reading, and it was green the entire time the product was mute, because it called the sentence-splitter directly and walked straight past the guard sitting above it. It now asks the same question the product asks, by the same name; proved by breaking the fix on purpose, which turns exactly those checks red and leaves the rest green. Three more things he asked for, all of them the same shape: the product was right and the person could not tell. Settings had their own menu entry and their own shortcut, and we had written to him twice to say so; the entry was called «Appearance settings» and sat under Accessibility, so somebody walking the menu bar by ear, listening for the word «Settings», never heard it. It is called Settings now, in all twenty-five languages, and the rename exposed a gap in our own translation pipeline, which fills in MISSING keys and leaves changed English alone while stamping everything as up to date, so twenty-two languages would have kept the old wording with every check green. It also stopped being a toggle: an item named Settings that closes settings on the second press is indistinguishable, without a screen, from one that did not work. Several menu items led into settings and all of them landed at the top of a page with over a hundred stops; jumping to a named section is now how every one of them arrives, which is what «Sign-in keys» in the account card should always have done. And downloading a voice from the settings list reported nothing: the percentages were spoken aloud at the quarters and sent to two other screens, but not to the list itself, so sixty megabytes went by with no way to check whether anything was happening. A spoken quarter cannot be re-read; text can. The figure now sits beside the button as plain text, in megabytes when the server declines to say the total rather than inventing a fraction, and the button tells a screen reader what it is doing and to which voice.
A blind person hit the certificate screen and heard only that the page had failed, not that the way past it was one Tab away
A site with a broken or self-signed certificate does not open, and it should not: that is the browser protecting somebody. But it is also the single most common way a page refuses in the countries where our users live: a municipal site, a clinic booking form, a small shop whose certificate expired last week. Our own screen appears instead, and it has two buttons on it: try again, and continue anyway with a warning about what that means. Sighted people see both. A blind person heard one sentence,«the page did not open, here is why», and that was the end of it. The second button existed, was reachable by keyboard, was correctly named for a screen reader, and was never mentioned, so the only way to discover it was to Tab around a screen you have just been told is a dead end. Most people do not; they conclude the site is unusable and leave. The announcement now names the escape hatch by the same label the button carries, so what you hear and what you land on are the same words. What makes this one worth writing down is how it was found and how it is kept. The acceptance rig had four checks pointed at this screen, all four green, all four measuring the OLD behaviour: a neighbouring session had deliberately changed the policy weeks ago and the checks had quietly adapted to the change rather than catching it. Green there meant nothing. They were rewritten to five, and the fifth was proved by breaking the fix on purpose: with the announcement disabled the run goes 547 of 548 and points at exactly that line, and green again when it is restored. A check that has never been seen to fail is not a check. Three other instruments turned out not to have been running at all (the context menu, the tab strip and the mouse ring) each failing in under a second with a message about a missing export, which is what Electron says when the editor’s own environment variable makes it start as plain Node instead. They had been failing that way silently, so this release is the first in some time whose gate is what it claims to be: 117 instruments, and the three that were pretending are now among them.
The page had been saying twenty-one languages and thirty-two voices out loud, in every language, for weeks
The Arabic page opened with an ENGLISH voice, because the track had never been recorded, and the code politely falls back to English when a language has none, which is the correct behaviour and the reason nobody noticed. It is recorded now, and it is the only language on the page read by a native rather than by the English narrator who covers everything without one: the other languages are heard by a sighted sceptic to whom an accent is no obstacle, while the Arabic page is heard by a blind speaker for whom the track IS the product. Modern Standard, not a dialect: one page for the whole Arabic-speaking world. Then the recogniser we used to check it read the last sentence back, and the last sentence said twenty-one languages and thirty-two voices. Counted against the engine’s own catalogue rather than against memory: forty-six entries, of which four are a second speaker inside the same package (still forty-six things a person picks from) across twenty-two languages. So the number had been wrong on the page for weeks, and wrong in a place nobody reads: it is the first thing a blind visitor hears, forty seconds in. Two places in each of twenty-five dictionaries, and because the numbers are written as words this was grammar rather than digits: Polish changes the noun’s case, Arabic the gender of the numeral against «لغة» and «صوت», Hungarian turns huszonegy into huszonkét before a noun. Three more places turned up on the way, none of them where anybody was looking. The Japanese track carried a THIRD number of its own: twenty-seven voices, in digits, next to a bullet on the same screen that said thirty-two: a Japanese reader saw one figure and heard another, and both were false. The same paragraph sat on the documentation page. And in the internal voice document, which is most likely where the page copied them from in the first place. All twenty-five tracks were re-recorded, and four of them (English, Russian, Japanese, Arabic) were run back through speech recognition to confirm the spoken number matches the written one. The Japanese needed the larger model to settle: the fast one heard «にょんで16» where the track says forty-six, which is the instrument being wrong rather than the recording. One quiet improvement underneath all of it: these twenty-five tracks had never been made by any script: they were typed into a web interface by hand, which is exactly why a new language of the page stayed mute. A new language is now one command, and the text comes from the same dictionary key as the transcript printed under the player, so what a deaf visitor reads and what a blind visitor hears cannot drift apart.
Legato is in the Microsoft Store, which is the first way to install it on Windows without being told it might be a virus
It was submitted for certification on the 27th and passed on the 28th, including the part nobody could predict: the permission it needs to run a full browser engine, its own speech and a conversation with the accessibility services is approved by a person at Microsoft rather than by a machine, and that person said yes. The page is live, the search finds it, and it is free in all 240 markets. What this changes is narrower and more important than «we are in a store». Our own Windows installer is unsigned, because the certificate has been paid for since the 9th of August and is stuck behind a postcard sent by ordinary mail from Houston to Zaporizhzhia, so SmartScreen meets the file with a window in which the only visible button says «Don’t run». The button that lets you continue appears only after you open «More info», and somebody installing by ear has no way of knowing that. The Store copy is signed by Microsoft: no window, no unknown publisher, and updates arrive through the system. So the download block on the page now has four buttons rather than three, and the Store sits second, straight after Windows, because it is the second door into the same system and a person listening should hear the two of them together rather than after two Mac buttons. It is drawn as an outline rather than a fill: the main path is still the direct download, this is the quieter alternative. The arrow leaves a frame instead of pointing down, because nothing lands on your disk: Microsoft hands no .msix to a browser, ever; the install happens inside the Store app on Windows itself. That also means the link does nothing on a Mac, which is the store’s design and not our fault, and worth knowing before somebody reports it as one. Twenty-five dictionaries carry the two new lines, and in Arabic the arrow mirrors, since a sign that points somewhere has to point the way that writing runs. One honest gap: the copy in the Store is 0.3.67, one version behind the site, so it does not yet contain the two fixes Mehdi asked for. The update has to be packed on Windows and go through certification again.
The keyboard stopped being thrown out of the room every two seconds, and a running agent learned to say what it found
Fifteen reviewers went through Offer, Route and Deal, five lenses each, and the same fault turned up in all three products from three different angles. All three redraw themselves while an agent works: the board in Offer every 2.5 seconds, the trip in Route every second, the console in Route after every click. Writing markup that way destroys the nodes, and the browser has nowhere to put the keyboard focus, so it drops to the top of the document. In plain terms: while the agent was working, the page could not be walked with a keyboard at all. Every tick, the person started again from the top. Nobody had reported it, because it is invisible to anyone using a mouse and unremarkable to anyone who has given up. What comes back now is not only the focus but the caret, the selection, and any block the person had opened. The last of those is why the agent’s raw log in Route used to snap shut once a second, which made it unreadable exactly while it was interesting. The second half is worse and simpler. A run was mute. Not quiet, mute: the number of finds was never announced, in any of the three. Meanwhile the one live region on Offer’s screen was spending itself on a carousel of explanatory facts, one every fourteen seconds, and Route’s was reading out the names of the animation steps every 1.8 seconds. The noise was on the empty thing and the silence was on the real one. A blind person could start a search in Deal, sit through twenty minutes, and hear nothing at all: not the start, not the finding of twelve companies, not the end. The end was announced only when the run FAILED. Now the count speaks, and only when it changes; the agent’s own question in Route interrupts rather than waits, because it stops the whole flow until it is answered; and a finished run says so, including when it found nothing, since silence there reads as «still thinking». Three more, each found by measuring rather than reading. A failed run in Offer was reported as «we looked and found nothing», so somebody whose Claude window had run out was told the agent had walked the boards and advised to widen their search: advice that could not possibly help. The Stop button carried a careful guard against the engine dying, written a month ago, attached to markup that does not exist; the real button had none. And Route would move a trip to «ready to pay» when the agent came back with prose instead of an answer: a report with nothing filled in, under a button offering to mark it paid. The studio’s own surfaces were rebuilt in the same pass: the rail was the last thing painting itself from its own token, which is why «make the content darker than the rail» never showed: measured, the two were 0.2 apart in lightness while the headers sat 4.3 above both. One plane for the rail and every header, one for the field under them, and a single soft light from the centre that follows the chosen tint. Not the tint of whichever app is open: that was the reason one screen glowed in two different colours. Where the light belongs turned out to be a measurable question rather than a matter of taste: a soft radial reads as light only on a plane large enough to spread it, and on a strip fifty pixels tall the whole falloff lands inside those fifty pixels and becomes a bright band across the screen instead. So the two tall planes keep it and every strip is flat. The last one to hold out was Route, whose header was not the shared component at all but the app’s own bar, painting itself with two hardcoded colours: a translucent slate with a blur, which made sense while it floated over a coloured canvas, and a dark teal that outranked the shared plane. Measured side by side it sat visibly darker than the rail beside it. Both now apply only on the product’s own page, where they are its identity; inside the studio the bar takes the shared plane and can no longer drift away from its neighbours. One more, and it is the kind that only shows up for the people who need the setting: at the largest interface size the whole page grew a scrollbar and a dark band appeared above the footer. Both were the same arithmetic. The size control works by zooming the page body, so anything measured in rendered pixels and then fed back into the layout gets multiplied twice. The footer was measuring itself that way, 52 layout pixels tall, reported as 67, reserving 88, so the rail and the field stopped twenty pixels short of the footer and the ground showed through between them, and the rail, short of exactly those pixels, started scrolling. The page itself had the same fault one level up: its body is told to be one screen tall, and the zoom then made it a third taller than the window, which is where the scrollbar came from, not from the rail or the content, which is why nothing inside them could remove it. The zoom step is now written down once and divided back out, so the two numbers cannot drift apart. Measured after: zero overflow at all three sizes. And one button on the Ops page was wearing the wrong pair of colours: dark lettering on a mid-blue fill in the dark theme, which is hard to read and looks like a mistake because it is one. The set keeps two separate accent tones on purpose: one for icons, borders and links, which lightens in the dark theme so those stay visible, and one for button fills, which stays deep in both themes and carries white lettering. This button was reaching for the first pair, so it inherited the ink that belongs with a light accent and put it on a fill that had gone light underneath it. Four other products already live by the button pair; this one had been missed. It now measures 6.69:1 in both themes. The first attempt at that fix nailed the lettering to white and broke the same button on the public landing, where the studio’s tint layer does not exist and the fallback lands on the environment’s own bright orange, where white measures 2.54:1. The contrast gate caught it before it shipped, which is the entire reason that gate stands between the build and the domain. The lettering now travels with whichever fill it lands on. Two more things about moving between screens. Pressing the rail row for the tool you are ALREADY in reloaded the whole page. Since each product became its own document, a rail row is a real navigation, and for the tool already open that meant tearing down and rebuilding the entire frame to arrive back where you started, losing your scroll and the tool’s state on the way. It now does nothing, which is what it looked like it should do. And every page carries a small block of colour that paints before its stylesheet arrives, so the screen is never white for a beat; those colours had drifted away from what the studio actually paints. Measured one reload at a time: the light skin showed a warm cream and then arrived at a cool grey, the dark one showed a lighter slate and settled darker. That is the two-colour flicker. All eighteen pages now hand over to the exact colour they land on, inside the studio only; a product’s own page keeps its own palette, which is part of its name. And the page has a third way of healing itself now. It already noticed when one of its own files fails to load, and when the tab is simply holding last week’s build. What neither could see: a file that arrives with a perfectly good 200 out of the browser’s own disk cache and turns out not to be a stylesheet at all: the residue of an old caching fault where a missing asset was answered with a page. No error fires, the build number matches, and the person is left looking at bare markup: a list of links and a system media player where the tool should be. That is what one of us hit on the live site while the server was serving 1342 rules and a clean browser opened the page whole. The check is direct (a stylesheet that produced no rules did not apply) and one refresh puts it right.
The home page became a drum, and the studio stopped painting itself five different greys
The home page used to be a shelf of tiles. It is a conversation now: a line says what a person needs («I need to find a job», «I need customers») and the line under it answers with the name of the tool that does it, which is also the line you press. Seventeen of them turn on a wheel, one detent at a time, with a click; the sound has a switch and the whole shelf is also there as a plain list for anyone who would rather not turn anything. What the rebuild found underneath was worth more than the page itself. Measured across thirteen screens, the rail sat at one shade and the panels inside the apps at five others (0.037, 0.029, 0.025, 0.021, 0.017) and nineteen different border tokens were in use. Nobody had chosen any of that against anything else: each app had reasonably invented its own, and the studio was the first place they met on one screen. There are two planes now, one line colour and one speed, all of them read from six values in one block, so changing a number moves the whole studio: both themes, both styles, twenty-five tints, every app. The header strip above each tool became one component rather than eight, opaque and sticky, and the corner of a card went back to the style switch: 4px in classic, 14 in modern. Three faults were only findable by measuring rather than by reading. A button whose label stayed dark on a coloured fill through three attempts to fix it, because the button has no colour of its own at all: it inherits one, and inheritance cannot be beaten by a selector. Pages that appeared to slide into place on load, which was never an animation: the class that says «we are inside the studio» was added after the first paint, so the page drew itself as a standalone landing and then snapped. And a divider in one product, meant to be a hairline, arriving 92 pixels tall. The gate on the way out caught a fourth, which the same tidying had just created. Once the legal and about pages started reading their colour from the shared set, they took the accent meant for FILLING a button and used it for WORDS, and on the dark ground that is a step too deep: links at 3.74 against the 4.5 the standard asks for, section headings at 4.45, inline code the same. Four hundred and sixty-seven pieces of text across thirteen pages, and none of it visible to anyone reading the stylesheet, because the rule said «accent» and the accent was correct, for the other job. The set has carried a separate tone for small text for weeks; these pages simply did not know about it. Nothing shipped until all four hundred and eight page-renders came back clean. The keyboard gate then stopped it once more, on the drum itself. Seventeen of the forty-nine places focus can land on the home page had no ring around them: they changed colour and grew an underline, which tells you nothing if you did not see the state before. That list is invisible until it takes focus, so the ring is the only thing that says WHICH of the seventeen you are standing on; it was switched off in our own stylesheet. It is back, on the list and on the answer, and the mouse keeps the quiet underline it had.
The Legato page speaks Arabic too · and the photograph found what the code hid
The browser learned Arabic this morning; the page it is downloaded from was still written in twenty-four languages, so somebody whose browser spoke to him in his own language arrived at a page that did not. Twenty-five now, and the first one that reads right to left. The writing direction is set beside the language, in one line: without it an Arabic page lays out left to right: lines pushed against the wrong edge, and a screen reader walking the markup rather than what is visible, naming things in an order nobody sees. What makes this worth writing down is the two faults that the code could not show. The language switcher came out EMPTY. The name and badge tables are declared as complete records over the language type, and the comment beside them promises that a forgotten language breaks the build rather than the page. It did not break: the build strips types without checking them, so the guarantee that comment relies on does not exist. In the photograph it was a blank pill where «the Arabic» should be. And three arrow glyphs pointed backwards. The layout swaps the sides of a row, but not the sign inside it, and in right-to-left «onward» is leftward, so each of them pointed at what had already been read. Ticks and crosses have no side and were left alone. Checked by picture rather than by argument: twenty-seven screens in a row, nothing over the edge. The dictionary is machine-made and NOBODY HAS PROOFREAD IT, unlike the eight second-wave languages, which were read by a human. That is written into the file itself. The judge is the same blind Arabic speaker who asked for the language in the first place, and until he says otherwise, Arabic is not announced anywhere as finished.
Legato 0.3.68 · the browser now closes itself so the installer can work, and the interface learned to run right to left
Mehdi, a blind tester, updated on Windows and wrote down exactly where it stopped being simple: the installer opens, you press Next, and it tells you to close the browser first. For someone sighted that is one extra click. For someone listening it is a dead end in the middle of an update: «now what do I do, and how do I get back to the installer after closing the program?«. The browser closes itself now. It says out loud that it is closing so the installer can work, waits for the sentence to finish, and goes; the last page of the installer has «Open Qiksy Legato» on it, which is where you come back from. Only on Windows: on a Mac you copy the app out of the disk image by hand, and the browser is still needed at that moment. He also could not find the Arabic voice in the settings by ear, and the reason turned out to be duller than an encoding bug: the voice was named «كريم», in a script that nobody who can reach that list is set up to read. It is called Kareem now, in Latin letters, and the native spelling comes back the day there is an Arabic interface to put it in. The interface itself learned right-to-left, and the honest half of that story is that three of the faults it uncovered were never about Arabic. The back and forward arrows did not mirror: the buttons swapped places with the layout while the glyph inside kept pointing left, so the first button pointed the opposite way from what its own label said. The buttons inside the new-tab search field were pinned to the right edge while the space reserved for them travelled with the text, so the placeholder ran into the icons, and that one was found by photographing the screen, not by reading the code, because the measurements said everything was fine. And the «skip to content» link, hidden off-screen the classic way with left: -9999px, stretched the toolbar by nine thousand pixels of horizontal scroll, because in right-to-left «off-screen» becomes «into the document». Seventeen asymmetric paddings moved to logical axes at the same time; not a pixel changed in English, which was checked rather than assumed. Every screen and every pop-up was then opened one at a time in both directions and measured against itself in English, thirty-three pages and ninety-one states, and the mirrored comparison came back clean. There is an Arabic dictionary in this build, all 3203 keys of it, and it is machine-made: no native speaker has read a word of it yet. It is marked as unreviewed in the repository for that reason, and it is not being announced as a finished language until someone who reads Arabic says it is one. One more thing, and it is the least comfortable. This release was stopped at the gates by a stand that had been failing silently: the walk through the first five minutes after installation, the ones in which a blind person decides whether to keep the browser at all. It needed a WebSocket that this version of Node keeps behind a flag, and it fell over before testing anything, while the gate above it went on reporting success. Nobody knows how long it had been dead. It runs now, and it passes.
A page froze for seven seconds and would not take a keystroke · and it was us, not the network
The owner opened Google Translate: five seconds before anything, and the input box refused to take a single letter. The obvious suspects were all wrong. It was not the network: measured side by side, a plain engine and ours both reach readiness in about 700 ms. It was not the cache either, which is why reloading never helped: a cache saves network, and what we were spending was the page’s own main thread. The profiler named the culprit outright: 94.5 % of our scan sat inside one check. To describe where a finding lives we build a CSS path from the node upwards, and from the eighth level on we asked the WHOLE document, at every single level, “does this path match exactly one node?”, with a long selector, a document of sixteen thousand nodes, hundreds of findings. The question turned out to be unnecessary: a path carried all the way to the root, with the child’s index at every level, is unique BY CONSTRUCTION. We now ask only where the path had to be cut short. Scan 6954 → 352 ms; the contrast measurement 7216 → 289 ms. The repairs themselves are untouched, and so is the shared cache: its key is computed from the node’s markup, never from the path, so not one hash moved. The guard that protects this was built wrong twice, and that is worth writing down. The first version measured milliseconds on a synthetic page, and with the fault deliberately put BACK it stayed green: the trouble does not live in depth, it lives in AMBIGUITY: the old code stopped as soon as the path became unique, and on generated markup it becomes unique immediately. The page is now forty identical branches, so a path tail matches forty nodes rather than one, and the measure is no longer time but the number of document-wide queries per finding: the disease itself rather than its shadow, and independent of how fast the machine is. Starved, it reports 9.0 queries per finding against 0.0 healthy. Also in these two releases: a Help menu, because a totally blind tester wrote that he had no way to find out which version he was running, and “you have the latest version” is a black box to someone who cannot read his own version number: he cannot tell a successful background update from a fetcher that is quietly failing. The check now says the number in the same breath as the verdict, and About / Guided Tour / Check for Updates live in the menu bar, where help is looked for without needing to know a shortcut first. One more, found by the keyboard gate on the way out: on the download page the very first thing a keyboard user meets, “skip straight to the download”, pointed at an anchor that does not exist on that page, so it did nothing at all, and silently. That is the worst shape a fault can take: you press, nothing happens, and you cannot tell whether the page is broken or you are. The heading level under it jumped from one to three as well, which breaks the outline a screen reader walks by.
Legato 0.3.65 · the file that never reached the site, and four instruments that were measuring the machine
Uploading a file to somebody else’s site had been failing silently, and the reason is worth stating plainly: almost every modern uploader creates an <input type="file"> on the fly, clicks it, and removes it from the document again, keeping only its own reference. Legato refused to deliver into a field that was no longer in the document, so you chose the file, pressed the button, and nothing happened, with no sound and no message. Listeners live on the element rather than on the document, so it delivers now, and the stand has that exact case: it goes red without the fix. The file panel also opens where you took a file last time instead of always in your home folder, and it scrolls in one place. The whole window used to scroll, carrying the “where am I” line off the top edge, which for someone listening is the one line that answers the question the panel exists for. The right-click menu had been cutting words off on Windows: the card measures itself to ask for a window its own size, and it was doing that before the interface font had arrived, so it was measured in the fallback face. On a Mac the fallback is near enough in width to hide it; on Windows it is Segoe UI, and “Open in another browser” came out as “Open in another brow”. It measures a second time once the font is ready. The focus ring Legato draws on sites that have none now appears from the keyboard and not from the mouse. :focus-visible was not enough on its own, because it answers “does this element need a visible focus mark”, and for a text field the engine answers yes even for a plain click, so clicking into a search box put a heavy ring around it for a sighted user who did not need one. The tab menu gained “Add to bookmarks”, and the selected section in the side column is marked by a ring rather than a pale fill that measured 1.28:1 against the three that WCAG asks for. Voice catalogue: 46 voices. The uncomfortable half of this release is about our own instruments. Four of them were measuring the MACHINE rather than the product: each waited a fixed number of milliseconds for something whose length is not ours to choose. Under load the synthesis of a single chunk takes as long as a whole phrase used to, so the ear walked out of an area before the browser had finished naming it and then blamed the browser; the voices stand collected half of a seven-language phrase and reported it as truncated; the voice catalogue judged Turkish and Ukrainian with a listener that cannot hear them, and the same voice on the same three sentences scored 13, 24, 61 and 83 percent errors in different runs, and 11 with the larger listener. And a timing-sensitive run was listed for isolation under a name the runner does not use, so for two months it ran in a crowd of fifteen and reddened from the company. One thing is still open and is written down rather than hidden: under extreme load the name of an area can fail to reach sound at all when you enter the toolbar. The phrase-joining that this release fixes is visible working in the trace; the cause is deeper, in the ordering inside the synthesiser, and it is the first item of the next release rather than a line quietly left out of this one.
Record a form flow once, replay it with one press · and six things that had been lying about their own work
Scenarios shipped: press Record, fill the form the way you normally would, press Stop and name it. Afterwards one press replays it: across the steps of a wizard, across pages, and across sites, because a flow is rarely one page and a sign-in hand-off or a payment page on somebody else’s domain is part of it. It waits for you at every page boundary, since a page that has just loaded is not a place to type unasked, and it stops at the first field the page no longer has, naming that field rather than reporting a number. Passwords and card numbers are recorded as fields and never as values, because a scenario is a file you can export and send. The bridge got the same version on npm the same day. The other half of the release is uglier and more useful. A menu built from anonymous divs (which is most hand-rolled ones) was read as an empty list, so the widget was reported as “did not respond” while sitting there perfectly openable; rows are recognised by shape now, not by class name. A read-only box that opens a list was dropped by the scanner as if it were a caption, so the field was skipped SILENTLY and the form still counted complete. “Filled 2 · skipped 2” now names the two, because a count you cannot act on, in front of a form you have to submit, is how a half-filled form gets taken for a finished one. Validate had been answering “everything here validates” about a form with two fields that validate nothing: it looked for a red line “near” the field and “near” could be the wrapper around the whole form, so one field’s genuine error vouched for its neighbours. The agent bridge’s fast pick was matching an option anywhere on the page, so with a suggest box left open elsewhere the value went to a field nobody had named. And a required asterisk drawn beside a control was being recorded as part of the value, found not by a test but by photographing the panel for this page. Each of those now has a stand of its own that goes red before the fix and green after.
A Spanish message in a Russian interface was being read aloud in Russian. Not any more
The open chat had no way of saying what language a message was in. A page declares one language for the whole document, so a screen reader took every message in that one, so a line written in Spanish came out with Russian sounds, or was spelled letter by letter. This is exactly the fault our own browser exists to repair on other people’s sites, and it was sitting in our own room. Two fixes, because either one alone is half a fix. The language is now worked out when the message is SENT, where the text is whole and fresh, and stored with it: the reader gets a fact rather than a guess made from three words. For everything written before today there is no stored language and never will be, so it is worked out when the message is drawn. Both halves refuse to answer when they are not sure: a short «ok» or «thanks» gets no language at all, because a wrong language mark is worse than none: the reader then says a foreign word confidently and wrongly, and the person listening concludes the text is broken rather than the label. And the page about who we are, which had been reachable only from the footers of some pages, is now in the studio rail with a way to write to us next to it.
The row of counters above the chat feed is gone · what is left is one icon in the header
It arrived three releases ago as five buttons, was cut to one, and is now not a row at all. A whole band of height was being spent on a filter that matters on a long run, which is to say rarely, while the panel already has a header. So the count moved there, beside history and “new conversation”: a funnel with a number, and nothing else. A funnel rather than a flag, because the flag in this window already means “keep this as a finding” and a second flag beside it would read as one more finding. The tooltip says both what the number is and what pressing it will do, because there is no “show everything” button next to it any more: the way back is pressing the same icon again, and leaving that unsaid is exactly the trap the old “all” button existed to prevent. The filter takes both bad outcomes at once, since the number counts both: promising five and then showing three is worse than showing nothing. It appears only when there is something to filter to: no failed steps, no icon, however long the run. Worth writing down is why it did not work the first time: the dock builds a panel’s header exactly once and says so in its own source, “static by design: they fetch their data on press”. An icon whose existence depends on a number therefore never appeared at all, because the panel is born before the conversation. The node is permanent now and its number, state and visibility refresh from the feed’s own redraw, before the early return on an unchanged signature, since that signature guards the body of the feed while the count can change without the body changing. Two smaller things in the same pass. The pressed state of that icon used to add its border on press, which widened the button by two pixels and made its contents jump every time; the border is always there now, transparent until it is needed. And a step’s line was ending mid-word, “did not go th”, because all three of its parts were set not to shrink, so anything that did not fit simply left the panel with no sign it had been cut. The step’s name shrinks with an ellipsis now; the outcome is what the line is read for, so it stays readable to the end.
The row of counters above the chat feed is now one button · and only appears when something actually broke
It shipped two days ago with five buttons (all, errors, held, did not work, done) and four of them were dead weight. Exactly one does something nothing else can: jump to what broke in a run three hundred steps long. The rest are numbers nobody acts on, and the summary card at the end of a run already states them, in words, split into passed / did not pass / blocked / not checked, with an honest note of how many were actually measured rather than asserted. Two voices for one fact, where the second is poorer than the first, is not a summary. It is noise above the feed. The threshold was wrong as well: the bar appeared at eight steps, and eight steps is an ordinary short conversation, so it sat there in exchanges with nothing to filter. Two conditions now, both required: scrolling is genuinely hard, and there is somewhere to jump to. A clean run shows no bar at all, however long it ran; and since the “all” button is gone, pressing the remaining one again is the way back, so it says so rather than leaving you to discover it. Above the bar there was a dead 8-pixel band, because the feed carries a top margin to clear whatever sits above it while the counters are the first thing in that grid and stick to the top, measured before and after, 8 to 0, at rest and at every scroll position. And the “check this” button under an answer, which fills the composer with a ready sentence so it can be sent as it stands, was filling a box and then focusing a discarded one: the feed redraws at that moment, and the element found immediately afterwards is sometimes already gone. It fills and focuses on the next frame now. That one was caught by the acceptance run only in company: alone the check passed, after its neighbours it failed, which is the difference between “it works” and “it works after somebody else has been here”.
Six places in Jig had no background at all · including the bar that asks whether a page may use your camera
A CSS variable that does not exist is not an error. It is silence: the property is simply not applied, and nothing anywhere says so. Six rules referred to tokens this theme has never declared, and the results had been shipping for weeks. The permission bar, the thing that asks whether the page you are testing may use your camera or your location, had no background and hung transparent over the page it was asking about. The row of outcome counters above the chat feed had none either, so text scrolling underneath showed straight through the buttons, which reads as broken layout rather than a missing colour. The digit in the busy-project marker had no colour. The diff, the failure screenshot, the summary of edits and the action log had neither background nor rounded corners. There is now a check that reads every stylesheet and refuses any var() without a fallback that names a token nobody declared: exactly the kind of fault a screenshot cannot report, because on screen it looks like a decision somebody made. Two more in the same pass. The copy-the-address button had left the address field entirely: it is placed inside the field at the right edge, and a list of selectors added for something else (an invisible 24×24 target so small buttons can be hit by someone with a tremor) happened to name this one by its id, which outweighs two classes and silently replaced its positioning. It dropped into ordinary flow, to the left of the field and below its bottom edge, and had been there since 1.2. And the “check this” button under an answer, which exists to hand you a ready sentence instead of making you retype somebody else’s paragraph, was setting the draft while the feed’s redraw ignored it, so it focused an empty box. Last, a run you stop now leaves a trace saying you stopped it, instead of nothing at all: an hour later, which is when a conversation gets reopened, a run that broke off on its own was indistinguishable from one a person ended. Out loud it was worse: the window announced “run finished” after a stop, telling somebody who cannot check the screen that the work was done at the moment it was cut short.
Jig 1.3.3: a page can ask for the camera again, code changes arrive as changes, and the chat reads differently for a tester, a developer and an analyst
Jig used to answer no to every permission a page asked for: camera, microphone, location, notifications, USB. Meant as safety, it worked as a wall: a video call or a map could not be tested inside it at all, and from the outside that looks like a broken site rather than a decision somebody made. There are three levels now. Things a page asks about its own behaviour (full screen, writing to the clipboard, pointer lock) are granted at once, because a prompt for those only teaches people to click yes without reading. Everything else is asked, and until you answer the page simply waits, exactly as it waits for a Chrome prompt nobody has clicked; a minute of silence is a refusal. The answer is remembered per address, and the question is a bar at the bottom rather than a modal window, because a modal takes the focus, the one thing a screen-reader user is holding on to. Second: a file edit in the chat now unfolds into a real line-by-line diff with actual line numbers, read from the file on disk rather than counted from earlier cards, which drift the moment anything above them changes; where two lines are similar the part that changed is highlighted inside the line, because one renamed variable in a sixty-character line is not something the eye finds between two evenly red-and-green rows. The header used to say “+40 −40” for a change of two lines inside a forty-line block. It counts the change now. Open the file puts it in the editor at the changed line; Undo this change puts the old text back, but only if that exact text is still there, so a file that has moved on is not quietly returned to a state it was never in. Third: three people were asked what they needed from the chat feed and independently named the same noise, which is now gone: the random faces on every step (picked by hash, so two identical steps looked different and the eye could not group them), the “thinking…” line, the raw dump of call arguments, and the string of reading steps, now one folded line. Then their paths diverge and so does the feed: a tester gets a row of outcome counters above it, each one a filter, so a three-hundred-step run answers “is there anything to talk about” in two seconds, every step carrying the time, the duration and the address, a failed step turnable into a finding on the spot with a screenshot taken at the moment it failed; a developer gets edits unfolded without a click; an analyst gets the call detail folded away, a summary of what passed and what did not, and the action log moved to the bottom. Both Mac images are signed and notarised and the Intel one was run through the acceptance rig under Rosetta; the Windows installer is still unsigned while the certificate is in validation.
Jig 1.3.2: a blind tester can now work through the whole product · six things stood in the way
The ask was plain: make it possible to test the whole product without seeing it. So three people walked through Jig (somebody using a screen reader, somebody at 200% zoom, and somebody who cannot use a mouse) and everything they hit was fixed the same day. A project could not be opened from the keyboard AT ALL: the plate in the strip is a container with a click handler, the keyboard lands on the name field inside it, and that field listened to one key only, F2, to rename. With a mouse the project opened; with a keyboard it never did, which for somebody who cannot see is not an inconvenience but a dead end. Closing a project happened in silence, because the sentence “project closed, reopen it from Settings” lived on the × button’s own handler: closed from the keyboard, from a command, by the model or from another window, a project simply stopped existing. And twenty-eight controls were under the 24px minimum: irrelevant to a blind tester, constant misses for somebody with a tremor; the isolated ones got an invisible 24×24 target around their centre while the composer’s rows deliberately did not, because two expanded areas side by side overlap and then the miss lands on the NEIGHBOURING button, which is worse than a small target. Then two real screen readers were pointed at it, and each found something every earlier check had called green. NVDA on Windows heard an opened tool announce itself as “document”: focus goes to the first control inside a panel, and an empty panel has none, so focus stayed on the document, and a polite live region does not rescue that, because moving focus cancels it. NVDA also heard nothing where the list of keyboard shortcuts should be: it was spoken at the exact moment the dialog took focus, and the dialog announcement wins, so somebody asking for help got “Jig, region”. VoiceOver on macOS read out the entire first message of a conversation as that conversation’s name, cut off mid-word: invisible by definition, since on screen it is trimmed with an ellipsis and CSS never reaches a screen reader. All six are covered by acceptance that runs on every pass: a tab walk, the accessibility tree read straight from the browser, and the two readers themselves. Both Mac images are signed and notarised; the Windows installer is still unsigned while the certificate is in validation.
Our own JavaScript was answering Google with a redirect, so the pages we built for search were the ones being dropped
Search Console wrote to say that pages listed in our sitemap were not being indexed, reason: «page with redirect». The server was innocent: every one of those addresses answers a plain 200, with a canonical pointing at itself and a full set of hreflang siblings. The redirect was ours, in the browser. A language page has always been allowed to yield to geography: if you never picked a language yourself and the country the edge reports disagrees with the language in the address, we moved you to your own country’s version. That existed for a real reason: someone in Ukraine was sent a link carrying /ru/ and got the Russian landing, a language chosen for somebody else. What the code claimed, in a comment, was that crawlers never see this because they read the prerendered HTML. They do see it. Googlebot runs JavaScript and crawls from the United States, so every /uk/, /ru/, /de/, /es/ and /pt/ page politely redirected it to English, and fourteen of the exact pages that exist FOR search quietly left the index. Nothing navigates by itself now. The page stays where you opened it and makes an offer instead: one line at the bottom saying this page exists in your language, a button to it, and «not now». That is also what Google’s own guidance says to do rather than redirect by IP. The offer speaks the language it is offering, and carries that language on the element, because a screen reader otherwise pronounces Ukrainian words with English phonetics, which is help that arrives as noise. Refusing it is remembered for the visit, not forever. Finding that turned up something bigger that nobody had reported: thirty-four live, prerendered pages were missing from the sitemap altogether: every Spanish, Portuguese, German and Polish version of eight landings, and the whole of the accessibility-audit section. The pages are generated from a config; the sitemap was kept by hand; so every language added since July simply never arrived in it. The sitemap even carried a comment promising that our build fails when a language route is missing from it. That check had never existed. It exists now, and it is the reason this entry can promise it: the build walks the generated routes against the sitemap and stops if one of them is unlisted.
We were comparing a bridge against a script. Now it is bridge against bridge, and the numbers changed sides
Yesterday this page stopped claiming QA Copilot was faster than Playwright, because a fresh measurement said otherwise. Today the comparison itself turned out to be the wrong one, and the owner is the person who spotted it: we were racing our BRIDGE against a pre-written Playwright SCRIPT. A script is code inside your own test process, with no agent, no protocol and no round trip, so of course it wins; it fills the same ninety-four fields in about 0.4s. That is not the thing anybody chooses between. What an agent actually holds is an MCP server, so the stand now runs a real @playwright/mcp on the other side, attached over CDP to the SAME browser and the SAME tab our bridge is working in, which is the generous setup for it, since left alone it launches a fresh blank browser first. Driving the form the way an agent does, one call per field, it takes about 3.0s and ninety-five calls; our one call takes about 1.4s. Median of three runs, and the video on the page is those two runs, with the call counters counting for real. One thing is stated rather than hidden: Playwright MCP also has a batch verb, browser_fill_form, and with it the same form goes in about 0.7s in two calls, but the agent has to build that list of ninety-four fields and their types itself, while ours takes a plain label-to-value dictionary and works the rest out. Hiding that would have lasted exactly as long as the first reader who opened their documentation. The stand is in the repository and runs with one command, both modes.
Legato 0.3.60: postcards you can actually send · and the picture arrives with its own words
A postcard in Legato is made to be heard rather than looked at. Pick a mood, write a line or two, press one button, and the picture comes with it, described in whole sentences, so the person who sends it and the person who receives it end up with the same postcard. The file is plain text with nothing executable in it, it carries its own language, and it is read in that language whatever the receiver has their interface set to: a Russian card under an English interface used to be spelled out letter by letter, and that is gone. The path to the main button is five keystrokes; a council of five blind testers measured forty-seven to reach the field you write in. And the picture can be built a layer at a time (background, who is on it, a magnet across the top) with each layer naming itself as it lands, and one key to hear the whole thing. Behind that, three defects that were only visible from a real screen reader. On Windows every postcard carried the PREVIOUS picture, and the very first one was a plain white sheet: the first frame after a redraw request delivers the old one there, and the code took the first frame it got. Found on an actual Windows machine, not argued from the code, and the person sending it heard “picture chosen” the whole time, because the only instrument said everything was fine. Our own reader announced a CHOSEN radio button or checkbox as “not selected”, in our settings and on every site that builds its own (consent boxes, checkouts) so a blind person could not tell whether they had ticked it. And a licence with no end date read as “0 days left, valid until 1 January 1970” while the screen said “for good”, and quietly rewrote itself at every launch. The file picker is ours rather than the system one, for the plain reason that the system window is the one place our reader cannot help: it now keeps the main button reachable instead of dropping it out of the tab ring, and it says where you are and how many items are there: a sentence the reader itself had been cancelling one millisecond later. Both Mac images are signed and notarised; the Windows installer is still unsigned while the certificate goes through identity checks, and the download page says so and publishes the checksum. There is no in-app update yet, so this one is a download.
The speed claim on the QA Copilot page was wrong, so it was measured and rewritten: one call, not ninety-four
The page used to claim QA Copilot was faster than Playwright, over a video recorded in July. Both halves of that had gone stale, so it was measured again from scratch, and the claim did not survive. The stand is in the repository: one form, ninety-four fields, thirty-nine of them plain text and the rest selects, dates, numbers, checkboxes, textareas, URLs, emails and phone numbers; the page times ITSELF, from the first keystroke to the submit, so neither driver is trusted to report its own score. It is filled twice on two identical clean copies: on the left Playwright over the Chrome DevTools Protocol from a script, on the right our own bridge, and the video on the page is those two runs side by side, unedited, neither slowed nor sped up. The honest result is that Playwright fills this form in about 0.4s to our 1.4s, and on plain native inputs it will stay ahead; it runs inside your test process, and we go out to a browser and back. So the section now says that in as many words, in seven languages, instead of the sentence it replaced. What actually differs is the count: ours is ONE call, one round trip for the agent, one thing to get right, and it stays at one whether the form has ten fields or two hundred, against ninety-four, each of which an agent has to decide on, behind a script somebody wrote for THIS form and rewrites when it changes. Qiksy had never seen this form; it read the page, matched the labels and filled it. Measuring honestly also found a real defect, which is the usual reward: the fill was waiting for a dropdown list to settle after every single field, including the ninety-odd that have no list to open. Ninety-four fields went from 8.36s to 1.36s, and the cap is now paid only by controls that can actually open something, the same reasoning in both places that decide it, the bridge and the extension, because two answers to one question is how a fix half-lands. The old figures are gone from all seven dictionaries rather than from the English one.
Jig 1.3.1: hand a task to the project it actually belongs to, instead of retyping it
A tester keeps several flows open at once, and the mistake is an ordinary one: you start typing a task in this project and realise halfway through that it belongs to the other one, the one pointed at a different folder. Until now the only way out was to erase it and type it again, from memory, in the right window. Right-click the send button, pick the project, and it goes. Three decisions inside that, each against the obvious one: the task joins the QUEUE of the other project rather than starting by force, because work may be running there, and “hand over” must not mean “cut in line”; you STAY where you are, because you are handing it over precisely so you do not have to abandon your own flow, and what went and where is said out loud by project name; and it lands in that project’s CURRENT conversation, since guessing which of its conversations a task belongs to is not something we can do for you. You can be wrong about the project after sending too (it is often easier to spot while looking at your own queue) so a queued task has a fourth button now that hands it over the same way. Alongside it, two things about keeping many flows at once. The ceiling on projects is ten instead of six: six was set in early August after a strip of seventeen ran off under the buttons on the right, and that reason is gone: plates shrink, the strip scrolls, and it now has pinning and an order of its own. Memory is still the real cost, since a project is a live browser with its own session, so a ceiling remains a ceiling and the eleventh is refused out loud rather than by a dead button. And closed projects, which have always come back whole with their tabs, context, checklist and findings, no longer live only in Settings: right-click the + in the strip and they are there, next to the thing that makes projects, in the same place where they were closed. Four acceptance acts cover this, and they judge the ceiling from both sides: that ten open, that the eleventh is refused, and that the sentence explaining the limit names the same number the code does.
Jig 1.3.0: the strip of projects finally says what is happening inside it
Jig has always known which project has an engine working in it. Until today that knowledge left the window in exactly one place, the little × asking “a task is still running here, close it anyway?”, and the strip itself said nothing. A project that is working now wears a dot in its own colour, with a digit from the second lane onward, which is the answer to “why did my next task queue up”. More important is the other half: a project that FINISHED while you were elsewhere keeps its marker until you go in. A dot that vanishes when the work ends tells somebody who stepped away for ten minutes nothing at all, since it was there and then it wasn’t, so the ring stays, and it is cleared by arriving rather than by a timer, with a quiet low tone that is deliberately the least noticeable sound in the set. The project you are standing in never gets a marker; you are looking at it. Pinned projects have no close cross at all, which is the point: the window already knows how to ask before closing, and that is precisely the question people dismiss without reading, and a guard you can click through is not a guard. Right-click unpins; pinned projects sit first. Both strips reorder by dragging, projects and tabs alike. The keyboard reaches them: Ctrl+Tab walks the tabs of the current project and wraps around, ⌘⌥→ and ⌘⌥← walk the projects in the order you SEE rather than the order they are stored in, and ⌘1…9 keeps meaning “tab” as it does in every browser, and taking that away to spend it on projects would be a pure loss. Every move is spoken. A closed tab comes back on ⌘⇧T or from the right-click menu, which also learned to duplicate a tab into a clean cookie jar (“the same page, but I am nobody”, the most common check of the day) close the others, and close the ones to the right. Four acceptance acts were written for this and caught three defects on the way, none of them visible by eye: a pinned project stopped opening on click, “pinned” was being silently dropped by a whitelist of fields, and the first drag implementation was off by one when moving rightward. Both Mac images are signed and notarised; the Windows installer is still unsigned while the certificate is in validation.
Jig 1.2.9: on Windows the engine now arrives · and is recognised when it is already there
Jig fetches its engine once, by itself, so that nobody has to open a terminal. On Windows that had two failures stacked on top of each other, and the first was the cause of the second. It could not SEE the engine it had already installed: the check asks the binary for its version and waited four seconds, and a cold start of a 330 MB executable that Defender is opening to scan at that very moment does not fit in four seconds, so “did not answer in time” was being cached as the final word “there is no engine on this machine”, and Jig went off to download a second copy. It waits twenty seconds there now, and a negative answer that came from the timer is not remembered at all: it is about that second, not about that machine. Then it could not PUT the new copy in place, because renaming a finished download onto the final path fails while any process holds that file open, and the process holding it was Jig itself, having just asked the old engine for its version. The old copy is removed first now, both steps retry with a growing pause, and copying is the last resort; macOS passes on the first attempt and never saw any of this. The symptom people met was a red line on the very first screen saying the engine did not arrive, next to a perfectly good engine and a 337 MB half-file nobody could explain. Verified on a real Windows Server 2022 rather than argued from the code: a clean first run downloaded the engine, put it in place whole, left nothing behind, and the app reported the engine’s own version back. This release also carries the voice fix from 1.2.8, so voice input works again on both systems.
Jig 1.2.8: voice input works again · it had been broken in the two releases before this one
Two days ago Jig learned to answer in the language of its own interface rather than the language of the operating system underneath it. The change was right and the line that carried it was wrong: it asked the settings object for a value the way you would ask a function, so every voice recording and every question that went through that path died on the spot with a type error instead of being transcribed. It shipped in 1.2.6 and again in 1.2.7, which means anybody who pressed the microphone in either of those builds got nothing back: not a bad transcription, no transcription. Nobody reported it. It was caught by the last step of our own full working day on the bench, the one whose only job is to fail if the window threw any error at all during the run, and which is deliberately written so that it cannot be passed by doing nothing. That step is the reason this is a fix and not a report from a customer, and it is worth saying plainly: the feature had a test for what it produced and no test for whether it ran, and the difference between those two is a release. Both Mac images are signed with a Developer ID certificate and notarised by Apple; the Windows installer is still unsigned while the certificate is in validation, so SmartScreen will warn on first run.
Legato 0.3.59: the browser says the uncomfortable part out loud, on the way in
The previous version taught the browser to own up: to mark a name it worked out itself wherever a mistake costs money or cannot be undone, and to answer, on one keystroke, where any name under the reading cursor came from. What it did not do was tell anybody. A feature nobody was told about does not exist for a blind person: there is no glancing at it out of the corner of an eye, no toolbar to notice it in. So the first run now ends on a screen of its own, spoken, before the first real page: pages often name nothing, where a control has no name the browser works one out, that name is the browser’s and not the page’s, and it can be wrong. Three ways to check come with it: the marking that lands on roughly one control in three hundred, Alt+Cmd+N on anything at all, and a switch that extends the confession to every guess. There is deliberately no “I agree” checkbox: the button already means “I heard this”, and for somebody driving the machine with a single switch every extra press costs effort: the acknowledgement is made by saying it, not by collecting a click on a box. The shortcut is never baked into a translation, because the key has a different name on each platform and in each language; the screen exists in all twenty-four, Russian and Ukrainian written by hand. One quieter change with the same reasoning: the “first run completed” mark is now set by the LAST step rather than the second to last, so that closing the window between the Chrome import and this screen cannot make the browser skip the one thing it owes you about itself. Both Mac images are signed with a Developer ID certificate and notarised by Apple. The Windows installer is still unsigned (the certificate is bought and not yet issued) so SmartScreen will warn on first run.
Legato now tells you when the name it just spoke is its own invention
The reason this browser exists is that pages do not name things. A button with no label reaches a blind person as “button”, and Legato answers that by working a name out: from the page’s own markup, from a repair somebody else’s browser made earlier, or from AI, and handing it to the screen reader. Which means the browser is the author of a word somebody then acts on, and that word can be wrong. A guessed name on a button that deletes an account, transfers money or signs you out is not a cosmetic error. So the browser stopped letting its own guesses pass as the page’s. Where a mistake costs something (pay, buy, subscribe, transfer, withdraw, delete, erase, deactivate, close an account, submit, upload, sign out, recognised in the page’s own language as well as in English) it appends “name guessed by the browser” to what it speaks, before you press anything. That is on by default and lands on roughly one control in three hundred. Alt+Cmd+N, on Mac or Alt+Ctrl+N on Windows, asks the same question about anything at all: the browser says out loud whether that name is the page’s own, came from the shared memory of earlier repairs, was written by the AI, or was worked out on this computer, free, no licence, no account. And a switch in Settings extends the confession to every name the browser supplies, not only the costly ones. The first run ends on this now, in as many words and in the person’s own language, before the first real page rather than in a document nobody opens. It is the least comfortable thing we could put on a product page, and it is the honest one: a tool that fills silence for you owes you a way to tell its voice from the page’s.
Dark by default across the studio · and QA Copilot’s pictures are finally the product you get
The studio opens dark now. It has been the other way round since early August, and the reversal is a taste call rather than a discovery, but it is the sort of call that has to be made in one place or not at all: the default lives in a hook and in twenty separate boot scripts, and the moment those two disagree the page paints one mode and repaints in the other a frame later, which reads as a flicker nobody can explain. Anyone who has already chosen light keeps light; the choice always wins over the default. Alongside it, the QA Copilot page was re-shot from scratch. The old images were from July and showed a panel that no longer exists (different palette, different buttons, a different mark on the round button) and a product page whose screenshots do not match the download is a small lie that the visitor discovers ten seconds later. Seventeen states instead of eight, every one taken from the built extension against real data: the findings come out of an actual audit, the session timeline out of an actual walk through four pages with real thumbnails, the fill card out of an actual fill. Each is a PAIR, light and dark, and the page shows whichever matches the theme you are reading it in, because a dark screenshot on a milk-white page reads as somebody else’s picture pasted into the layout. Two defects surfaced from the photographs themselves rather than from any test: the finding-group headers were printing dictionary keys, and a counter said “1 fields”. Both fixed, and the panel’s test run now looks for raw keys on its own, because they contain no English, so the language check walked straight past them.
QA Copilot 1.12.0: the panel finishes the sentence, and it can find a Save button that is not in English
The previous release put the panel into seven languages, and it only got halfway: the titles were translated and the explanations under them were not, so a tester in São Paulo or Warsaw opened a panel in their own language that explained itself in English, which is worse than either extreme, because it looks finished. Every hover tip, every paragraph under a tool, the empty states, the toasts and the placeholders are in the dictionary now, 171 strings of them; sentences that carry a piece of code or a bold word are stored whole rather than cut at the tag, because German and Polish do not put the verb where English does and the word order belongs to the translator. Quieter and more consequential: four word lists decide what SENDS a form, what closes a modal, which dropdown rows are placeholders rather than options, and which field wants a date, and they knew English and Russian. On a German or a Spanish form the tool could not find the page’s own Save button, and it failed silently, because from the outside that looks like “this page has no form”. All four cover the seven shipping languages now, with an acceptance test in which every positive case is paired with a negative one: “Abbrechen” must not read as a submit, “Enviar” must not read as an exit, and a German shop called “Laden” must not be thrown out of a dropdown as a loading placeholder. Findings, session notes and the client report stay in English on purpose, because they are pasted into a ticket that a developer in another country reads. The panel also got calmer: twenty-five muted accent colours instead of eight loud ones, the colour you choose now tints the whole sheet instead of four controls, the light theme is warm paper rather than blue-white, and its shadows are a hint rather than a hole. While measuring that, the most muted text on the light theme came in at 3.4:1, below the 4.5 this very tool flags on other people’s pages. Fixed in both places it appeared.
Pick your own four notes on the Legato page, and read them out over the phone
In a room where several computers are working, a beep from the machine next to you sounds exactly like your own, and a blind person turns towards every one of them. Legato has always answered that by signing its own results with four notes of yours: first “this is me”, then “here is what happened”, but until now you could only meet the feature after installing the browser. The page has it too: type a name, hear the five ways it could sound, keep the one you recognise. A callsign is written in note letters, CEGA or DFAC, so it survives being said out loud: dictate it over the phone, put it in an email signature, read it off a forum post, and at the other end it sounds the same with nothing downloaded and no account. The page also plays the scene the feature exists for: three results in a row from three machines, one of them yours. Nothing plays on its own, every sound is spelled out in words, and the notes come from the browser itself rather than a copy, so the four letters you pick here are the four you get after installing.
Jig 1.2.7: sign it in to a different Claude account from the one your editor uses
Claude Code keeps its login in a config folder, and Jig had never asked for one of its own, so it shared the folder with whatever else on the machine signs in the same way, usually the owner’s editor. One account for both, one allowance for both, and pressing “Change account” inside Jig quietly signed you out of your IDE. Sharing stays the default, because for a developer who is already signed in it is the version with no sign-in step and nothing to discover. What is new is the switch beside it: turn on “Sign Jig in separately” and the app moves into a folder of its own and signs in there, after which the two are deaf to each other in both directions. The switch never signs anything in or out by itself, it only chooses which folder is read, so you can turn it on, look, and turn it back off without losing either login.
Jig 1.2.6: it answers in the language of your interface, and the page now says what your computer will ask on the first launch
Somebody with Jig set to Russian asked the voice assistant a question in Russian and got an answer in English. It read like the model being wilful; it was not. The window was sending the language of the MACHINE (macOS was set to en_UA) instead of the language chosen inside Jig, and the prompt uses that as its fallback for questions too short to judge. A spoken question is almost always short, so the fallback fired most of the time. Four places in that same file already sent the right value; five had drifted, and now all of them agree. The same is enforced a second time in the main process, so a future caller cannot get it wrong quietly. Legato, which was checked for the same fault, never had it: it resolves the setting first and the system only as a fallback, and that is now written down beside the fix. Also new on the download page: a section that says what happens the first time you open the app, on both systems: which window Windows shows, which button is hidden behind “More info”, why it will say “Unknown publisher” while our certificate is still in identity validation, and the checksum of each published file with the one command that verifies it. The name is not what proves the file is ours right now; the number is.
Jig runs on Windows, and we checked it on a real one before saying so
There is now a Windows installer on the download page. What makes it worth saying is the checking rather than the building: the packed build was unzipped on a real Windows Server 2022 and made to run its own fourteen self-test modes there (the first-run wizard, navigation, the gates, consent, the outside door, scenarios, fields, recipes, cross-browser, layout, fit, validation, interruption) and the same fourteen were run on the Mac for comparison. Doing both is what made the answer trustworthy: eight modes failed on Windows at first, which looked damning until the Mac failed in exactly the same eight places. That is not a Windows defect, it is a missing test fixture on both, and one of the eight turned out to be a genuine mistake inside the test itself, where an address was mentioned instead of being substituted, so the check had been failing on its own typo on every platform for who knows how long. With the fixture up, thirteen of the fourteen pass identically on both systems. Honest limits, on the page as well as here: the installer is <b>not signed</b>, because the certificate is still in identity validation, so Windows will show its blue "protected your PC" screen and you have to choose More info, then Run anyway. It installs into your own user profile and never asks for administrator rights. We would rather write that down than let your own computer contradict us a minute after you believed the page.
Jig 1.2.5: the administrator’s lock now holds, account logins stay on your machine, and the allowance is described the way it is counted
Three things an audit found by comparing what Jig says against what Jig does. A company that switches sharing off (with JIG_NO_SHARE or a policy file) sees bothboxes greyed out and a line saying nothing is sent whatever the box shows; that was true of publishing a recipe and false of asking for one, so every form analysis still made a request, from intranet hosts included. It now passes the same two locks as publishing: consent, and the page being public. Second: when there is no Claude on the machine and the question goes through our cloud instead, it used to carry the logins of your saved roles and the addresses of your test stands. Passwords never travelled and still do not, but a login on an internal host is your client’s data, not ours, so the cloud request now carries the role names alone, and the stripping sits in the sending itself so nothing added later can slip past it. Third, and this one was our own price list rather than the product: Pro was sold as “1,000 calls a month” while the engine counts seven separate, non-interchangeable pools. Nothing was ever short-changed (there are 1,440 across the seven) but somebody who used their three hundred failure explanations hit a wall at the 301st call of a thousand they had paid for, and the refusal did not say which pool had run out. The page now lists the pools, and the refusal names the one that emptied.
We ran the same audit a second time without the cap, and it found twice as much, including a hole in the morning’s fix
The first pass had been told to bring back its three best findings per area, which is a sensible way to keep a review readable and a terrible way to learn how many there are. Run again with no cap, and against a list of what had already been fixed, it returned twenty-eight candidates; nineteen more survived a sceptic whose job was to disprove them. The first thing it disproved was our own work: the tab-scope fix written that morning still let a call arrive with no tab named and land on whatever tab the person was LOOKING at, so attaching the app under test and then glancing at your mail pointed the agent at the mail, while asking for that same tab by number was refused. The gate was on the branch that names a tab and missing from the one beside it, which is the exact shape we had just spent the morning removing. Twelve more of the same kind: deleting an isolated session in MultiLogin never reloaded its tabs, so a tab the popup had just called deleted carried on talking to the site with the profile’s real cookies; "Recording paused" kept writing findings and network entries into the report that later goes to a client; a targetless keystroke bypassed the Pro and consent checks that every other verb passes; Legato’s shared name-cache reached the network on every public page with no way to switch it off, under a line promising "no internet, nothing leaves it"; Jig sent account logins and the addresses of internal test stands to our cloud with the question; the engine’s "npx qiksy stop" printed "Everything is off" while launchd restarted it seconds later; and a licence renewal paid the partner who brought that customer nothing at all, silently, while the panel went on showing the client as theirs. All of them are fixed. Seven sets of tests now hold the pieces down, five of them written as pairs that fail in both directions: break the code and they fail, quietly rewrite the promise and they fail too. Each one was checked by sabotage: remove the guard, watch the test go red, put it back.
We went looking for places where our own text promises more than our code does, and found six
It started with a switch. QA Copilot has an “off on this site” setting, and it turned off the part you can see (the panel disappeared) while the part you cannot kept running: the extension was still wrapping the page’s network calls on a site the tester had switched it off on. That is one bug, but it is also a shape, so we went looking for the same shape everywhere else: a promise made in an interface, a store listing or a privacy policy that the code does not keep. Six survived checking, and every one of them had the same cause: the rule was enforced at the main door and missing at the second, quieter one. The bridge to a coding agent limited which tabs it could ACT in, and did not limit which tabs it could READ, so an agent could ask for any tab in the browser by number. MultiLogin Tabs said session data was “cleared when the browser closes”; the cookies were, and everything the site itself stored under that session stayed on disk, including after you pressed Delete. Jig’s administrator lock stopped recipes being published and did not stop them being asked for, so a machine with sharing switched off still made a request per form. Legato’s consent card said only markup was sent, while small cut-outs of the page and the site’s name went with it, and its privacy page still described the version of the product before the repair step could reach the cloud. And Jig’s own landing page, in seven languages, promised a rail that had been deliberately removed at a tester’s request months earlier. All six are fixed, some by changing the code to match the promise, some by changing the promise to match the code, and we have said which is which in each case. Three of them are now held down by tests that fail before a release rather than after one, because the honest lesson here is that all six were written by people who meant it, and not one of them had anything checking.
Jig can now be worked in by somebody who cannot see the screen, and a real NVDA walked it to prove it
A blind tester is usually stopped not by their screen reader but by the product under test: an admin panel that cannot be used at all, so the work is physically impossible. In Jig they never go into that page by hand: they say in words what to check and an agent walks it, which turns the inaccessibility of the site under test from their problem into their finding. Making that true took four fixes. Jig now has a mode for working with a screen reader: with it on the window speaks every step of a run and reads the whole answer, not just its beginning. It had existed in the settings file for weeks with nothing anywhere to switch it on, no checkbox and no key, so the whole channel was written and unreachable; it is a checkbox now, and Alt+A from anywhere. The list of keys opens on F1, because the old shortcut needed a slash, and on the German and French layouts a slash is typed with Shift, which means that combination cannot be pressed at all on the keyboards of two of the seven languages we ship in. The window says one sentence about its keys when it opens, into the live region, invisible to everyone else, and the only way to learn the keys exist without seeing the screen. And the tour, which is the one place the product explains itself, was silent on all twenty-nine of its stops: the focus stays on the Next button, so a changing card is not an event a reader announces. It speaks every stop now. Two more things this uncovered: the welcome screen had been opening EMPTY since 18 August with no way out of it, so the product was not passable by anyone, blind or sighted; and on Windows one press of Ctrl with a digit did two things at once, switching a tab and opening a panel, announcing both. Checked with a live NVDA on real Windows and with instruments on the Mac, and the path (open a page, ask for a check, hear the run, hear the result) is now walked start to finish with nothing but a keyboard.
We drove a real screen reader through the first five minutes, and it found five places where a blind person got no answer
Until now the setup was checked by reading the markup, and markup is silent about the things that decide it: whose voice is talking, whether anything is talking at all, and whether two voices are talking at once. So there is now a stand that starts the installed build on a clean profile, switches VoiceOver on, walks the whole setup with nothing but Tab, the arrows and Return, and writes down both channels second by second: what the reader said and what the browser said, marked as spoken by us, handed to the reader, or said by nobody. The headline answer is a good one: with VoiceOver running, the browser’s own voice stays off and the reader does all the talking. Two voices happen on exactly one screen: the handover, whose entire job is to tell you that you may switch your reader off now. What it caught: the step count promised four screens to everyone, so anyone keeping their own reader heard “step 1 of 4, step 2 of 4, step 4 of 4”, a missing number, and no way to look back and find out what went past. The tour invitation had no name, so VoiceOver announced “dialogue with 3 items” and never spoke the question. The status chip announced the bare word “original” on every new tab. Return on the unavailable “Bring over from Chrome” did nothing and said nothing, which for someone listening is indistinguishable from a frozen browser. And everything the browser says about itself during setup was being written into the toolbar’s live region, a different web area, which a reader standing in the content does not read. All five are fixed in 0.3.55, along with builds for both processors, signed and notarised.
The download button now hands you something that opens, and there is a build for Intel Macs too
The Mac button had been serving a .pkg, and a .pkg was the wrong shape for this product twice over: the system installer opens a wizard with no product name in its title, and it put the browser wherever it was run from rather than into Applications. You could walk the whole wizard, hear “installation successful”, and then find no browser anywhere. It is a disk image now: the familiar window with the app on the left and a shortcut to Applications on the right, signed and notarised by Apple, so the first launch asks one ordinary question and never asks again. There are two files, one per processor: the page used to say the build would not start on an Intel Mac at all, which was true when there was one build and is not true now. If you do not know which Mac you have, the Apple menu’s “About This Mac” says either “Apple M…” or “Intel”, and with VoiceOver that window reads itself out.
The build number moved out of the window corner and into the settings
It sat in the top-left corner of every window, next to the tabs, and it was put there to answer one question during development: is this the fresh copy or the old one. That is a question you ask a handful of times in a lifetime, and answering it does not require a number in front of you all day. The corner is clear now, and the build number stands as a line in the settings, under the switch for talking about new versions, the one section that is about builds at all. Nothing else changed in this release.
The download block on the Jig page stopped saying the same thing three times
The paragraph above the buttons repeated what stood directly under them: that the Mac build is signed and notarised, which the badge three lines below already says, and that Windows is waiting for its code-signing certificate, which is the line right beneath the buttons. Read top to bottom it was the same two facts three times over, and the one thing the paragraph is actually there for, why you would leave an address at all, was buried at the end of it. That is all it says now. The Windows button itself was written out twice, once in the first screen and once in the download block, as two copies with the same classes and nothing keeping them in step, so a change could land on one of them and not the other. It is one control with two call sites now, so the button at the bottom of the page cannot drift away from the button at the top.
Legato now describes the picture you are standing on, not the biggest one on the screen
Browse mode moves a reading cursor and deliberately leaves the system focus alone, as NVDA and JAWS work the same way, because moving focus fires the site’s own handlers. The consequence went unnoticed for months: every command that asked “where is the person” asked the focus, and for a blind reader that answer is always empty. So “describe this image” fell through to the largest picture on the screen, the form summary and the form check each picked the container with the most fields, and could land on different forms of the same page: the table reader took the first table, and “what is this place called” recognised nothing at all. Standing on the third photo of a feed and hearing a confident description of the banner above it is a substitution the listener cannot catch. All six commands now follow the reading cursor. Inline SVG came back into reading as well: a chart with a name had been thrown out together with stylesheets and scripts, so the G key walked straight past it.
A described picture keeps its description, and the next person gets it for free
Until now a description was only spoken. The picture stayed unlabelled, your own screen reader still knew nothing about it, and tomorrow on the same page you would press the key again. Now the description becomes the picture’s alt text, so NVDA, JAWS and VoiceOver read it like any other label, and it goes into the shared memory under the same key the repair engine uses to ask about that picture for everyone else. Whoever opens the page next gets it already described: no AI call, no quota, no keypress. It is the same loop that already runs on button names, with one difference that matters: this description was made by looking at the actual image, not guessed from the markup around it. Only public pages take part, and only the detailed description: a quick skim from the cheap model would have become that picture’s permanent label for everybody.
The privacy section now says what actually travels
The page promised that the sites you open are never sent anywhere. AI repair does send the name of the site, example.com, never the path, the search terms or the order numbers, because without it the model cannot tell what kind of site it is looking at. Consent for it is also asked once rather than per page: allow it, and it keeps working on its own. Both facts are written down now. The numbers describing the limits of the engine were understated too, which is worse than it sounds for anyone checking us before an install: eleven attributes rather than ten, twenty-four ARIA roles rather than twenty-two, twenty-four interface languages rather than twenty-three. They are taken from the validator itself from now on, and a mismatch stops the site from being built.
Windows now stands in the row of download buttons on the Jig page, marked as not ready
Until today the Mac builds were buttons and Windows was a sentence underneath them, on the reasoning that a dead button pretending to be a live one is worse than a line of prose. It is the wrong way round for the person it was meant to protect: somebody arriving on Windows scans the row of buttons for their own system, finds two Macs, and leaves before reading anything below. Windows is a button now, and an honest one: it carries the word soon beside the label, it has no file behind it, and pressing it moves you to the line explaining what is being waited for, which is the code-signing certificate and nothing else. It stays reachable by keyboard rather than being switched off, because the one platform a Windows visitor came to check should not be the one control they cannot get to. It stands in the first screen too, beside the two Mac builds, and the four of them are now laid out two by two rather than in one long row, which read as a menu and ran the width of the page. Its outline is drawn in the full accent rather than a wash of it: the first cut measured 1.84:1 against the page in the light skin, and an outline IS the shape of a control: below three to one it is not a faint button, it is a button somebody cannot find.
Each of the three readings of the Jig page now has an address of its own
Since last week the page has read three ways: for someone testing by hand, for whoever ships the code, for the person who signs the requirements off, and the plates above the headline switched between them. What all three shared was one address, and a page title lives on an address: a search engine can only hold one title per URL, so whichever way you arrived, the head of the document said the page was built for QA. Somebody looking for a browser for developers met a headline that was not about them. There are three addresses now: the page itself for testing by hand, /jig/for-developers/ and /jig/for-analysts/, each carrying its own title, its own description and its own link preview, and each one is written out in full at build time rather than assembled in the browser, because the previews in LinkedIn, Telegram and Slack read the first response and never run any script. The plates stay exactly where they were and do the same thing; they now change the address as well, so the link you copy is the one whose title matches what you were reading. Each reading also carries its own accent from now on: the teal stays with testing by hand, the code gets a violet and the requirements an amber, so the three are told apart before a word is read; only the accent moves, since the ground and the ink are what make the page legible and they were measured to be. The light in the headline behaves differently too: a wide even pool for testing by hand, a tighter source with a visible edge for the code, the softest and broadest wash for the requirements. The product being described does not change between the three, with the same panels, prices and facts, only who the page speaks to first.
Every download button on the Jig page now names the chip
Jig is two files for the Mac, one for Apple Silicon and one for Intel, and until today only the section at the bottom of the page offered the choice. The button in the hero and the one in the middle both pointed at the Apple Silicon build, so somebody on an Intel Mac downloaded a package that will not open at all. The page cannot pick for you: on Apple Silicon the browser reports itself as “Intel Mac OS X” exactly like a real Intel machine, which is why the Legato page asks the same question the same way. Both buttons now stand wherever a download is offered, each carrying its chip in the label. The line beside them was also wrong about the size: it said 137 MB for both files, where the Apple Silicon build is 131 MB and the Intel one 136, measured against the release itself rather than a local build, which is the copy a person actually downloads. It names both now. A number like that is not decoration: it is what somebody on a metered connection decides by.
Legato can be downloaded for Mac · two buttons, because it is two files
The browser is signed with a Developer ID and notarised by Apple, so it opens on someone else’s Mac by double-clicking rather than through a trip into Security settings. There are two buttons and not one because a build for Apple Silicon does not run on an Intel Mac at all: the system refuses it, and a single file would have meant half the people downloading two hundred megabytes to be told no. We do not guess the chip either: a browser on Apple Silicon reports itself as the same “Intel Mac OS X” as a real Intel, so the person chooses and the page says which is which. What arrives is an installer rather than a disk image, and that is an accessibility decision: a disk image asks you to drag the application into Applications, and drag-and-drop cannot be done from the keyboard or described by a screen reader. The installer opens with a double click and is walked with Tab. Windows is still a waiting list: its certificate is issued by a third party and is still being validated.
Jig stops taking the same form apart twice, and now shows how much of the work runs from memory
The first pass over somebody else’s form costs real work: a hand-rolled list of divs has to be pressed, watched and understood. Jig does that once and writes it down: a procedure per control and a whole layer for the form, the order fields take values in, the knots, the places that fought back. From the second pass on it is a read from disk. Settings now carry three rings that say how much of today’s work ran from this machine’s memory, from your team’s under the same licence key, and from the shared memory, with the count of procedures collected, whole forms learned, and model calls that were not needed. The denominator is real: every control Jig filled this week, and five honest outcomes that add up to a hundred, including the one that carries most of the load: twenty-seven libraries the engine knows with no memory at all. Open an unfamiliar application and the share drops; go through it once and it climbs. Two more things changed with it: the shared memory is now served to everyone, with no key and no subscription, because the base grows from those who publish, and they were never the paying half; and a form that a developer rebuilt is recognised as the same form, so what was learned moves onto the new structure and Jig says what changed: these fields appeared, those are gone.
The Jig page now reads three ways, and each one has its own voice
Jig outgrew manual QA: inside the product you say what you usually do: test by hand, write code, write requirements,and the panels arrange themselves around that answer. The landing page now does the same. Three plates above the headline switch what the page claims: the headline, the lead, the pile of windows you recognise as your own working day, the four figures, the section headings. The choice is written into the address, so `?for=analyst` is a link you can send to someone who writes requirements and it will speak to them. What does NOT change is the product: the panels, the prices, what leaves your machine and the editor bridge are the same facts for all three readers, because a page that reshuffles its features per visitor is lying to two of them. Each reading also got its own forty-second narration, recorded in all seven languages with the same voices as the video series.
The catalogue lets the screenshot speak
Every product card carried an accent tile with the product’s icon pinned over the corner of its screenshot, a second mark competing with the picture that was already showing you what the product is. It is gone, in all three densities, and the dark gradient along the bottom of the shot went with it: it existed only to keep that tile legible.
Jig 1.2.3 · a quiet pause is not an error
In a conversation the microphone reopens by itself after every answer, and if you simply read the answer instead of speaking, Jig used to drop a red “no speech heard” strip into the chat right after a perfectly good exchange. An empty turn now ends the conversation quietly; the strip remains only where it is honest, on dictation you started yourself that heard nothing.
Jig 1.2.2 · the voice moved into the chat
Talking to Jig no longer takes over the screen: the conversation window is now a small card inside the chat, floating just above the message box: an equaliser ring driven by the real audio level, the state in words, and a stop that is always in reach. The same card appears when you press “Read aloud” under any answer, and when answers are read out automatically. The composer stays honest about whose ear is open: the microphone button lights up only when you started dictation yourself, because a conversation listening in the background shows it on the card, not on your mic button. Both Mac builds (Apple silicon and Intel) are signed, notarised and live on the download row.
Intel Macs get their own Jig build · same release, second lane
Jig 1.2.1 now ships for Intel Macs too: a separate darwin-x64 build with its own Piper synthesiser and its own locally-compiled dictation binary, signed and notarised like the Apple-silicon one. It went through the same harness before earning its download button: onboarding, projects, the voice question, five parallel chats with per-project cookie jars, and two full create→approve→confirm role chains, all green on the actual packaged app. The landing’s download row now offers both lanes; the update channel serves each architecture its own files. The QA Copilot landing also gained a link to our YouTube channel, where the product is shown working rather than described.
Jig 1.2.1 is downloadable for Mac: signed, notarised, and honest about roles
The Jig page now has a real download button: the macOS build (Apple silicon), signed and notarised, opens with a double-click. The Windows build is ready and waits only for its code-signing certificate. The release itself closes a night of hard testing on a five-app stand: a role’s cookie jar is now scoped to its project, so two roles with the same name in different projects stop sharing a session, proven with five projects on one domain and two create→approve→confirm chains running in parallel, correct signatures at every step. A run no longer mistakes its own freshly opened tab for the tester taking the wheel and stops itself. Passwords, in the role form, the connection token and the HTTP gate, got an eye button that shows what you typed and never submits the form. And the “who answers you” voice question became one radio list: Jig’s own voices for your language plus this machine’s voice, which starts instantly with nothing to download; while a voice is downloading the conversation politely waits, and when it lands, the new voice announces itself.
The home page was a frame around nothing, and the index counted to one three times
The doors on the home screen, the shape the whole layout is built around, were drawn on a surface darker than the canvas behind them: 1.04:1 against their own background on the dark theme, which is not a low contrast so much as an absence of one. You saw a frame around nothing. They now sit on a raised plane that says so three ways at once: the plane itself, a highlight along the top edge, and a shadow. The type had the same problem in a different register: everything below the title lived between 9.5 and 17 pixels, seven sizes inside six, so after the heading the page had no ranks left, only texture. The scale is open again: 52 · 30 · 19 · 17 · 15 · 13 · 11. Two bugs that last week’s zoning introduced quietly went with it: the counter was reset on every list, so “01” printed three times and the numbering stopped meaning anything. The doors closed back to the same 14-pixel step the service cards stand on, because two objects next to a row of cards on a different grid read as somebody else’s page. The hairline under the promise is now the product spectrum: eleven hard segments, one per environment accent, gold through mint. Hard stops rather than a blend, because a gradient would read as an ordinary rainbow, while steps say “these are products”. And the service cards themselves stopped leaning on a coloured stripe to separate them from the background: the real border was 1.3:1 against the canvas, which is to say there was no edge, and the stripe was doing all the work alone.
Switching the theme happened at four different speeds at once
The owner put it plainly: some buttons lag behind when the theme changes. Measured, it was the reverse of what it looked like: the lagging parts were the ones being animated at all. The theme button rode a 150ms default from Tailwind; on the language switch only the border and the shadow moved, so the text and the fill jumped while the frame eased; and the mark and the header’s own background had no transition whatsoever. Inside the hub there was a fourth story: surfaces morphed over 350ms against 250ms for ink, lines and accents, so text finished repainting a tenth of a second before the surface underneath it. One duration now, 200ms, fast enough that hovering does not feel sticky, slow enough that a repaint reads as a morph and not a flash. All four landing headers and the whole token morph in the hub read it from the same place, so they cannot drift apart again.
Two menu items said the same word and went to different places
In the Portal header “Privacy” led to a section of the page; in the footer, a link with exactly the same name led to the legal document. “Pricing” had the identical pair. A screen reader announces one and the same item twice and it goes somewhere else each time, and the keyboard gate calls this same-name-different-target, and it is one of the few faults that holds a deploy rather than warning about it. The header now reads “Your data” and “Plans”, in all seven languages, each label checked against the legal link of the same language so the collision cannot come back through a translation. The footer is untouched on purpose: the document names there are canonical and identical across every landing we run.
This page grew to 127 entries and stopped being readable, so it now turns pages
Building in public has a side effect nobody warns you about: the record of it gets long. This feed had reached 127 entries in one unbroken scroll about 42 000 pixels tall, which is less a changelog than an endurance test. It comes in pages of 25 now, with a pager at the bottom: newer, older, the page numbers, and a line telling you where you are in the whole thing. The page you are on lives in the address, so a link to the fourth page opens on the fourth page. One deliberate decision underneath: the entries you cannot see are still in the page, just hidden, rather than left out of it. This page is what our posts link to and what the email digest is built from, and cutting a hundred shipped things out of the document to save a reader some scrolling would have been a bad trade. While we were in here, the small Shipped and Fixed labels turned out to be drawn too pale on the light theme to meet the contrast standard we hold everyone else to: 2.5:1 where 4.5:1 is the floor. They are legible now.
Your system has no API. Now it has
Qiksy Portal has a page of its own, and it is the first wedge of an idea we have been circling for a while: an agent that works inside somebody else’s web cabinet, under a login, doing what a person would do with a mouse, because the system on the other side has no API to talk to and never will. The page speaks to two audiences, and they are genuinely different people. A business running on Bitrix24 or 1C wants its own numbers out of a cabinet that will not export them; a platform vendor wants to hand its customers an integration it does not have to build. Three steps, an honest privacy section: the credentials stay on the customer’s side and nothing about their data reaches us, and draft prices while the first installations tell us what the work actually costs. Seven languages from the first day, and a card in the product catalogue marked early access, the same way Jig went out.
Thirteen environments stood in one flat list, and the list was drawn twice
The studio held thirteen environments in a single row, repeated in the rail and again on the home screen, while the grouping that would have made sense of them existed only as a comment in the registry: described, never drawn. The obvious axis was “serious versus for fun”, and it was the wrong one: Offer and Route are sold under a licence, and a caption reading “entertainment” above them talks their price down. So the split is by who pays: For business, Open to everyone, For yourself, For partners. Access moved in with the services, because an audit is quoted rather than installed, and Deal moved next to Earn, because it looks for buyers of our own catalogue, which is a partner’s job and not a customer’s purchase. The zones speak through typography and material rather than colour: ten environment accents already share one screen, seven of them in the blue-green sector, and an eleventh colour would have added noise instead of order. The personal zone sits on a recessed plate.
Nine cards offered a choice between one thing and itself
Every card in the catalogue carried two actions, “Open” and “Landing”, and on most of them both led to the same page. That was true rather than sloppy at the time: “Open” used to mean the product’s landing inside a frame under a pinned bar, and when the frames were removed last month it quietly became a redirect to the very page the other button already opened. So on Legato, a browser you download, the card asked you to choose between a page and itself. Now a product says for itself whether there is anywhere else to go. Five keep both: Qiksy Offer, Route and Deal are agents you work in, Check runs its audit in the browser you are already holding, and Access opens the workbench. The rest (Legato, Jig, QA Copilot, MultiLogin and Assist, which install elsewhere, and Pay, Build, Ops and Shift, which are pages you read) keep a single action, and it takes the accent, because one quiet link on a card that wants opening reads as a footnote. The remaining “Open” also stopped going through the front door: it points straight at the app’s address inside the studio instead of the hash route, which made the hub paint its own home page first and travel afterwards.
The catalogue never listed Shift, while everything else in the studio already did
Shift has its own page, its own place at the head of the sidebar, its own promo text in seven languages, and a partner commission that Earn has been counting since it launched. The one place it did not exist was the product catalogue, so the shelf that is supposed to hold everything we do was missing the newest thing on it, and a partner who read the rates list and then went looking for the card found nothing. It has a card now, at the end of the shelf with Access, Build and Ops, because it is sold in a conversation rather than from a checkout, and first among those three, the same order the sidebar keeps. Its copy was written straight into all seven languages rather than the three the studio started with: a card that is blank in Spanish is worse than a card that is not there, because the row around it is full. The room for questions gained the matching shelf as well, because a category that does not exist is a question nobody can file. The card pictures came with it, in the full set the catalogue asks for: both design styles, both themes, both asset languages. Shift had none at all, which the page answers with a broken image rather than a blank space, and Legato’s were shot on the first of August and showed a page that has been rebuilt twice since. Both were taken again from the pages as they stand today.
One format for the settings in every header, inside the studio and outside it
The switch between the two design styles is a mark now, not a pair of words, and the mark names the era its look comes from: a bulb for the modern skin, a flame for the classic one. Sparkles and a palette, which it wore for a few hours the same day, read as “shiny” and “colours”, not what the two skins differ by. One pair across the whole studio. The three settings beside it (style, theme, language) used to sit in whatever shape each page had given them: some framed, some bare, some a capsule, one of them a sixteen-pixel glyph with no frame at all, and on four pages the language select drew a box inside its own box. They are one group now, in one fixed order: style, then theme, then language, then the button back to the studio, with ten pixels between them and a single format: a thirty-pixel square, a one-pixel frame, a body a step lighter than the page behind it, and a hover that moves the frame colour and nothing else. The corner comes from its own token rather than the card’s, because a card’s fourteen pixels on a thirty-pixel button is a circle. The studio’s own top bar follows the same rules, as it was the last place that did not. And the button back to the studio is now on every landing without exception: five of them had only a text link, and Qiksy Deal had no style switch at all, so the classic skin was unreachable from that page.
The studio opens classic and light now, and the switches in every header lost their frames
Two design styles have lived here for a while: modern, which is the cold screen with depth and glow, and classic, which is warm paper by day and faded charcoal by night. Modern was what a first-time visitor got; classic is what they get now. The switch is still there and a choice already made still wins, so nothing moves for anyone who has picked. The controls themselves changed too: a header switch is a mark you press, not a plate with a box drawn around it, so the outlines came off every one of them: theme, style and language, across the whole studio and every landing. Only the switches: the status and rating chips beside them are statements rather than buttons, and a bare “★5.0” reads as text somebody forgot to finish. Two pages had a theme switch and no style switch at all, because the shared control is translated through a stack those pages deliberately do not run; they have one now, in all seven languages. And while every header was open, all nineteen were measured at eight widths in the two longest languages rather than looked at: Shift’s section links were breaking mid-word from 1120px down and its “request a review” button hung off the right edge of the window below 820; Earn’s right-hand cluster ran up to 185px past the window in Russian; the style switch pushed the catalogue’s bar onto a second row on a phone, because “Классический Современный” is 235px of labels where the English pair is 140; and one landing scrolled sideways by 18px because of a decorative glow with negative insets. All four are fixed by placing the rungs where the words actually are, and the rule that a header sheds an item rather than folding onto a second line is the studio’s own, and it now holds in Russian and Ukrainian too, not only in English. The link previews were re-shot in the new skin for the same reason: a card that shows a page in a look the visitor will not meet is a preview of somewhere else. Shift got one of its own at last, as it was the only landing still previewing as the shared brand logo, which is exactly what having per-page pictures was meant to stop. The style switch itself then stopped being two words and became one mark, like the theme button beside it: sparkles for the modern skin, a palette for the classic one, and the icon shows what pressing it gives you rather than where you already are. That also retired a rung, because the pair was the widest control in every header (235px of labels in Russian against 140 in English) and every bar ladder had to drop it first; a 30px mark costs what its neighbour costs, so phones get the choice back. And the language menu stopped scrolling: the panel default caps any list at 280px and seven languages are exactly 280, so a scrollbar was being drawn to scroll two pixels.
The classic style is a second skin now, not the modern one with squarer corners
The studio has two design styles, and switching between them is supposed to change what the page is made of: the classic skin is a quieter palette: aged paper in daylight, soft charcoal after dark, every accent pulled most of the way toward grey, and no glow or shadow anywhere. The Shift page had been given the shape of it and none of the colour: flatter corners, a different reading face, and a palette still running at modern voltage, which is exactly what “classic” is not. It carries the real one now: the same recipe the hub itself uses, applied to the azure, the amber, the green and the ice alike, and the lit edges, the glow pools and the frosted glass come off entirely, so hairlines hold the layout instead of light. Contrast was re-measured on the new grounds rather than assumed from the old ones; all four skins pass. Two places where the switch had been leaking were closed with it: the studio kit was still painting this environment’s chips and hairlines in the full-strength blue while the page around them faded, and the very first frame of a visit was the cool modern canvas, while classic is the default here, so that was the most common first frame on the page.
Two pages stopped promising a box of checkboxes and started showing the work
Both pages used to say the same thing: the same engine can be tuned to your criteria. That reads as a settings screen, and it undersells what actually happens, because an industry, or a market, is not a checkbox but a separate engine. Each page now proves that with something real rather than with an adjective. Offer points at the second industry already open inside the product: care work and IT share an interface and almost nothing else: different sources, their own dictionary of 117 occupations across 25 languages, twelve card fields IT does not have, and two scoring scales with not one coefficient in common. Route points at its second market: local carriers and connection rules that live in the engine as text written for specific routes. Alongside each sits an honest note about the paid scoping session and the fixed-price modules, because “bespoke” without one costs margin. The pages themselves also stopped being brochures: the run is animated as a run: a live feed, a source counter, findings arriving with match rings, and on Route an itinerary that assembles leg by leg instead of a screenshot with the answer already in it. That is also the product’s main objection answered: twelve minutes of waiting looks like work rather than like a stall. Sections that merely restated the subheading were cut. And the Route landing finally speaks all seven studio languages: four of its addresses (Spanish, Portuguese, German, Polish) have been live and crawlable for a while, serving a translated title above an English body, which the file that generates them calls worse than not having the address at all. All 76 lines moved into the shared dictionary, the four missing languages were written, the compiler holds the symmetry now, and the four addresses were added to the sitemap, where they had never been.
One language control across every page, instead of three that did the same job
Three pages had each grown their own way to switch language. Most of the studio used a select; Shift had a two-letter button with a list under it, which reads as a badge rather than as a control; Jig had a hand-written menu with its own Escape, click-outside and focus-return, all correct, and all a second implementation of something that already existed; and Assist had a row of seven buttons, which worked at three languages and became a strip of badges wider than the navigation once there were seven. They are one control now, with a globe in front of the code so a two-letter label reads as a language rather than as any other two letters. Shift and Jig deliberately kept their own language state rather than adopting the shared component wholesale: those pages do not run an i18n stack at all, they carry typed dictionaries, and pulling one in to drive a value it does not hold would be a lot of machinery for a dropdown. The control is shared; where the state lives did not change.
Ops offered seven languages and could only speak three
The switcher on the operations-automation page listed all seven studio languages; the page itself had dictionaries for English, Russian and Ukrainian. Anything else fell back to English, so choosing Spanish, Portuguese, German or Polish changed the label on the button and nothing else, so a control promising a language the page did not know. All four are now written out in full, about three hundred lines each, and the shape is enforced by the compiler: a missing line is a build error rather than a blank spot on a live page. The original rule was kept in every one of them: never name a specific messenger, marketplace or payment rail, because this line is sold in several countries and those are exactly what differ between them; the copy describes symptoms, which are the same everywhere, rather than the customer’s toolset, which would be a guess. Every other app in the studio was checked in the same pass and was already on seven, so this was the last one out of step. The step numbers on that page also lost the rectangle drawn around them: it was a shadow with no corner radius, and it is now a rule that draws itself under the number as the step arrives, continuing the same line that joins the steps into a ladder.
The money-back guarantee is 30 days now, and a refund finally switches the licence off
Outside Ukraine our payments are handled by a merchant of record, and their checkout prints its own “30 days money back” badge, worded as a maybe: an issue that makes the product unusable, and we will consider a refund. Ours said 14 days, unconditionally. Two different promises about the same purchase is the sentence a buyer quotes back at you, so ours is now both longer than theirs and still unconditional: thirty days, first purchase, any reason, nothing to explain. Once per product per person, and that limit is written down as a rule rather than left to a judgement call, because at thirty days on a plan whose term is a month, “the same guarantee applies to every renewal” quietly means a free product forever. An unwanted renewal is still refunded in full within seven days of the charge, with the subscription stopped at the same time; that is a mistake to fix, not a trial to repeat. Underneath, the part nobody sees: when a refund goes through on their side, our licence used to keep working. The money was back with the buyer, the sale still counted as revenue in the partner ledger, and a commission was owed on money we no longer had. All three are handled now, and the term comes off by exactly the term that purchase granted, never to zero, because an earlier year somebody paid for is still theirs. We also walked the checkout with a keyboard: the button that charges you shows no focus ring, and the first tab stop is a control that changes the price. Both are reported to them. That page is not ours to fix, and for a browser built for blind users it is the part that matters most.
A custom deal can now pay several partners at once, each for what they actually did
Until today a project deal had exactly one recipient, and “who splits it with whom” lived in a 300-character free-text note that somebody read by hand at payout time. That is fine with one partner and it is how partnerships fall out with two: a note has no dates, no agreements, and no percentages that cannot be rewritten afterwards. A deal can now carry up to four participants with a role each: brought it 10%, sold it 10%, runs the project 10%, keeps the client 10% for the first year, plus up to 45% for a builder who takes the fixed price and any overrun onto themselves. The totals are pools rather than a list of rates, and that is the whole point: a list breaks on the fourth person, because each new participant increases the sum and the cap starts cutting into somebody else’s money. A pool does the opposite: a new participant divides what is already set aside, so a chain has its own reason to stay short and nobody has to be turned away by hand. Commercial 40% plus production 45% plus a 15% floor for the studio adds up to a hundred, so giving away more than exists is impossible by construction rather than by validation. Shares are taken from the quote minus fees and minus pass-through costs named in the quote: third-party licences, an outside contractor, hardware: money that merely passed through us. A margin guard sits on top for the one case that matters: if both the production and three selling roles are handed outside, the selling shares are squeezed so they cannot eat more than half of what the project actually earned, and the ledger records the rate that was actually paid rather than the one that was promised. All of it is public on the Earn page, in all seven languages, because a rule a partner cannot calculate before agreeing to it is not a rule.
Shift now opens inside the studio, the way the other two service lines do
Every environment in the studio has two doors: its own page on the open web, and the same page inside the studio, where the shell draws the top bar and the rail and the environment hands over a slim header with its own sections. Shift did half of that: it hid its own header when it was inside, and stopped there. So opening it from the rail gave the page standing alone: no studio chrome, no sections in the rail, and no way back out to the full page. It was the only one of the three service lines that behaved differently from its neighbours, and three products with three habits read as three companies. Both doors work now, and the sections light up as you scroll rather than only when clicked, because clicking is not the only way to arrive somewhere.
Two service pages could not be switched to a light theme, for two different reasons
Every landing in the studio carries a light/dark switch, and inside the studio the shell owns that choice and hands it to the page. Standalone, two pages were out. Build simply had no control at all: the page is dark by default and looks intentional either way, so nobody noticed the switch had never been added. Shift had one, in the markup and in the tab order the whole time, but it was rendered without a class, so it came out as a bare button: no border, no padding, an icon the colour of nothing, wedged against the language pill. Not missing, invisible; which is why it read as missing. The other fourteen pages were checked in the same pass and are fine. Shift also lost the 3D on its blue buttons: an outer glow under the button blurred its bottom edge, a white inner line along the top faked a bulge that reads as a film on a coloured fill, and the whole thing hopped a pixel under the cursor, with all three growing together on hover, which is what made hovering worse than not. The buttons are flat now, and hovering answers with brightness instead of geometry.
The price calculator now shows the thing you are configuring, not a sketch of it
The panel beside the options used to be a hand-drawn wireframe, honest about being a scribble, which is a problem on a section called «configure it, watch it take shape». It is now a real interface in a browser frame: the app shell with the screens you ticked, the storefront with the pages you ticked, the assistant with the channels you ticked, and a desktop/phone switch that does not re-draw anything: the preview simply responds, which is the honest way to show that it will. It takes half the block now instead of a third, and it follows you down the options, because ticking a box at the bottom of a long column used to change a picture that had scrolled off the screen. Two options joined the list. Extra languages were always there; a light + dark theme is new at $160, and when you tick it a sun/moon control appears in the preview and actually repaints the window, because showing what the line on the invoice buys beats describing it. The rest of the page grew a proof wall: thirteen things this studio has built, each with an honest label of selling, early access or still being built, anda desk that lays a week out hour by hour, from brief to live. Both service pages, Build and Ops, are also set in the studio’s own typeface now, the Latin/Cyrillic pair that carries all seven languages; Ops gained a live panel where one request walks the whole pipeline with nobody on it, and a board that converts the scattered version of today into the ordered version of afterwards while you watch.
Forms now refuse in the language of the page, not in the language of your browser
A Ukrainian page carried Ukrainian labels, a Ukrainian button, and under the empty field: “Please fill this in”. Two different things were speaking English for the same reason. Pages that check their own fields carried a two-language table and clamped the other five to English. Pages that lean on the browser’s own “this field is required” got the message in the language of the BROWSER, which stays English on most machines no matter what the visitor picked on the page. Both now draw from one dictionary that covers all seven studio languages, and it is pushed into the browser’s own message so the wording still arrives where a screen reader hears it. On a language the studio does not carry (Legato speaks twenty-four) we stay out of theway and let the browser answer, because its Japanese sentence beats our English one. Switching language also clears whatever a form is showing: a refusal is held as a finished sentence, so leaving it up after the switch means a German reader looking at a Polish complaint. The next attempt answers in the new language. Three more things surfaced while walking every form in the studio. The “tell us about the project” dialog, the one behind every “write to us” button, opened in ENGLISH on the Spanish, Portuguese, German and Polish pages, and its Send button did nothing at all, silently, if the contact could not be answered (“abc”): no mark, no message, just a button that refused. The account form, covering sign-up, sign-in, password reset and 116 lines of it, was in the same three languages. And on the checkout widget, the pay button and the line under it were still hard-coded Ukrainian, on the one screen where money changes hands; their translations had been sitting in the dictionary unused.
Assist speaks seven languages, and its mark now carries our own bolt
The landing had three languages while the studio had seven; Spanish, Portuguese, German and Polish have been written out in full, around a hundred and fifteen lines each, including the phone mock-ups and the price cards. Six of them now have their own crawlable address (/assist/es/, /pt/, /de/, /pl/ beside /ru/ and /uk/), each with its own title, description and cross-links, so a search in those languages can land on a page written in them. Writing them turned up something quiet: sixteen keys in the Ukrainian dictionary pointed at a heading level the page does not use, so every section heading, from “How it works” to “What is inside”, the channels and “Why Telegram-first”, had been silently staying in English on the Ukrainian page. Nothing reported it; the page simply looked like a translation that had stopped halfway. Fixed and checked in a real browser. The mark changed too. The bolt inside the chat bubble was a generic “flash” glyph, the one part of the logo that belonged to nobody, and it is now the Qiksy bolt, mirrored so it runs against the bubble’s tail instead of leaning into it. The ring, the tail and the three sparks are untouched; only the bolt was lifted out and redrawn, everywhere the mark exists: the site, the app icons, the favicons, and the widget itself, where it is the face on the button your visitors press.
Team seats now step down with the size of the team
A Jig licence has always carried QA Copilot Pro for the same term, in one purchase. That part is not new and is worth restating, because it is the question people ask first. What is new is the volume ladder on team seats: $129 a seat from ten, $109 from twenty-five, $89 from fifty, against the flat $149 that applied at any size. A ten-person QA department pays $1,290 a year instead of $1,490; fifty pay $4,450 instead of $7,450. The ladder is printed on the price list rather than living only inside the checkout, because a discount a buyer finds by accident is a discount that made them ask for a “company agreement” first. Teams that arrive through the new Qiksy Shift practice have their first year of seats inside the engagement: while the setup is being done the tool is part of the work, and charging for it twice would be strange. From the second year it is an ordinary licence at the prices above.
The docs now cover checking a page against its design, including what to know before reading the report
The Design panel compares what the browser renders with what the design says: paste a Figma link and you get a table of element, property, design value, page value, and the token the page value came from. “The button is painted with the pressed accent instead of the normal one” is a one-line fix; “the colour is 2% darker” is an argument. The overlay does the other half, laying the two pictures over each other with a slider, because a table can never show a block that has moved. Two caveats are documented rather than discovered later: sizes are only compared when the window width matches the frame width, since a design drawn at 1440 read in a 1600 window differs in everything, and the overlay compares blocks rather than pixels, because Figma and the browser antialias text differently and a raw pixel diff would light up every letter of a perfectly correct heading.
A new practice: helping engineering teams ship faster, without rebuilding how they work
Qiksy Shift is the studio’s third service line, and it is deliberately narrow: we do not automate testing. Autotests, CI and the pyramid stay the client’s own business. What we take is the manual half: filling a form of forty fields by hand, running the same scenario a third time, running it again in a second browser, and put it on the engines we already build, so the tester keeps testing and gets the day back. The smaller second theme is front-end: designs carry their spacing and colour as numbers, almost nobody is in the habit of reading them that way, and the task comes back from review. The page itself is new: its own palette, a console in the header that fills a form while you watch, and a request form that is real rather than decorative: three fields with validation, and the lead reaches the same inbox as every other “write to us” in the studio. Two things about that form are worth naming. The old one was three divs styled to look like fields and a mailto: link, which did nothing at all on a machine with no mail client. And when the new one was tested through our own bridge, the validation messages turned out to be invisible to a screen reader: they appeared in the markup but were never announced. Both are fixed. The page also spent a day held back from production: in the light theme the accessibility gate found 206 elements below the contrast floor, and one page was blocking every other fix from shipping. The light theme has been rebuilt since: cold neutrals instead of violet ones, a deeper accent for fills, and the gate is green. Two more gates had things to say before it could ship. The muted text in the light theme measured 3.51 against a 4.5 floor, which was most of the small print in the header console; the run log faded its lines in, and a line caught mid-fade has no contrast to measure at all, so the lines now arrive without fading. On the keyboard side the page skipped a heading level, had no “skip to content” link, so the first Tab landed on the logo, and had no live region, so the form’s own error messages existed in the markup but were never spoken. Two neighbouring pages were fixed in the same pass: the chat room had no h1, so a screen reader started reading from a heading inside a column, and the Jig footer’s “Pricing” link pointed at the studio’s pricing page while the menu item of the same name jumps to a section of that landing: one name, two destinations. The page now also speaks all seven studio languages: Ukrainian, German, Spanish, Polish and Portuguese joined Russian and English, each written rather than translated key by key, down to the company, region and reference numbers in the header console, which read as local rather than as a transliterated Kyiv address. Finally, every form in the studio was walked through, twenty-two of them. Most were fine, but two of the places where someone leaves an email answered silently: the “coming soon” block that sits on products not yet for sale, and the Qiksy Pay landing. Both drew their success and error lines on screen and announced neither, so for anyone using a screen reader, pressing the button did nothing at all. Both now speak the outcome.
We audited every screen we sell from, and the partner programme was the worst offender
Four reviewers went through twenty-nine addresses: every screen inside the studio and every product page, measuring boxes and reading what the pages actually promise. The money found the biggest gaps. The earnings calculator on the partner page priced custom projects as if they were subscriptions: five Build deals showed “$5,000 a year, recurring”, where the same page, two screens down, correctly says custom work pays 10% for bringing the lead and 20% for running the sale, once, on delivery. The till had the mirror-image bug: it paid a flat half-share on every plan, including the Legato work seat where partners are promised 10%, five times too much, in the partner’s favour and out of our own margin. And the shelf and the ledger disagreed about the base: the page said “50% of every payment”, the ledger has always paid 50% of the payment minus the 6.5% card and tax fee. Two numbers about the same money is the kind of thing a partner finds on payout day, so the pages now state the base out loud and quote the figure that actually lands. QA Copilot’s trial said 14 days in the published terms, 14 on one landing and 7 on another, while the extension has granted 28 since 11 August. Qiksy Pay, Ops, Build, Jig and Legato sold from pages whose footers had no link to the terms or the refund policy at all. Referral links stopped being lost in three places: arriving straight at the Jig page counted as “came to the site” rather than “came to that product”, the Assist checkout dropped the visitor id on its way to the till, and the pricing and changelog pages did not record a referral at all. Also fixed: the light theme did not reach the studio’s own frame, so the switch looked dead on the home screen; the chat bubble spoke Ukrainian on English pages because it read the country instead of the page; the investment screen printed two different liquidity figures for one metric and a “+99,999%” that was a formatter ceiling rather than a measurement; five form fields had no name for a screen reader, two pages announced two “main” regions, and the verdict badges under every metric were below the contrast floor in all four skins.
On a phone, half the header was past the edge of the screen
Measured on a 390-pixel screen, and all of it failed silently: nothing was cut off in red, nothing overlapped, parts of the interface simply sat beyond the glass. The Settings tab was at x=458 on a 390-wide screen: a tap at its centre landed on the header, not the button, which made it the one screen on a phone you could not reach, and it is the screen that holds phone access. The language switch was given 23 pixels for three buttons 126 wide, so only EN responded and the language could not be changed at all. The earlier phone rules only tightened the gaps, and no amount of tightening fits a brand, an industry, four tabs and the right-hand cluster into 390. The header now takes two rows on a phone: the tabs get the full width of the second one and swipe sideways, the right-hand cluster gets its own. Separately, every control on the studio’s new settings page was between 26 and 30 pixels tall against the 44 a finger needs, with the theme toggle worst at 26 by 26. They are shared controls that arrived from the desktop header, where a mouse-sized target is right, onto a page that exists only for phones.
Your phone can now use the engine running on your computer
Offer is local-first: your candidates, your searches and your Claude live on the machine that runs it, which is what keeps the data yours and the searches free to run. A phone has none of that, so the panel on a phone was a board that could not load: the screen it reached asked you to install an engine on a device that will never be able to run one. It can now borrow the computer you already have. Turn on “Phone access” in Offer’s settings, type the six digits it shows into qiksy.app on your phone, and the phone gets a way in. Nothing moves to our servers: your computer dials out and holds the line, requests pass through and are forgotten, and Claude keeps running on your own subscription. The code lasts ten minutes and works once, every paired phone is listed on the machine with its own way to cut it off, and the whole thing is off until you turn it on. A phone cannot open the door for another phone, so new codes can only be issued at the computer itself.
On a phone the menu opened at the end of the list
Tapping the menu on a phone showed its tail of Chat, Ops, Build and Admin, while the top of thestudio sat above a scroll position nobody had any reason to suspect. Two things caused it: the whole panel scrolled instead of the list inside it, and the bottom was taken up by a block of four labelled switches. The list now scrolls in its own area and opens at the top, and the bottom of the panel is a single pinned Settings row under the last product. Style, language, theme and interface size moved to their own full-screen page with a back arrow and Esc, a page rather than a route, because the same sidebar is drawn inside every product, and a route would have carried you out of the tool you were using. The desktop is unchanged.
The terms now say exactly what the shared memory sends, and what it never sends
Jig can learn a form once and remember the steps for everyone. A checkbox in the settings was the only place that said so, and a security reviewer reads the document, not the interface. The terms now state what the code actually does. Sharing needs three conditions at the same time: the checkbox, which is off by default and has to be turned on by hand; an explicitly public address, so nothing is ever sent from localhost, from an IP, or from an internal host; and a procedure that has worked twice. What leaves is the shape of the markup and the steps taken through it. What never leaves is the address, the values typed in, the text of the page, and test data. Administrators get their own switch for a whole organisation, named separately.
The studio leads with the tools it makes, not with the work it takes on
Two lists were putting the contract work first. The environment rail, which is also the order of the tiles on the home screen, opened with Ops and Build, so the first two things the studio said were both “hire us”, and the shelf of products came third. It now opens with the catalogue, then the tools themselves (Offer, Deal, Route, Investments), then the partner programme and the open rooms, with the two service lines sitting just above the back office. They lost nothing but their place at the top. In the catalogue itself the cards were ranked by ticket size, which had left Build and Ops sixth and seventh, in the middle of the shelf, between the paid products and the niche ones. Our own tools come first now: Legato, Jig, QA Copilot, MultiLogin Tabs, Pay, then the rest by maturity, and everything sold in a conversation rather than from a checkout closes the list. The free page check still stands next to the paid audit it leads into; they are now the seam between the two halves rather than neighbours in the middle. Also, the catalogue’s own description still named the three products it launched with, while Legato and Jig, the two newest things we ship, were missing from it entirely.
One current Jig mark everywhere, and a light theme that stopped glaring
The favicon would not open at all, the link-preview card was a version behind, and the catalogue shots were taken against a background we no longer use, so three places showed three different Jigs. They all come from the one current mark now. The light theme moved off a cold near-white onto a milk-coloured ground, with the bright patch lifted to the heading and the red deepened; that last part was not taste, the contrast gate refused the build before it.
The language list is ordered for the people reading it
The switcher still opened English, Russian, Ukrainian, Spanish, the order the dictionaries happened to arrive in, back when Russian was the only alternative we had. It now leads with English and then follows the markets the products are actually sold into, Spanish, Brazilian Portuguese, German and Polish, with Ukrainian and Russian at the end; the same order across the studio, the Jig and Legato pages and the Bench, so no two switchers disagree. Nothing about detection moved: your country still picks the language a page OPENS in, a saved choice still wins forever, and the list is read for display and nothing else.
Our landings stopped opening like a business plan
We had a voice written down and it only ever reached our posts, so the products themselves greeted people with concepts. Nine first screens now say the thing a person would actually say. QA Copilot leads with the browser you already have open: your profile, your logins, the tab you are looking at, and no second Chrome asking you to sign in again. MultiLogin is ten accounts, one window and zero incognito gymnastics. Qiksy Offer says out loud that the job hunt is brutal right now, because it is, and that the agents are there to take the grind. Access names where the problems actually live: behind the login, in checkout, in the account, in the dashboard. Business opens with the version you already survived at an agency: three weeks of discovery, six people in the chat, an invoice before anything works. Route starts at seventeen tabs and a spreadsheet. The catalogue admits every tool here was built for ourselves first. What did not change matters as much: pricing, licences, payment errors and anything you forward to your boss stay deliberately boring, and Legato, Check and Forms keep the plain voice they already had, because humour on top of somebody’s hard day is not charm, it is noise. The four kaomoji we did add are wrapped so a screen reader skips them instead of spelling out punctuation. Along the way a sentence in the Jig lead that had broken in half months ago got put back together in three languages.
The studio speaks seven languages, and the language switch became a select
Spanish, Brazilian Portuguese, German and Polish join English, Russian and Ukrainian: every dictionary, not a starter set: the switcher only offers a language once all forty of them are translated for it, because a page that falls back to English mid-sentence is worse than one that never offered your language. Each was written rather than run through a translator: its own register (tú, você, Sie, ty), its own fixed vocabulary, key names taken from that country’s keyboard so a screen reader does not read “Enter” in English halfway through a German sentence, and prices left in the dollars the till actually charges. The switch itself is now a select, because a row of chips works at two languages and falls over at four. Geography changed job with it: your country still picks which language the page OPENS in, but it no longer decides which ones you are allowed to see. Nine landings also gained their own crawlable addresses in each new language, with head copy written for that market instead of translated from ours. Two things this shook loose: the catalogue was printing month names from a hand-written table that had rows for three languages and would have shown a bare number to everyone else, and three of our own release gates were checking three languages out of seven while printing a tick, including one that tested “did it really translate?” by looking for Cyrillic, which a Spanish page passes by staying in English. All three now read every language we ship.
The promo kit folds up, and our own gate caught a button lying about its name
The partner kit prints every product’s copy in all seven languages the page speaks, which is thirteen products × seven cards of prose, and a partner arrives for exactly one of them. Every group now folds: a row with an arrow, the first one open, the rest closed, and the market notes closed altogether since nobody reads those end to end. The trigger sits inside the heading rather than replacing it, so the groups still form a list a screen reader can jump through. Separately, the language pill showed “RU” while telling assistive tech it was “Русский, language”, a name that does not contain what the control displays, so a voice user saying “click RU” would miss it. It passed in English and Spanish by luck (“es” hides inside “Español”) and failed on exactly the two Cyrillic pages. Found by the accessibility gate that runs before every deploy, which is the second time this month it has stopped something we could not see.
The QA Copilot that comes with Jig Pro now has a face, two links and a job of its own
Jig Pro has always included Qiksy QA Copilot Pro, the Chrome extension that is $49 a year on its own, but the page said so in three sentences of prose with nowhere to click, which is how the most generous line on a pricing block ends up reading as a bundle sticker. It now shows the extension: its own mark, its own panel caught filling a seventeen-field form, its standalone price, a link to its page and a link to the store. It also says who each half is for, which is the difference between a promotion and a concept: Jig is the pass you sit down to plan, with named runs, several signed-in roles at once and the difference between last week’s run and this one; QA Copilot is the page that lands in front of you, in the browser you are already signed into, for someone checking the feature they wrote an hour ago or whoever just opened the link in a ticket. Neither half needs a model to measure: forms, findings, the network with response bodies, the WCAG audit and the Tab walk are local and free. Still one-way, because a QA Copilot key does not open Jig.
The Jig page speaks seven languages all the way down, and its dividers stopped sitting on the text
Two passes over the landing. The rules meant to give every divider the same air above and below were written as bare classes, and they lost, silently, to the element rules further up the sheet, so each line kept its space underneath and had none over it. The larger one was the waitlist card: it renders its own heading, paragraph, field and button, and nothing was handing it translated copy, so “Follow the build” stayed in English on the German, Polish, Spanish, Portuguese, Russian and Ukrainian pages. Along the way: the header’s call to action no longer vanishes on a phone, the focus ring now reaches the two things that were reachable by Tab and invisible while focused, the primary button’s hover in the light theme stopped falling under the AA contrast floor, and the classic style squares the whole page rather than half of it.
The empty board now explains itself, and a run shows what it has actually been through
The board with nothing on it is the only screen a person is guaranteed to see before the product has done anything for them, and it was the most silent thing in the app. It now says what will appear there and offers one action, the same control the rail already has, not a second door to the same room, and behind the words stands the shape of a card with no data in it, so the thing being promised is visible rather than described. A run says more too: the sources it went through are named instead of counted, because “9 sources searched” asks you to take our word for it while a list of them is the proof. Chips collapse into “+N” once the strip gets long.
Black text on the main buttons inside the studio
Every primary button on the Offer desktop painted its label with the token the kit reserves for text sitting ON the accent colour, which is nearly black. Inside the studio that put dark text on a dark button; opened on its own the same screen looked right, which is why it survived this long.
A paid key now opens three installations, and the extension makes its first network call
Until this version a key had no device limit at all: the check was entirely offline, so one key pasted by a hundred people worked for a hundred people. Counting cannot be done locally by definition, because an installation has no way of knowing the same key was pasted on someone else’s machine, so the count now lives on our server, and the extension asks it twice: once when a key is pasted, once a day after. It sends the key and a random number the installation generated for itself. Not a device fingerprint: Chrome gives an extension no hardware id, and assembling one out of the user agent, the screen and the fonts would mean shipping a fingerprinter inside a QA tool. That is also why a fourth installation pushes out the oldest instead of being refused, because a reinstall spends a place, and a hard refusal would lock out someone who never shared anything. No page data, URLs or findings ride along, free and trial users generate no requests at all, and every key sold before today keeps working with no limit and is never asked again. The same limit now covers Offer and Route.
The paid features stopped being a list and became something you can press
Care was described in words, as “the AI helps on pages the browser could not fix by itself”, which answers everything except the one question a buyer has: what do I actually get. So the page now carries a made-up website, a nature reserve, with all four problems on it at once, and a button for each. Press one and you see the answer our server really gave for that page, read aloud in the voice the browser itself speaks with: the photograph described, the officialese rewritten with every fact kept, the form explained before you start filling it, the icon buttons that a screen reader calls “button, button, button” given names. Nothing there is written by us: every answer came from a live call, in each of the twenty-four languages separately, because the model answers in your language and the page should show what it will really say in yours.
The browser now tells you when you have picked up something paid, and how long the free month has left
The question about the cloud is asked once per feature and never again, which left nothing at the moment of the press to say that this button spends something and sends something off your computer while its neighbour is free and local. Now the item says so in its own name and in a line under it, and a sound made by nothing else in the browser plays the instant the request leaves, before the wait, not after it. Next to the address there is a label while the free month is counting down and after it has run out, with the way to a key one press away; on a running Care it is not there at all, because a badge that explains a thing that works is only one more stop on the way round the toolbar. When the month does end, the feature now says so straight away instead of going to the network to be refused.
There is a room in the studio now where you can ask us about any of this
Every product had a page and none of them had a door. Now there is one: an open thread for each Qiksy product: Legato, Jig, QA Copilot, Assist, MultiLogin, Offer, Deal, Route, Access, Check, and the parts of the studio that are not products either. Anyone can write, no account needed: a login before “could you add a button?” turns away exactly the people the room exists for. We answer there ourselves, and an answer carries the question inside it, so in a thread where five people are talking it is visible who is being answered and about what. It was built to be usable without eyes from the first line rather than as an afterthought: landmarks, a keyboard route through all four areas, arrows that walk the messages, and live regions that stay quiet while you are reading further up instead of reading every arrival over you. Legato and Jig both open it from their settings, already standing in their own aisle.
The microphone in Legato stopped belonging to the operating system
Dictation used to hand you over to the system: on a Mac it worked, on Windows it did not exist, and the words went somewhere the browser could not see. Legato hears you itself now, with our own build of whisper.cpp with Whisper’s weights, both MIT, running on your own computer. It works on both platforms, understands ninety-nine languages, sends nothing anywhere, and gives the words back to the browser rather than typing past it. The language pack is fetched at the first press, out loud: it says what it needs and how large it is, reads the progress as it goes, tells you when it is ready, and then simply starts listening. Measured on the same phrase, it heard “И заведи находку” where the cloud produced “И заведена ходка”.
Legato reads pages aloud itself, and the page finally says so
Legato has a voice of its own now: switch it on at first launch and the browser reads for you, free, from your own computer, in twenty-one languages. The screen reader you already use stays exactly as welcome: NVDA, JAWS, VoiceOver or Orca keep your voice, your speed, your shortcuts and your braille display, and one shortcut moves between the two in both directions. The page had been saying the opposite for months (“we do not read pages aloud and we replace nothing”), so the whole thing was rewritten in all twenty-four languages, the two sections about who speaks moved up to the top, and the spoken introduction was re-recorded from scratch, now a minute and a half rather than forty seconds, because there is more to say.
Jig’s prices now exist where money is taken, not only where it is advertised
Jig’s page has quoted three prices since it went up: a founding year, a public year, a seat for a team, and the till knew one of them. It knows all three now, the founding hundred is counted rather than promised, and a licence key finally passes the check that was silently rejecting it. The extension that the page says comes with a purchase now actually comes with it. One key opens three computers per seat, and a fourth is told so by name, with the other three listed, instead of being told the key is bad. The checkout stays shut until there is an installer for both platforms: what changed today is that the machinery behind it is real, and the prices on the page are the prices that would be charged.
Jig is signed and notarised, so it opens on a stranger’s Mac now, in seven languages
Until this week Jig ran on the machines it was built on. It is signed with a Developer ID and notarised by Apple now, which means the only thing between a new user and the app is a double click: no Gatekeeper wall, no trip into System Settings, no sighted person required to get past it. That last point is the whole reason the certificate was worth the wait: the wall is exactly the kind of obstacle that stops the people we build for. The interface finished its languages in the same stretch: Spanish, Portuguese, German and Polish, 920-odd lines each, translated rather than machine-passed, which brings it to seven. The built-in walkthrough follows in all seven: fifteen stops, spoken, so a first run explains itself instead of handing over an empty window. The task queue became visible while we were in there, and stopped printing the same task twice.
The audit workbench stopped pretending an empty checklist was a clean site
Two things were wrong with it, and the second one was the serious one. First: every audit opened on the same 42-state Shopify pack, whoever the client was, whether a marketplace with two thousand categories and a one-product store got an identical list, in English, inside a Ukrainian interface. The scope is planned now, from the client’s own robots.txt, sitemap and harvested links: route templates, samples chosen per template, and (the part no crawler will ever find) the states that have no URL at all. The filter drawer, the gallery lightbox, the add-to-cart toast, the login modal that is a modal and not a page. For one real marketplace that came out as 20 route templates and 94 states against the old 42, and 55 of those 94 have no address. Second, and worse: the tool counted defects, and nothing counted looking. Zero findings in an area is equally consistent with “clean” and with “nobody opened it”, and a report that cannot tell those apart is how a partial audit gets sent as a finished one. So there is now a coverage axis: fifteen directions reconciled from the installed axe-core rule catalogue, Lighthouse’s own audit groups, the WCAG 2.2 specification and EN 301 549, with all 55 A/AA criteria landing in exactly one direction each. It is deliberately hard to satisfy: an untouched audit reads 0 of 15 rather than a comfortable green nothing, findings never raise coverage, a full machine pass with no human verdict still closes nothing, and a sign-off shorter than a sentence is refused. That last rule matters because of a number worth saying out loud: automation speaks to 20 of the 55 criteria. The other 35 close only by hand, and anyone promising a hundred percent automatically is selling the 20. While we were in there we ran the tool on its own panel and it failed: three contrast violations, at 4.26 and 4.32 against the 4.5 the criterion asks for. Fixed, because it would be a poor exhibit for an accessibility audit otherwise.
Four more buttons that offered a conversation and opened a draft email
The same fix as on the partner page, applied to the four places that were left. Route’s “book a setup call”, the main button of a section whose entire promise is that we install the thing with you, opened an empty mail draft. The product catalogue’s “pitch your idea” called the support chat widget, and where that widget had not loaded it did nothing at all: you pressed it, the screen did not move, and nothing said why; a bare email address sat next to it as a second door. Assist’s “let’s discuss” about the native WhatsApp integration, the most valuable request on that page, was an email link. So was Qiksy Pay’s “tell us which bank”. All four are now the form the rest of the site uses: it reaches the same inbox and it says on screen that it arrived. One of them needed care rather than a search-and-replace: the Assist page translates itself by rewriting the markup React produced, which is safe only while React never re-renders that page, so the form’s open/closed state had to live outside it, or the first click on a Russian page would have restored the English text underneath. While we were in Pay we found the other half of the same problem: its entire acquirer section, meaning the argument for which banks it works on, the legend of checkout modes, the region names, the statuses and the fee footnote, was hardcoded English on a page that otherwise switches language. Three more section subtitles turned out to have translations sitting unused in the dictionary while the page rendered its own English next to them. The whole section speaks all three languages now, and the checkout modes are named once instead of twice, so the legend and the table can no longer drift apart.
Switching theme finished at four different moments, and the panels were last
The colour swap on the home page is animated on the design tokens themselves, so anything that simply reads a token moves in step with everything else. Anything that carried its own colour transition on top did not: the target of such a transition changes on every frame of the swap, so each frame restarted a fresh chase, and the block landed about a sixth of a second after the page it sits on. On the two big product panels that is what a slow element next to a fast one looks like, and it was reported as exactly that. Making the panels slower would have made it worse; what they needed was to stop chasing. Colour is now a plain function of the token again, and what animates is the AMOUNT of hover showing, so a theme swap moves everything in the same frame while hover still eases in. The same lag was on the header icons, the sidebar rows and the footer links, quietly, because their surfaces are small; they are fixed too. Two pieces of cleanup came free with it: the active sidebar row is no longer a second pair of colours racing the hover one, it is the hover state held down, three points deeper, and the index rows dropped a special-case rule for the classic skin that existed only to say which surface the wash sits on.
The button that offered a conversation was opening a draft email
The partner program has a page for the biggest thing we offer, one country and one partner, and it ended in a button that said “write about your country”. That button opened your mail app with an empty message in it. On a computer with no mail app configured it did nothing at all: you pressed the thing the whole page had been leading to, and the screen did not move. On a computer that does have one, you were thrown out of the page into another window, and nothing ever told you whether what you sent had arrived, because a draft email cannot tell you that. The same button now opens the form the rest of the studio already uses, the one behind every “tell us about the project” on our other pages. It goes to the same inbox, reaches us the same minute, and it says on the screen that it got there. Two more doors on that page were the same shape and are fixed with it. “Request a block or info”, which partners press when a landing is missing something they need in order to sell it, used to do one of two different things depending on whether a chat widget had loaded, chat if it had and a draft email if it had not, and one of those two was silent. It is the same form now, and it carries the partner’s own code with it, so we can see whose sale is waiting on the missing block. And registering a client, which is how a partner claims a lead that never came through a link, used to hand you off to a draft email the moment the send failed, out of the form you had just filled in, with no way to simply try again. Now the page says it did not go through, the button stays where it was, and email is offered as a link you may choose rather than a place you are sent. Last, “start as a partner today” was landing people on the top of the program page, which they then had to scroll past; it goes to the registration card itself.
The site opens light now, and the gold button was never as readable as it looked
A first visit used to arrive in the dark theme. It now arrives in the light one; anyone who has already chosen keeps their choice, because the choice was always stored and the stored value still wins. That default turned out to live in twenty-one separate places: the shared hook plus a small script in the head of every page, which is what stops a page painting one theme and flipping to the other a frame later, and three landings (Assist, MultiLogin, Qiksy Pay) were not reading the shared setting at all, so they stayed dark no matter what you picked anywhere else. They read it now. What the switch exposed is the more useful half. Filled gold buttons carried near-black text, and white was not an option: white on that gold measures 2.5 to 1, which is less than half the accessibility floor, and the dark brown sitting there was the reason why. So the fill moved instead of the text: a deeper gold that carries white at 5.5 to 1 and is legible as text in its own right, which the bright one was not. Business was the last environment wearing one accent in both themes; it now follows the rule the others already did, deep fill in light and bright fill in dark. Then we checked the rest by measurement rather than by eye, and found four more buttons under the floor that nobody had reported: Route at 3.7, Investments at 4.24, Qiksy Deal in the classic skin at 4.27, and the hover state in Forms at 3.97, and that last one made the button less readable at the exact moment you pointed at it. All four are fixed. The fifth took a decision rather than a patch: the violet buttons in the dark theme sat at 4.45 against a floor of 4.5, and the same colour is the link colour on that dark background, so darkening the fill to rescue the button would have dimmed every link on the page. A colour cannot be both a fill and a link colour on a dark canvas, so those are now two separate values instead of one, a split two of our products had already made privately, now part of the shared kit and available to all of them. The violet buttons are at 6.35, the links are exactly where they were, and no button anywhere on the site is under the floor.
The browser is called Legato, and its reference page had a white frame nobody put there
Two things on the feature reference at /legato/docs/. The name first. The landing header has introduced the product as Legato on its own for a while, but the reference page, the browser tab title, every link preview and a leftover key in all twenty-four dictionaries still said Qiksy Legato, so the same product introduced itself two different ways depending on which page you arrived at. It is Legato everywhere now. Qiksy Studio still appears once, in the line naming who publishes it, because that is what that line is for. The frame second. A pale eight-pixel border ran around the entire page, and it was not a border: it was margin. The reference is a separate entry from the landing and deliberately does not load the shared stylesheet, because that sheet fixes the page height and would cut a fifteen-minute read short, and the reset that zeroes the browser’s own default margins happens to live in the same file. So the browser applied its own eight pixels, and the surface underneath was white, because the page’s paper colour is declared on an element that the margin falls outside of. On a dark page that reads as a light picture frame around everything. It is reset now, and the surface itself is painted in both themes, so dragging the page past its end no longer flashes white either. While we were in there the footer moved out of the article and became a full-width rail across the bottom of the window, matching the header, which also makes it a landmark a screen reader can jump to in one key, which it was not while it sat inside the article.
In the classic skin, Russian and Ukrainian were never in the typeface we chose
The studio has two looks, and the classic one was built on a pair of typefaces that ship Latin and Vietnamese and nothing else. Neither carries Cyrillic. So for as long as that skin has existed, every Russian and Ukrainian word in it, the body text and the numbers alike, was quietly drawn by whatever the operating system had lying around: a different typeface mid-sentence, on two of our three languages, on a skin whose entire point is that it looks deliberate. Nothing was broken enough to notice, which is why it lasted. It surfaced because we walked into exactly the same trap again while building something new, caught it there, and then went looking for how long it had been true of the old. Both faces are replaced with ones whose Cyrillic is drawn rather than borrowed, including the Ukrainian і ї є ґ. One of the two was already in the bundle for the other skin, so the site now loads fewer font files than before, not more. Separately, our own accessibility audit had been reporting eighteen failures on the dark classic skin: nine product names in the sidebar, the copyright line, seven footer links, and all of them were one grey that cleared the contrast floor against one background and missed it against the other. It is a single value, and lifting it lifts the whole skin at once. All four combinations of theme and style now pass with nothing outstanding, which has not been true before.
Our privacy policy described an architecture we no longer run
On 3 August the paid AI features moved from Claude Code running on your own computer to our own cloud, so that they work without you installing or paying for an AI tool of your own. The privacy policy did not move with them. For three days it said the opposite of what happens: that the request “does not pass through any Qiksy server, and we never see it, store it or learn from it”, and that turning on a licence key was “the only conversation Legato ever has with a Qiksy server”. Neither was true any more, on the policy page or on the product page in any of its twenty-four languages. It now says what actually happens. When you ask for one of the three AI features, that one image (or the text of that one page) goes through our server, which asks Google’s Gemini using an account of ours. The address of the page is never sent, and neither is your history nor anything you typed into a field. We also say for the first time what we keep: the answer, stored under a one-way fingerprint of the thing it describes, with nothing recorded about who asked, which is exactly what makes the same picture free for everybody the second time round. That store has no expiry date today, and we would rather write that down than round it up. One consequence follows, and we would rather say it than have you find it: a page you ask to have retold is stored as its retelling, so do not use plain words on a bank statement or a medical letter, the free repairs and your own reader are the right tools there. Nobody reported this and nobody could have found it from the outside. A browser sold to people who cannot check for themselves what it sends is worth exactly what its privacy page is worth.
Running out of plain words now has an answer, and the allowance behind it was recalculated
The monthly AI allowance a Care licence carries was checked against what it actually costs us to serve, and one of its four numbers moved: retelling a page in plain words went from 600 a month to 75. That is by far the most expensive thing we do, four times an image description, and on its own it was three quarters of the whole ceiling. Image descriptions were not touched at all: they are the one kind a blind person can never check, so they are the last place we would economise. Quick scans and form summaries came down to 1000 and 200 a month, both still well past what anyone uses. The number the grid is now built from is not the headline $49 but the cheapest seat we sell, $22 in the hundred-seat tier, because anything costing more than that seat earns would mean selling an association a loss. What makes this worth telling you rather than quietly adjusting is the other half. A ceiling you can actually reach has to have something behind it, and until today it did not: run out of retellings and the browser said “come back on the first” to somebody standing in front of a page they needed to read. There is now a free reserve of three retellings a month on top of the limit, the same idea as the ten spare image descriptions. More can be bought by the piece, 100 for $3, and they do not expire, and the browser offers that out loud at the moment you reach the ceiling, and as a button in Settings, in all twenty-four languages. The free trial month now carries forty retellings instead of twenty: the first month is when somebody who has not been able to read the web catches up on everything they could not read, which is the least typical month there is and the worst one to meter tightly.
The home page stopped being a shelf of ten identical tiles
A visitor arrived at a headline promising to find them work and clients, and directly under it got ten tiles of exactly equal size, including the back office, with nothing saying which one to open first. The two products the headline actually names now get real panels in their own colours, and everything else became a dense two-column index with a numeral per entry. The colours were always there, one per product; they had been spent on 32-pixel icon squares nobody could see. Three other things went at the same time. The logo left the workspace, because the top bar already carries it and introducing the brand twice on one screen cost a raster download to do it, so the largest element on the page is now text, which paints faster than the picture it replaced. The status dot beside every product left too: in production it pings paths that always answer, so the red dots only ever appeared on a developer machine, and it marked a slow answer as a broken one: "do not know yet" was being drawn as "broken". And the display typeface was replaced, for a measurable reason rather than a matter of taste: the previous one is a very wide face whose round letters run wider than they are tall, which costs Cyrillic about three times what it costs English, and it has no small-capital forms at all, so the capitals it was drawing had no ascenders or descenders and every product name came out the same rectangle. The Russian headline was landing on three lines where English took two.
We stopped calling ourselves a studio in front of you
The word ran through the interface in three languages: "one key for the whole studio", "the studio storefront", "back to the studio", "bring clients to what the studio sells", about 170 places in all. It is what we call ourselves between ourselves; it is not what anyone is buying. Whoever is here is buying a tool, and the word put an extra thing between them and it. In Russian and Ukrainian it also declines, so it could not be deleted mechanically without leaving broken sentences behind: every line was rewritten rather than edited. Product names are untouched: Qiksy Offer, Qiksy Deal, Qiksy Route and the rest are exactly as they were. Along the way the descriptions on the home index lost a duplicate: Ops and Build introduced themselves as "Qiksy Ops:" and "Qiksy Build:" in a line that already had the name printed beside it.
Paste a link into a chat and you now see the page, not our logo
Sharing qiksy.app/legato/ into Telegram produced the Qiksy logo; sharing qiksy.app/qa-copilot/ produced a picture of the product. The difference was not the messenger: QA Copilot was the only landing pointing its preview image at a screenshot, and the other fourteen all pointed at the same brand card. One logo cannot answer "what am I about to open" for fifteen different products, which is the entire job of a link preview. Every landing now carries a photograph of itself, shot at the proportion messengers actually render (1200×630, so nothing is cropped off the sides of the one sentence the card exists to deliver) and generated by a script, so it can be re-taken whenever a hero changes. Translated routes inherit the picture; the home page and the legal pages keep the brand card on purpose, because there "Qiksy" is the answer.
On a phone the pages could be dragged sideways, and the culprit was one invisible pixel
Every landing could be pushed left and right on a phone, taking the text off the edge of the screen, the kind of thing that reads as "unfinished" before a single word has been read. Measuring all 36 routes at 390px and 320px found six separate causes, and the largest one was invisible by design: the screen-reader-only labels in a comparison table (the words behind each ✓ and —) are 1×1 boxes positioned where they would have sat in the flow, which is inside a table far wider than a phone. With nothing positioned around them they hang off the document rather than the table's own scroller, so one pixel of width added ninety-three pixels of page. The others are rows that could not wrap: three tabs in the partner header (they now swipe as a strip), the report pager, a card whose long word made its grid column refuse to shrink, a button carrying a translated label wider than the screen, and a header where the style switch, the language pair and a large wordmark would not share 320 pixels. The site now also holds a belt for all of it, so the document simply cannot scroll horizontally, using the one CSS value that does this without turning the page into a scroll container and breaking every sticky header, and without being quietly ignored by iOS Safari, which is what the old guard did.
The home page had no door a stranger could walk through, and three dead ends behind it
Every second tile on the home shelf leads to a tool that wants a local engine and a signed-in Claude CLI before it shows anything, so a visitor who has neither has nowhere to go, and thirty days of the live domain produced 120 outside visits and not one second screen. Check is the one product that answers in a click with nothing installed and no account, so it is back on the shelf. The two buttons under the headline now open the tool INSIDE the studio rather than throwing the reader out to the marketing page they just came from. Three dead ends went with it. The renewal banner rose for anyone whose browser held a day counter, including people who had never paid a cent, and it printed a raw slug, "work-finder: Pro закончился", for a product id that was renamed months ago; it now only speaks to someone who actually bought something, about a product that still exists. The "engine is offline" copy, which is read in four different places across Offer, Route and Deal, told people to run npm scripts from OUR repository; they install the engine with npx qiksy and have no repository, so it now names the engine's own commands. And a dead engine used to be visible only in Offer: Route span a search forever, Deal never asked the machine anything while idle, and Access could lock its composer so hard that only a page reload freed it. All three now notice, say so, and recover on their own when the engine comes back.
The partner rate now follows whoever does the work, instead of one number for everything
The partner offer carried a single share and applied it to every kind of deal, which broke the moment custom engineering entered it: a $3 000 MVP paid the partner $2 400 for gathering requirements and the studio $600 for building the thing. There are three rates now, each pointing at the work. Subscriptions off the shelf: 80% to the partner, because the shelf is already built and selling it is the whole job. Custom work where the partner runs the discovery themselves: 50/50. Custom work where we run it: 30/70. A partner sees the gap between 30 and 50 on their first deal, which is exactly the incentive we want on both sides. The offer also answers "I have the idea but no budget for it": we build it at our own cost when three named companies prove the demand, the scope is small, and it queues behind paid work, so the partner gives up exclusivity and origination royalties, not their rate, and the product goes to the whole shelf. Separately, landing pages left the business positioning entirely. We sell engineering work, internal tools and MVPs, and a $199 landing sitting first in the estimator set the price people read everything else against.
Kazakh is the twenty-fourth language, and running out of image descriptions is no longer a wall
Kazakh gets a real recorded track, not the English one played under a Kazakh page: the usual multilingual voice does not know the language and would have read Cyrillic approximately, so the track was recorded with the model that supports it officially. The text is machine-translated and says so, and the first native speaker we reach reads it over, and that is written down as a task rather than assumed. The other half is what happens when a paid user hits the monthly limit on described images. Repeating an image is free and always was, because the cache is checked before anything is deducted, which is now said out loud: each picture is described once, for everyone. On top of the limit there is a small monthly reserve of ten descriptions, so nobody is left standing in front of the one image that mattered. And more can be bought by the piece: 300 for $3, which never expire. A topped-up money balance was deliberately rejected, because a blind user cannot check a melting balance against images they did not see, and would start rationing three-cent decisions.
Two plans had a price, a feature list, and no way to buy them
Assist Start ($96) and Pro ($180) sat on the page with everything except a button, since the only clickable thing under them was the Founding strip, which is a discount on Start. Someone convinced by Pro had to work out for themselves that their door was the cheaper offer. Both prices had been in the till since day one; the link was what was missing. In the same pass, Qiksy Offer got a demo it already had: the scene we filmed the hero video with only opened if you typed a query parameter by hand. It touches no engine and makes no outside request, which makes it the product demo the landing never had, and it is now linked from the hero and, more importantly, from the install screen, where a first-time reader hits a wall before deciding whether they want the tool at all.
The name says what we do, the mark is no longer cropped, and one number is one number
Dropping "Studio" from the name left something short and mute, so the name now travels with a line: tools that run on your own machine, automation that works for your business. It names both halves of what we sell and states the difference at the same time: the tools live with the client, not on our server. The mark itself had been silently guillotined: the lightning tail runs below the baseline into the rows where an old slogan was painted, and the fix that removed the slogan cropped from the centre because the tool ignored the offset it was given, taking sixteen rows off the top of the Q. The raster is no longer cut at all; the browser hides the slogan and the mark draws whole, with the y in the same colour as the rest of the word so the only gold left is the lightning. Finally, the MultiLogin install count was hand-written in nine places and disagreed with itself: three said 697, six said 644. It is the one number on this site anyone can verify by opening the store listing, so a mismatch does not read as a stale copy, it reads as a number nobody checks. One constant now, with the date it was last verified next to it.
The bridge sent people to a panel tab that had been renamed
Opening an isolated login needs its own confirmation, because multi-login intercepts the site's cookies, session cookies included, so Agent control does not cover it. Both the docs and the refusal the bridge itself returns pointed at a "Roles" tab that the panel now calls "Logins", so the one instruction you get at the moment something refuses named a place that does not exist, and a switch looked like a broken tool. All four refusals are now written down with their causes, including the one that is not about consent at all (the tab simply is not in the session), along with the thing that actually unblocks most people: you never have to open an isolated login for an agent to work, because a normal tab is enough. The reference also stopped understating the bridge: thirty-three tools, not twenty-two.
The front page described the furniture instead of saying what any of it is for
The first line of qiksy.app used to read "Your studio desktop. Pick a product below." That is an instruction given to someone who has not yet been told why they would want to pick anything, and the page underneath it offered nine equally weighted tiles, which is nine ways to not decide. It now opens with what the studio is actually for, tools that find you work and clients, followed by the one sentence that matters about how they work: the agents do the searching and the checking, they show where every fact came from, and they run on your own machine rather than ours. Two buttons sit under it, one into the job search and one into the catalogue, both leading to the page that explains the product rather than dropping a stranger straight into a tool that will ask them for things they do not have yet. The nine tiles are untouched, in the same order as the rail beside them, because a home page that quietly rearranges itself teaches the same set of products twice. Three smaller things went with it. The logo lock-up carried a second slogan painted into the image, English only, invisible to search engines, and now a competing promise sitting directly above the real one, so the plain wordmark took its place, which also happens to be the element the page load time is measured by and it is a third of the weight. The description search engines print under the site had gone stale enough to name products by their old names and miss three that exist. And the strapline itself is now a real heading in all three languages instead of a picture of a sentence in one. The card messengers show when someone pastes the link was baked from that same old image, so for a while it was the last surface still making the old promise, in the one place you get a single sentence to land it, and it now carries the new one as text.
Twenty-three languages, and not one of them is answered in English any more
Czech, Swedish, Danish and Finnish finish the European set: the page and the browser now speak the same twenty-three languages, which matters because a screen reader picks its voice from the language tag, so get it wrong and a Finn hears Finnish read with English phonetics. Finnish is the one that shows the rule we hold ourselves to: its page had been written for a day already, and it was not offered, because the browser had no dictionary yet and promising a language the product is silent in is worse than not offering it at all. The other half of this is sound. The first thing the page does is play a forty-second track, and on ten of those languages it played the ENGLISH recording, because a track is recorded, not written, so the dictionaries ran ahead of the voices. Every language now has its own: thirteen are studio recordings, and ten are synthesised with the voices the operating system ships, which are drier than a recorded voice but are at least the language the page is written in. Those ten get re-recorded and replaced. The dictionaries themselves were machine-built and then edited by a second pass that reads them as speech rather than as text, and it earns its keep: in Danish alone it found the interface calling a tab two different words, which nobody sees and everybody hears.
The browser walks you through itself, one area at a time
A browser built for screen reader users cannot be learned from a manual nobody will find, so Legato now explains itself from the inside: it dims the window, lifts one control out of the dark and says what that control does and when you would reach for it. It is not a five-slide welcome, it is 121 steps in 16 chapters, covering every button on the strip, every section of the side column, every item in the menu and every single setting, including all fifteen page fixes and all twelve sound cues. Any chapter can be skipped in one press. The point of that length is a person arriving with a problem rather than with curiosity: somewhere in there is the switch that solves it, and until now the only way to find it was to open settings and read tumblers. Three things had to be true for it to be worth shipping. It speaks to the reader first: each step is announced through a live region while focus stays on the Next button, because a reader will not re-read a button it is already sitting on, and control lives on Tab and Enter, which work in every reading mode, while arrows and Escape are extras. It shows rather than tells: the repair chapter opens a deliberately broken page of our own, and to make the before honest it switches auto-repair off for those steps and forgets what it had already learned about that page, then repairs it in front of you and puts your settings back, including if you leave halfway. And it never launches itself: after installation it asks once, with "not now" standing as an equal answer, and after that it stays where you can always find it: F1, the Accessibility menu, and a button at the top of settings. Honest caveats: the tour speaks Russian only for now, and it has been proven step by step on a live window but not yet heard end to end with VoiceOver and NVDA. That listening happens before release.
A written reference for the browser, for the half of the decision the landing cannot carry
The Legato page is a paced, audio-first argument for why an assistive browser exists at all. It is the wrong shape for the other question people ask before installing a second browser: "does it do the specific thing I need, and what does Chrome do there instead?" That now has its own page at /legato/docs/, in the same form as the Assist and QA Copilot references: a long, plain document, with shortcuts written out as text rather than shown as key-cap icons, because an icon is silence to a reader. Nothing on it describes something the browser does not already do.
The agent reached for a second browser on the first unfamiliar field
We watched someone install the bridge and, at the first date picker they had not met before, their coding agent proposed wiring up a separate browser driver. Nothing was broken: the bridge drives that widget, has done for weeks, and it is written down. The problem is where it was written. An MCP server hands its manual over once, at connection time, cold, before there is a page, and what an agent does under pressure is what it can still recall. So the manual now installs itself. The first time the bridge runs in a project it writes the full guide next to the code and a short block into the file the agent reads at the start of every session, saying plainly that this browser, the real one, with the real logins, is the first tool for anything that happens in a browser, and that handing the wheel to another driver means opening an empty browser where none of those logins exist. It only writes where a project actually is, never twice, never outside its own markers, and one environment variable switches it off. The other half is that every refusal now carries its own way out: a control that will not take a value answers with the ladder to climb, and a gate that needs a human answers with which switch to flip, in the same reply as the no. And because a capability nobody names does not exist, the product page now lists what the agent can actually do: fill a whole wizard step in one call, sign in through Microsoft or Google, run several logins side by side, upload real files, read the boxes in pixels and the design token behind a colour, next to the two things it honestly cannot: take a screenshot, and run arbitrary JavaScript.
Enter confirmed a deletion while you were standing on Cancel
Every “are you sure?” in the studio comes from one shared dialog, so everything below was true everywhere it appears, including the audit panel of Access, the product we sell accessibility with. The dialog listened for Enter globally, which reads as a convenience until you arrive by keyboard: you Tab to Cancel, you press Enter on it, and the thing you came to rescue is deleted. Enter still means yes, but it is the confirm button that answers it, and focus starts there, so the key can no longer be pressed while aiming at the refusal. Three more things were wrong in the same twenty lines. The dialog had no name, and a dialog without one is announced as “dialog” and then silence: you hear that something opened, not what it is asking. Tab walked out of the modal onto the live page underneath, where every control was still reachable while supposedly blocked. And after you answered, focus went back to the top of the page instead of the button you asked from, which for a screen reader means finding your place again in a list that has just changed. Focus is handed back before the promise resolves, because the code that asked usually redraws the list immediately after, and a moment later there is nothing left to return to.
While the field was empty, the submit button did not exist for the keyboard
A defect we found on the Legato page turned out to be systemic: five forms had it, including the “follow the build” box that sits in the footer of every page we run. Each one turned the browser’s own validation off and disabled the button until the value matched our pattern. Either alone is defensible; together they make a dead end that only a keyboard shows. The form says nothing about what is wrong, because we switched off the part that would have said it, and a disabled button is not merely greyed out, it is removed from the tab order entirely. So you reach the field, press Tab, and land past the form, having never been told what it wanted. To the eye there is no defect at all: the button is right there, just pale. The browser now names the empty or malformed field itself, in the language of the operating system, which is more correct than any string of ours and needs no translating into fourteen languages. The button dims only while something is actually being sent.
Windows high contrast mode, where shapes held by a shadow have nothing to hold them
High contrast on Windows is not a theme, it is a takeover: the system strips the page of every colour it chose for itself and hands back the palette the person picked, and along the way it drops box-shadows and background gradients. That is the right behaviour, and it is also exactly the mode a large part of our audience works in every day. Half our surfaces were shaped by fill and shadow rather than by a line, so a card, a button and an input became text floating on nothing, with no edge to say where one ended and the next began. Wherever shape was carried by a fill or a shadow, there is now a border in the current colour. A selected state is told apart by the thickness of that border rather than by its colour, because in this mode our colours do not apply and arguing with the user’s would break the very thing they turned the mode on for. Focus uses the system Highlight, which they configured themselves. Honest caveat: this is measured, not yet seen, because we have the geometry and the computed styles, we do not have a picture. It gets looked at on a real Windows machine with NVDA before we call it finished.
The lamp on the start screen was quietly tinted, and a tinted lens is a dim lens
On a light background a beam of light cannot be drawn in white, since white on white is nothing, so the warm core of ours is mixed from the browser’s own colour, about two parts in five. That correction belongs to the beam. It was also being applied to the glass of the lens and to the hot spot right above it, which are not light but its source, and a source must not take the colour of what it emits. On the light theme the lens went a washed-out peach and the mark on the start screen visibly dulled next to its own colour swatch in settings, where the lens is left alone. The lens is plain warm white again, the same recipe the app icon, the settings swatches and the mark on this site have always used, and the start screen was the only place that had drifted. The dark theme never had the problem and does not change. The body of the lamp was drifting too: it was built from two mixes, the tint with white and then with black, and on a light theme it faded away from the tint until the mark read as pale plastic beside the very swatches naming its colour. It now stands in the pure colour with a single highlight: white along the top edge, shade along the bottom, and the coloured haze that used to sit around the lamp is gone. Shape comes from the light; a third layer between them was doing nothing but muddying it.
On the light theme the lamp was invisible, because it sat underneath its own light
Legato’s mark is a lamp with a beam, and the lamp was drawn first, with the beam laid over it. On the dark theme that costs nothing: the light right at the lamp is almost the same cream as the lamp itself, so covering one with the other changes no colour anyone can see. On the light theme it erased the lamp completely. The beam near its mouth is close to opaque, so only about a fifth of the difference between the lamp and what is behind it came through, and on a pale tile that difference is already nearly nothing. A fifth of nothing is nothing, which is exactly what you saw: a dark collar, and beneath it straight into the beam, with no source anywhere. The lamp is now drawn last, and what keeps it recessed in its collar is a clip along the collar’s lower edge instead of the collar physically covering it: the same pixels, a different order. Two things went with it. The tile’s light was inside out on the light theme: the tint sat in the middle of it, and a tint is darker than paper, so the tile had a dull patch in the centre and clean white corners, which is the opposite of a lit surface. The middle is white now and the tint has moved to a faint wash at the edges. And the warm core of the beam left flat cream for amber mixed from the tint itself, because white light cannot be drawn on white. Every surface that draws the mark was changed together: start screen, welcome, search, the tab favicon, the colour swatches, the mark on this site and the window mock-up in the showcase, and every generated image was rebuilt from the same source: the app icon, the macOS and Windows icon files, the favicons, and all twenty-four tints in both themes.
Signing in became ordinary, which is the whole compliment
Resetting a password used to happen without the screen changing: you pressed “forgot your password?”, the form stayed exactly as it was, and a line of small print appeared somewhere below it. Nothing told you an email had been sent, or where, so the honest reaction was to press it again, and again. It is two proper steps now. First, where to send it. Then a screen that names the address the link went to, says which folder to check and who it comes from, and offers to send another one after a minute rather than instantly, because five presses in ten seconds is five emails and then a refusal you would read as a fault. What the server answers has not changed: identical for an address we know and one we do not, so nobody can use this door to find out who our partners are. Passwords now explain themselves while you type them, instead of a single “at least 8 characters” that tells you nothing about what is wrong. The list turns green as you go: length matters most, a digit and a symbol are required while the password is short, and from sixteen characters a plain phrase counts on its own, because forcing character classes is what pushes people to Password1!, which is weaker than four ordinary words. Your own name and your own email are refused, which is the password that looks strongest to the person choosing it and falls first. Under the hood, four things that were quietly wrong: attempts were counted per network address, which protects us and not you, because a pool of addresses is something you buy, while the person being attacked has one email, so the count now follows the account itself; reset emails got their own, much stricter limit, since flooding someone else’s inbox cost an attacker nothing; the cost of hashing a password went from a hundred thousand rounds to three hundred and ten thousand, written into the salt itself so older records still open and are silently re-hashed on the next successful sign-in; and an address that does not exist now takes exactly as long to refuse as one that does, because a third of a second of difference was telling anyone who asked whether an account was there. Last, there is one door instead of two: the Earn page had its own copy of the sign-in form, which would have known about none of this.
The support chat was unreachable by keyboard, on the pages about accessibility, of all places
The chat bubble sits in the bottom corner of every page we run, and its panel was hidden the way most of the web hides things: transparent and untouchable by the mouse. To an eye it was gone; to the Tab key and to a screen reader it was still there, in full, all the time. So a keyboard user walking down the page fell into a dialog they could not see, and the panel’s focus trap, which is the right thing to have in an OPEN dialog, then held them inside it. The bubble itself comes right after the panel in the page, which means it could never be reached at all. Closed now means closed: the panel leaves the tab order and the accessibility tree together, and the trap only arms while it is open. The bubble announces whether it is collapsed or expanded instead of being a nameless button, and the whole widget is a landmark, so a screen reader can jump straight to it by region rather than tabbing to the end of the page. Two more things went with it. The chat now exists on three pages that had none: Legato, Access and Check, the first two being exactly where someone reading by ear is most likely to arrive with a question. And WhatsApp and Telegram, which until today only the hub offered, are now in the menu on every page: on a page about screen readers, a live human is a better answer than a form.
Accounts stopped working today, and the form could not say why
The service that holds licences and partner accounts moved to an address of our own, api.qiksy.app, so that the string baked into an installed copy of Legato stays valid for as long as that copy lives, because a blind person updates an app reluctantly, and an address tied to a worker name would die the day we renamed anything. The move was right; what we missed is that every account-shaped thing on the site still called the old address, which stopped answering. A JSON request is preflighted, and the refusal came back without the headers a preflight needs, so the browser killed each call before it left the machine. The only thing a form can say at that point is “network error”, indistinguishable from your own connection being down. Registration, log-in, changing a password and the reset mail all went at once, and the role check went with them: the studio asked who you were, got nothing, and drew the rail for a guest, so a signed-in owner lost their own tools. Every shipped surface now points at the new address, including the site’s own content security policy, because a line missed there would have produced the identical “network error”, from the policy instead of the network. Failures also name themselves now: under the sentence you read there is a line you can forward us, with the host, the HTTP status and the server’s own code. And an unreachable server no longer decides who you are, because “I don’t know” and “not the owner” are different answers, and only the second one is allowed to take anything away. Two smaller things went with it: “forgot your password” no longer claims to have sent a mail it did not send, and the reset page ends where it should, with a button back into Qiksy instead of a sentence asking you to type the address yourself.
The mark stopped being a sticker on the page
Legato’s mark sits on a tile, and that tile had a colour of its own: graphite in both themes at first, then warm paper on the light one. Either way it disagreed with the window behind it, because the browser has four backgrounds (two themes × two styles) and a tile with one fixed colour can only match one of them. On the light theme the effect was plain: a cream square in the middle of a cool grey page, reading as something stuck on rather than part of the product. The tile now takes the window’s own background, tint wash and all, and what gives it shape is light instead of colour: a small radial of the current tint, brightest in the middle and gone by the edges. Same recipe everywhere the mark is drawn: start screen, welcome, search, the tab favicon, the twenty-four colour swatches in settings, the mark on this site, the window mock-up in the showcase, the app icon and the OS favicons, all rebuilt in both themes. The swatches keep a stronger wash, since on a shared background the colour is the only thing telling them apart. The lamp itself is a third thicker and pushed further out of its collar, because the sliver of light read as a reflection rather than as the source.
The spotlight now has something to light up
Legato’s mark is a spotlight, and until today its beam fell on nothing. Now the tile is covered in a field of small line drawings: a home, an envelope, a globe, a padlock, a printer, forty-two of them, and the light is what makes them readable: outside the beam they sit at four per cent and register as texture, inside it they come up to a third and can be told apart one by one. It is the product’s own claim rendered as a logo: the page is already there, the light is what makes it legible. Three things had to be solved to get it. The drawings are a raster set, so each one is cut out, thresholded and thinned to a hair individually, because a single threshold across the sheet broke the strokes into dashes wherever the pen had pressed lighter. They are laid on a grid whose index is (row × 11 + column × 13) mod 42, which is why no drawing ever repeats along a row or a column: 11 and 13 are both coprime with 42, so it is arithmetic rather than luck. And the small sizes needed different geometry, not different opacity: at a ten-unit cell a drawing is ten pixels on a 96-pixel tile and turns to mush, so anything under 256 gets a coarser field with a thicker line, and at 32 pixels and below the drawings are dropped entirely. The light theme needed its own everything: white lines do not exist on cream, so the same image is re-inked by matrix, at its own opacities, over a plate that now sits on warm paper rather than white, because a white tile beside the browser’s warm background read as a sticker rather than part of the page.
A day on one beam of light, because the mark was drawn in six places and only two of them agreed
Legato’s mark is a spotlight, and the light is supposed to run off the edge of the tile it sits on, because a lamp whose beam dies in the middle of its own frame reads as an object, not as light. It did die, everywhere: the cone was already extended past the tile, but its opacity faded to zero at the end, so at the depth of the tile’s bottom-left corner, 107 of 120, because the mark is tilted twenty degrees, about five per cent of it was left. Technically the light arrived; to an eye it did not. The tail now holds twenty-six per cent and the tile’s edge is what cuts the beam, which is the only thing that reads as “it carries on past the frame”. The other half of the day went on finding that the mark is drawn by hand in six separate places: the app icon, the colour swatches in settings, the start screen, the tab favicon, the search header, the site, and that fixing the icon fixes exactly one of them. All six now share one rule: where the mark sits in a tile, the light runs to the corner; where it stands free, on a bare PNG with no edge to cut it, the light still fades to nothing, because there a beam that has not faded gets a straight razor cut along the edge of the image instead. Twenty-four tints rebuilt in both themes, plus the Windows icon and the favicons.
The page for Legato is up, the browser itself is not, and the buttons say so
Legato is a browser that repairs broken pages on your own computer so VoiceOver, NVDA or JAWS can read any site properly, and it now has a page. It opens by playing, not by explaining: a recorded human voice greets you in your own language, thirteen of them recorded so far, fourteen written, every word by hand and none machine-translated, because a page about screen readers that has to be read before it can be understood has already lost the argument. Both platforms are named on it, Windows first because that is where 86% of screen reader users are, and both buttons are marked “soon” and lead to a notify field rather than a download: there is no installer yet, and promising one to somebody who reached the button by ear would be the worst thing this page could do. We also pointed an audit at the page before shipping it, which for this product is not optional. It came back with three violations and seven defects, all now fixed: the colour swatches you use to pick the browser’s tint were eleven pixels across at 400% zoom against a twenty-four pixel minimum, the “I am paying for someone else” link was told apart from the text around it by colour alone at a contrast of 1.27 to 1 where three is the floor, the transcript toggle under the audio was twenty-one pixels tall, two nested regions announced themselves under the same name, and the sound controls sat outside every landmark on the page, so a reader navigating by region simply lost them. The layout holds from 320 pixels to 1920 without sideways scrolling, 320 being what a 1280 laptop becomes at 400% zoom, the size our own readers actually use.
We ran our own accessibility audit on ourselves, and published it
Before selling an accessibility audit it seemed fair to survive one. We pointed the same engine our free scan uses at our own production site and it returned twenty findings across six causes. The serious one: with the product rail folded, all thirteen of its buttons announced themselves as “button” and nothing else, because the label was hidden with a rule that removes text from the screen reader as well as the screen, so the studio could not be navigated by voice in that state. The rest were the kind of thing no eye catches: a step number failing the contrast minimum by three hundredths, the “AI” chip on the product cards dimmed for looks below what anyone with reduced contrast sensitivity can read, a footer tagline at 2.92 to 1, and a footer link that was both too small to hit and partly covered by our own chat bubble, so a click at the top of it opened the chat. All twenty are fixed, five CSS rules and one line of config, and the pages now come back clean in both rail states. The report is published as it stands, findings and fixes side by side, as the first entry in the sample gallery on the Access page: an audit shop that has never audited itself is asking you to go first.
Pages stopped jumping while they load
Every page in the studio used to shift as it finished loading, with the whole body sliding eight pixels up and to the left the moment the stylesheet landed. Our own analytics scored it at 1.0 on the products catalogue, which is about as bad as that measurement goes. The cause was mundane: the rule that removes the browser’s default page margin lived in a stylesheet the browser waits for, so the first frame was drawn without it. It is now declared in the page itself, in force before anything is painted. Qiksy Offer had a second version of the same problem: the jobs view was revealed as an empty desk and then grew to full height under you, and it now waits for its first real content instead. The footer links also grew to a proper 24-pixel target while we were auditing ourselves against WCAG 2.2, which we should have done before shipping an accessibility product.
The language switch follows where you actually are
The header used to offer the same second language to everyone on earth, whether or not anyone there speaks it. Now it follows the country: English on its own in most of the world, with no switch to ignore; English and Ukrainian in Ukraine; English and Russian in the countries where Russian is the working language. Nothing became unreachable: every language still has its own URL, the search engines still index all three, and if your browser is set to Russian or Ukrainian you are offered it wherever you happen to be. Developers see all three on localhost, which is the only way to actually check the copy.
The partner rates are grouped by what you can sell today
The products-and-rates list was flat, which read as “eleven products, all equally ready” and sent new partners into their first conversation with the hardest one. It is now grouped by how each product is actually sold: what a client can start self-serve in minutes with your link crediting you automatically, what is closed in a conversation with the studio delivering, what is live but needs something true on the client’s side first, and, last and earning nothing, the free tools you use to find clients in the first place. The rates themselves are unchanged.
Hear your own page read out loud
The free page check now lets you press play on the transcript: your browser’s own voice reads the page the way a screen reader announces it, in the page’s declared language, highlighting each line as it speaks. Hearing “link. no name. link. no name.” about your own site lands differently than reading it in a table. Nothing is uploaded, because the voice is the one already in your browser. The report grew a few other things while we were in there: the search result is drawn next to the chat card, with the real truncation both apply; merit badges are counted out of ten, so the ones you have not earned name themselves; the end credits list the stack the page admits to, set like film credits; and the whole report now downloads as a Markdown file or prints to PDF, which is the shape it needs to be in when you hand it to whoever owns the site. Two new numbers: how many minutes the page is out loud, and how long its HTML alone takes on a slow 3G connection.
The sample reports are now shown whole: scroll the actual deliverable
The gallery on the Access landing used to show a screenshot of each sample report’s first screen, which quietly sold a verdict line, two fix-map tables and a findings register with evidence as one thin picture. The frame now holds the report document itself, scrollable in place, with a small table of contents above it naming what you are about to scroll through. The five fictional verticals and the honest “sample, not a track record” stamp are unchanged.
The theme switches on Access and Check actually switch again
On the Access and Check landings the light/dark toggle saved your choice and then changed nothing on screen, because the button wrote the preference in one spelling while the stylesheets listened for another. The classic design style had the opposite problem: it technically applied, but these two pages never carried the classic skin, so flipping the switch barely changed a thing. Both are fixed: the toggle repaints the page it is on, and classic now means what it means everywhere else in the studio: warm paper in light, soft charcoal in dark, flat corners, the quieter accent. First-time visitors also land in the modern style now, as everywhere else, instead of being seated in classic by mistake.
One tab icon for every page, and it stopped vanishing on light tabs
Every page of the studio now wears the same Q-and-bolt mark in the browser tab. Until today each product carried its own: a teal plane on Route, Assist’s own mark, and on several pages a white transparent glyph that simply disappeared against a light tab bar. The mark is now an SVG that listens to the browser theme: ink-black ring on a light tab strip, white on a dark one, the gold bolt in both, so it stays readable wherever the tab is drawn. Safari does not render SVG favicons and keeps the dark badge instead.
The audit agent chat grew into a workspace
The agent tab in the Access workbench now behaves like a real place to work, not a strip under the KPIs: the chat takes the full height of the window (the audit header scrolls away and comes back), only the log scrolls while the composer stays put, the field grows with your text, and you can dictate the task by voice, with the same one microphone the rest of the studio uses. Agent replies turn every WCAG criterion they cite into a link to its W3C Understanding page. And a run no longer dies with its tab: a panel that reopens picks up the running job, and a finished run’s findings are imported even if nobody was watching when it ended.
A country is no longer bought, it is won
The entry fee for a country partnership is gone everywhere. It filtered for capital rather than for hunger, and it made the arrangement look like something it is not. Partnering starts the way it always should have: register as an Earn partner today, get your link and dashboard immediately, 50% recurring on subscriptions, with no application, no waiting, nothing to pay. The lead seat for a country now goes to whoever reaches five paying clients or $1,500 in attributed revenue within ninety days. Several people may run at that at once, and the dashboard is the referee rather than a conversation with us: real clients are the whole interview. Only after the sprint is there an agreement to sign, with exclusive territory and distributor terms.
Headers that give something up instead of breaking in half
On a narrower laptop the top bar of our product pages could quietly fold onto a second row, with the button you were meant to press ending up underneath the links, the page pushed down behind it. Every one of our headers now sheds what it can spare instead: the section links first, then the way back to the studio, then the design-style switch, and only on the smallest phones does the main button trade its words for its arrow. It keeps its name for screen readers when it does. The widths at which each of those happens were measured against the real labels in all three languages rather than estimated, since Russian and Ukrainian run about a fifth wider than English, which is why the bars that broke, broke there first and on screens where the English page looked perfectly fine.
One product mark in every header, and controls that stopped fidgeting
The small square that names the product you are in was built seven times under three different names across the studio, so it reacted to the classic style on some pages and not on others, and inside the panels it lost its border entirely. It is one pattern now, driven by shared tokens: every header, every app, both styles. In Qiksy Offer the industry switch no longer changes size when you flip between markets: active and inactive were two differently-built boxes, and the header shifted with them. And Qiksy Deal’s search button stopped pretending: while something is still missing it dims, and pressing it marks the exact field that needs an answer instead of doing nothing.
Qiksy Access · an accessibility audit of the pages your customers actually buy on
A new service with a document as the deliverable: a WCAG 2.1 AA audit of a live store or app, including checkout and account pages behind login, which free scanners never reach, with nothing installed on the site and no overlay script. The report does not hand your developer four hundred rows; it traces every finding to the component and the design token it comes from, so fixing a handful of sources closes hundreds of findings at once. Fixed prices are on the page, and so are the limits: what an automated pass can and cannot see is stated before you ask, because roughly a third of real accessibility failures need human judgement and ours are marked as such. The audit workbench itself, with the 42-state checklist, the findings register and the live fix map, is in the studio sidebar, and the free one-page Check remains the doorway: check one page for free, audit the whole store when it matters.
Selling history stopped being sending history, and the panel stopped asking everything at once
A list of letters you sent is not a record of selling: it cannot tell you which pitch and which product bring answers and which go nowhere. A candidate now moves past “sent” to “they replied” and “they bought”, one button at a time, and the board filters by those steps like any other. The panel around it was cut back to one question at a time: what you sell, who you are looking for, how many, search, with the whole console one click away when you want every setting at once. Which channels to search and how deep to dig live in settings, where they are actually remembered; on the panel they were switches that forgot what you told them after a reload. Past searches fold into their own block that always shows the last three, and the cards on the board read top to bottom again: logo, name, what the company does on its own line, what you are selling them underneath.
Searching twice now finds new ones, instead of paying again for the same list
Both hunters had the same blind spot: run the same brief a second time and the agent ran the same queries against the same web, so most of what came back was what you already had. Qiksy Deal now tells the agent which companies are already on your board and, more importantly, that skipping one does not use up a slot, so the places freed up get filled with new names rather than quietly shrinking the list. It also has a floor on effort before it may claim a niche is finished: several genuinely different searches: other towns, the local wording, the local language, smaller catalogues, and it reports which queries it actually ran, so “there is nobody left” can be told apart from “it did not look”. And when a niche really is worked through, pressing search again says so before the run starts instead of after twenty minutes of waiting; you can still run it anyway, and the note clears itself after a week, because new businesses appear. Qiksy Offer gained the same warning for a role whose market is exhausted, as it used to spend two full sweeps rediscovering that, and it drops the warning the moment you change the keywords, the regions or how fresh a posting has to be, because that is a different question.
Qiksy Check · see one page the way everyone who is not you sees it
A new free tool, and the only one here that asks nothing of you: no account, no key, nothing to install. Paste an address and it reports what a screen reader can and cannot use, what a search engine and a link preview make of the page, and how it is served: twenty-six checks, each with the reason it matters instead of a rule number. It also shows what a score cannot: the page read OUT LOUD in the order it is announced, with everything that has no name marked; the exact card the link turns into in Slack, LinkedIn or Telegram; the outline people actually navigate by; and every other company the page loads something from, with the recognisable trackers named. The audit runs in your own browser: we fetch the page’s HTML and nothing else, and keep none of it. It is honest about its limits too: colour contrast, JavaScript errors and failed requests need the page to actually run, and that is what QA Copilot is for.
Work Finder is now Qiksy Offer, and the road from “add me” to a running search stopped having holes in it
The name says what you are actually after. Nobody wants a list of vacancies; people want an offer, and that is the thing the tool works towards, from your résumé to the letter that goes out. Same tool, same data, nothing to migrate, and the address you have bookmarked still works. Behind the name, a full pass over the newcomer’s path fixed the places where the product knew something and did not act on it. A candidate dictated in one market no longer lands in another and disappears; roles now attach to the person rather than to whichever board was on screen. What you said out loud arrives already ticked: the country you live in, the city, a language level, whether your diploma is recognised, instead of being asked again two screens later. Nothing blocks a search silently any more: a run that finds nothing says so and stays in the history, a role that fails says why, counts stop including dead links the engine itself struck out, and the local engine dying mid-run is now visible within seconds instead of leaving a stopwatch running for hours. Where an answer really is missing, the card takes you to that field and holds an amber mark on it until you get there.
Creating a candidate stops guessing at the country, at the limit, and at the city you said out loud
Four things went wrong on the way to a first candidate, and all four are fixed. The target country was a free-text box, so a typo quietly narrowed the search to nothing; it is a list now. A profile that was saved without everything the search needs used to vanish from the column. It stays there now, marked, and pressing it opens the very fields that are missing instead of a general "something is incomplete". Everything that blocks a search now sends you to the candidate’s own card, never back into the résumé builder you just left, with the missing answers lit up in amber, the address field among them, opened and focused so you can type it where you are standing. That holds when the refusal comes from the engine rather than the panel, too: it used to be a dead end with a message in the wrong language. And a city you mentioned while dictating your story, as in "I want to work in Berlin", now reaches the search: it used to be heard and dropped, which is how a Berlin request came back with Switzerland.
You can follow the build by email now, from Qiksy Offer and Assist too
We are building Qiksy in the open, and until now the only way to hear about it was to happen to come back. The short "follow the build" box, one field and no account, was on the catalog, QA Copilot, Business and this changelog; it is now also at the bottom of the Qiksy Offer and Assist pages, in all three languages. One list, not one per page, and it exists to send a note when something actually ships.
The renewal reminder closes now, including the one that says your term has ended
Nothing here renews by itself, so the studio speaks up a week, three days and a day before a licence runs out, and once more after it has. The “ends soon” bars could be dismissed; the “your Pro has ended” bar could not, and a notice you are unable to close stops being information. Every one of them now has a × on the right, and closing it is remembered through reloads. It comes back only when the news actually changes, so dismissing the week-ahead warning no longer silences the day-before one, which is what used to happen, and renewing starts the count over. Close the “ended” bar and it is gone for good; the quiet mark next to the tool in the sidebar still says where you stand.
Dictation works on the site again: we were blocking our own microphone
Speaking your story into the profile builder failed on qiksy.app with “the microphone is blocked”, and it failed for people who had never blocked anything: one of the site’s own security headers switched the microphone off for every page here, so the browser refused before it could even ask you. That header now allows the microphone on our own pages, and nothing else gained access; the camera stays off, as it was. If you do deny the mic yourself, the message points at the address bar, which is where the switch actually is.
Picking a market no longer blurs the form you are filling in
Switching between IT and healthcare on the “create your profile” screen dimmed the whole card and put a spinner over it, a wait staged for a board full of finds, on a screen that has none, with the spinner sitting off the card’s centre. The choice now lands immediately. The two markets also carry their own colour everywhere they show up, blue for IT and green for healthcare, so which one you are filling the form in is readable without reading. Inside the tool, where switching really does swap a full board, the soft blur stays.
Two markets, two boards, so a nurse can no longer show up in a developer’s list
Qiksy Offer hunts in two markets, IT and healthcare, and the industry used to be just a label on the candidate: every part of the panel had to filter out the other market by itself, and one of them never did: the “add a candidate” picker offered a care worker in the middle of a full-stack search. Each market now has its own space in the database on your machine: candidates, roles, finds, leads and search history are kept apart, so there is nothing left to leak. Switching markets loads its own board behind a soft blur instead of flashing an empty screen, and the search settings you tune, from freshness to channels to how many results per sweep, stay with the market you set them in. Your existing data is split automatically on the first run, with a copy of the old file kept beside it.
Telling us about a project is a form now, not a draft email
Every "start a project" and "book an audit" button opened your mail client with a half-written letter in it, and on a machine with no mail client set up, it did nothing visible at all. They now open a short form: a couple of lines, a way to reach you, and a file if you have one. The estimate the calculator builds rides along as a real PDF attachment instead of landing in your downloads folder, and the message goes straight to the people who answer it.
MultiLogin Tabs has a privacy policy you can actually open
The policy linked from the store listing pointed at a page that had gone missing, and a privacy policy nobody can read is not a privacy policy. MultiLogin now has its own at qiksy.app/multilogin/privacy/, written for THIS extension instead of borrowed from another one: exactly what it touches (cookies, localStorage, IndexedDB and Cache Storage, isolated per tab), where that stays (your browser, and nowhere else), and what each permission is really for. It also says the limit out loud: this is a best-effort container built from header rewriting and JavaScript virtualization, not a true browser container.
Every page can now reach a person, not just five of them
The chat bubble lived on the hub, Business, the catalog and two product pages, so a question that came up on Pay, Forms, MultiLogin, the partner program, the radar or the pricing page had nowhere to go. It is on all of them now, and it is the same Qiksy Assist we sell: the message lands in a Telegram chat and the reply comes back into the widget. The three working tools, Qiksy Offer, Qiksy Deal and Route, are deliberately left alone: they are what you already paid for, not a place to be sold to.
A long prompt in the message box no longer looks broken
When the assistant asked something wordy, the hint inside the empty message box wrapped onto a second line and put a scrollbar into a field nobody had typed in yet. It now cuts off with an ellipsis instead, and the moment you start writing, the box wraps and grows exactly as before.
Pages stopped throwing you back to the top while you read
Scrolling a page inside the studio would snap back to the very top every screen or so, which made anything below the first section effectively unreadable. The page was not scrolling itself: the studio frame around it was being rebuilt from scratch as you crossed each section, and a freshly built frame starts at the top. It is now updated instead of rebuilt, so the scroll position, and everything else the page was holding, survives. Checked on every landing in the studio.
Care work is free now, because the people who need the search most were the ones locked out
Healthcare and care used to be a paid industry: on the free plan only IT worked. That protected the wrong side. Germany’s own labour figures say the qualified nursing layer is short of PEOPLE, at 57 unemployed per 100 vacancies, while the layer without a recognised diploma is the crowded one, at 2 131 per 100. The person for whom finding a posting is genuinely hard was the only person we would not let in. Free now covers one candidate in care exactly as in IT: local job titles, region by region, language level and diploma recognition read off every posting. What is paid stays paid: several people at once, and the agent working while you are away.
Team: the more seats, the cheaper each one
Seats were a flat $99 a year, which meant an agency working with two hundred people saw a five-figure number and stopped reading. A seat is also less than it sounds: it is a concurrent slot, freed the moment someone is placed and removed, so a handful of seats carries a much bigger yearly flow. Now the price steps down with volume: $69 a seat from ten, $49 from twenty-five, $35 from fifty, on one rule: a year of the licence must cost less than a single placement, at any size. And nobody pays more for less: a ladder like that would otherwise make twenty-four seats cost more than twenty-five, so when the next step is cheaper in total you simply get that step: more seats, less money.
A candidate may list every job title they actually do, on the free plan too
One person is often three postings: a care worker is advertised as “Pflegehelfer”, “Betreuungskraft” and “Alltagsbegleiter”, and a developer answers to two or three titles as well. Roles stopped being something you pay for, and every plan now carries the same generous cap, because a board built on a single title is too thin to show what the tool does. What you pay for is automation (auto-apply, leads, scheduled monitoring) and the number of people you are hunting for. Engine 1.7.2 on npm.
Engine 1.7.1 · a mistyped licence key now says so
A key with a typo, a stray space or a missing character used to report “could not verify, check your connection”, sending people to fix their wi-fi instead of re-reading the key. The engine now tells the two apart: a key we reject is a key problem, and only a real network failure is reported as one. `npx qiksy` picks it up on the next run.
A walkthrough that builds a profile in front of you
First run now starts with one question, IT or healthcare, and then offers to show youthe tool working, on invented data, before you type anything of your own. The walkthrough drives the real screen: it opens the résumé builder, tells its story into the field, watches Claude assemble the profile and name what is missing, then hunts, opens a find and sends the application. Say no and it waits behind a bar at the top; the compass in the header replays it any time.
The first frame no longer says your board is empty
Reloading with candidates in place used to flash “create your profile” for a moment before the data arrived, because the app could not tell “nothing here” from “nothing yet”. It now remembers that a board exists and shows placeholders until the engine answers. The browser-status pill stopped flashing red for the same reason: not asked yet is not the same as disconnected.
Describe a candidate in one sentence, and the card asks for the rest
Type or dictate one sentence and the candidate card fills itself in: profession from the catalogue, country, region, language level. Whatever is still missing becomes a question with the answers ready, instead of a list of complaints you have no way to act on.
Engine 1.7.0 on npm
`npx qiksy` now carries industries, regions and the whole care vertical, so a local install gets them without waiting for anything else.
Healthcare and care work, searched the way that market actually works
A second industry alongside IT: vacancies are searched by the profession’s LOCAL name in the country you picked, region by region, and scored on the things that decide a care job: the language level the posting demands, whether a diploma has to be recognised before you may start, housing and visa support.
Search by region, not just by country
An offline job is an address. Countries now open into their own administrative divisions, from states and oblasts to federal states and voivodeships, with the word each country actually uses, so a search for Bavaria stops meaning “somewhere in Germany”.
Move your data to another machine without a cloud in between
Candidates, résumés and finds export to a file and import on the next machine. Nothing passes through us on the way, because the tool is local, and moving it should not be the one moment it stops being local.
The landing shows the real panel, and a walkthrough runs the whole job
The page you land on now shows the actual working board instead of a drawing of one, and the guided walkthrough goes end to end, from candidate to search to finds to letter, rather thanstopping halfway.
Qiksy Forms · announced, in development
A tool that opens an official form and fills it in while you answer out loud, on your own Claude, on your own machine. It is being built, not sold yet: the page says so plainly and takes an email for the day it works.
Follow the build · one email, no algorithm
Added a “follow the build” signup across the studio, so you can watch Qiksy grow from your own inbox instead of hoping a feed shows it to you. No spam, leave whenever.
A name, not a code
Qiksy Assist now asks a visitor’s name before the chat starts, and tells two people with the same name apart, so the person on the other end is a real conversation, not an anonymous ticket number.
Rebuilt as one live agent
Qiksy Offer became a single “live agent”: a search that narrates itself in real time, vacancy cards with a 0–100 match ring, and a calmer royal-blue look. It runs on your own machine, on your own Claude sign-in, and we hold no key.
Your tools, your key
Every AI tool now runs on your own Claude sign-in. No key to hand us, nothing billed through us, and your data never leaves your machine.
Two-way chat, live in production
Qiksy Assist went live: one script tag turns any website into a two-way chat that lands straight in your Telegram: you answer from your phone, the visitor sees it in the widget.
★5.0, and free forever
MultiLogin Tabs keeps every account in its own fully isolated tab: cookies, storage, the lot. ★5.0 from ~700 real users, free forever. Small, but real, and we’ll never quote a bigger number than the true one.
Keys that verify themselves
Stood up the licensing service so the local-first tools can unlock by key, verified against their own worker and kept deliberately separate from everything else.
Follow the build
We're building Qiksy in the open: new tools, real progress, the occasional stumble. Get the short note when something ships.