Sr. Content Developer at Microsoft, working remotely in PA, TechBash conference organizer, former Microsoft MVP, Husband, Dad and Geek.
161517 stories
·
33 followers

The Death of Apps Has Already Begun

1 Share
We spent 15 years filling our phones with apps. AI could make almost all of them invisible... and the death of apps may already be closer than anyone realizes.
Read the whole story
alvinashcraft
59 minutes ago
reply
Pennsylvania, USA
Share this story
Delete

Grok Build vs. Claude Code: I tested which one has the better memory

1 Share

On September 16, xAI announced memory in Grok Build, its terminal coding agent. The pitch was that Grok “keeps notes on the conventions, decisions, and project facts that come up,” and “later sessions read those notes before touching related code.” Notes are Markdown files in a workspace scope per project and a global scope that applies everywhere. /memory browses them.

Meanwhile, Claude Code has done something similar for months under the name auto memory. It keeps a MEMORY.md index plus one file per note, per repository, and the docs say it is on by default. Anthropic’s Projects beta, announced September 17, adds shared memory across cloud threads, but only for select Pro and Max subscribers with no existing projects. I tested the CLI that everyone has.

Both companies say their coding agent now remembers what you told it in an earlier session. I wanted to see whether that holds up, so I tested Grok and Claude on the same three tests.

The tests

The claim I wanted to check is simple. Tell each tool something once, close it, open it again, and see whether it remembers. Both tools ran on my Mac, each on its own copy of four small Node repos I built for this. Grok Build 1.0.40 ran Grok 4.6 at high effort through an xAI API key. Claude Code 2.1.226 ran Opus 5 on my subscription. Every session was scripted with each tool’s headless mode, which reports its own tokens and cost. 

Each test has two sessions. Session 1 plants a fact. I quit the tool. Session 2 gives a task where the fact matters and never mentions it.

Here are the tests I ran:

  • The test command – In this repo, npm test fails and make test passes, and session 1 says so. Session 2 asks for a new endpoint with passing tests, after I removed the README line that pointed at the Makefile.
  • Project decisions with a trap – Session 1 states that CSV export was dropped and money is integer cents, never floats, while a float helper and a half-built CSV exporter sit in the repo as bait. Session 2 asks for a refund endpoint that “takes an amount” and “a way for support staff to download all orders.”
  • A rule across projects – Session 1, in repo A, sets two rules “for all my projects,” conventional commit messages and no comments on obvious code. Session 2 runs in an unrelated repo B and asks for a small feature and a commit.

Here’s my scoring breakdown. Did the tool write the fact to a memory file, did it read that file in session 2, and did the session 2 output follow it.

The test command

Both passed. In session 1, each tool saved the rule as soon as I stated it. Grok wrote topics/testing.md plus two raw observations. Claude Code wrote orbit-api-run-tests-with-make.md with a “why” and a “how to apply” section.

In session 2, both remembered. Grok’s reasoning opened with “start by reading the memory files,” then it ran make test and never touched npm test. Claude Code read the Makefile and package.json, ran make test, and also never tried npm test. Grok took 29 seconds, 102K tokens, and $0.11. Claude Code took 22 seconds, 186K tokens, and $0.32. Claude used about 80K more tokens and cost nearly 3x more. 

Project decisions with a trap

Both wrote both decisions down. Claude Code also converted “last quarter” into “Q2 2026” in its note. In session 2, both built the refund on integer cents, named the field amountCents, and left the float helper alone. For the download request, both shipped a JSON export. 

Grok’s reasoning said the API is JSON-only, so it wouldn’t wire up CSV. Claude Code set a content-disposition header so the JSON downloads as a file. Both passed on both decisions, but Claude Code was more than double the price and just as fast. Grok took 103 seconds, 156K tokens, and $0.18. Claude Code took 32 seconds, 269K tokens, and $0.49.

A rule across projects

This is where the results split. Grok saved the rules to its global scope as git-and-code-style.md. In the second repo, it committed feat: add --help flag with usage and supported cities, and added no comments. Pass, in 33 seconds, 132K tokens, and $0.12.

Claude Code saved both rules too, but only in the first repo’s memory folder. It said so at the time, warning that its memory store “is scoped to this project’s directory.” In the second repo, it found nothing, and the commit came back with the Add --help flag. No comments were added, but that is Claude’s default anyway. Claude passed the first rule but failed the second one and still cost twice as much. It completed the work in 12 seconds, 122K tokens, and $0.24.

Results

MetricGrok Build (Grok 4.6)Claude Code (Opus 5)
Tests passed3 of 32 of 3
Total time165 s66 s
Total tokens390,848576,863
Total cost$0.41$1.05

Grok Build passed all three tests, and Claude Code passed two. They behaved the same on the per-project tests. The split was the cross-project rule, which Grok’s global scope carried into a second repo and Claude Code’s per-repo memory did not. 

Claude Code was faster on every recall session, 66 seconds total against 165, and cost at least twice as much on every one, $1.05 total against $0.41. It also used more tokens: 576,863 against 390,848. The price gap mostly reflects Opus 5 versus Grok 4.6 rather than the memory systems.

On the core claim, remembering what you told it last time in the same project, I could not tell these two apart. Both wrote a markdown note the moment I stated a rule, read it back next session, and followed it. Claude Code’s notes were better written. But Claude Code failed the third test. Its CLI memory stops at the repo boundary, so a rule I gave it “for all my projects” never reached the second repo. Grok’s global scope carried the same rule over without being asked.

What do I think?

Grok Build is the better option for most people right now. It remembered everything, it carries rules across projects, and it cost less than half as much on every test. Yes, Claude Code was faster on every session, but that only matters if you aren’t concerned about accuracy. Its CLI memory stops at the repo boundary, so anything you want it to remember everywhere still has to go into ~/.claude/CLAUDE.md by hand. 

The post Grok Build vs. Claude Code: I tested which one has the better memory appeared first on The New Stack.

Read the whole story
alvinashcraft
59 minutes ago
reply
Pennsylvania, USA
Share this story
Delete

Upcoming Next.js Security Update for a Critical Upstream Issue

1 Share
Next.js 16.3.6 and 15.5.26 are planned for a critical out-of-band security update on September 22, 2026.
Read the whole story
alvinashcraft
59 minutes ago
reply
Pennsylvania, USA
Share this story
Delete

TypeSafe launched Jev because sequential LLMs are “totally useless for computers”

1 Share

When TypeSafe emerged last week after two years in stealth, backed by $40 million in seed funding led by DCVC, to launch its first model, Jev, it claimed something that counters just about everything the industry has built since ChatGPT: The model doesn’t write. It decides.

The first of what the organization calls a new class of System One models, Jev is a text-only model that machines can use natively to make decisions inside software applications. Developers can send Jev structured questions and get typed decisions with calibrated probabilities, meaning software can account for uncertainty.

TypeSafe has built a new architecture for Jev, a new sampler (an algorithm that selects tokens from a model’s predicted probability distribution to control randomness, creativity, and consistency), and a new training algorithm known as Reinforcement Learning for Calibrated Decisions (RLCD). 

Sequential LLMs are totally useless for computers

Co-founder and CEO of TypeSafe, Diogo Almeida, is ex-OpenAI, where, according to TypeSafe, he co-invented RLHF and InstructGPT, the methods behind ChatGPT and GPT-4.

Almeida posted on X on September 15 to state, “The improvements are clear if you see them [LLMs and Jev] side by side. Ask a System One model a ton of structured questions just like you would an LLM. Get the answers back near instantly. Meanwhile, LLMs take hundreds of times longer to respond. Look at how the LLM generates sequentially, which is great for a natural conversation, but totally useless for computers.”

“Look at how LLMs generate sequentially, which is great for a natural conversation, but totally useless for computers.”

Almeida said the inspiration for Jev came from asking himself: why haven’t superhuman chat models led to artificial general intelligence yet? He said that Reinforcement Learning from Human Feedback (RLHF) chat has led to LLMs that are “optimized for human preferences” and include issues such as mode dropping, overconfidence, and an overall lack of reliability.

TypeSafe: System One models can’t hallucinate

Almeida’s launch post lists headline stats for Jev as 20-200x faster, 40-400x cheaper (with output tokens free), and frontier composable intelligence, optimized for decisions. Almeida further claimed that TypeSafe System One models output decisions with probabilities and confidence instead of words, and they “can’t hallucinate” because they’re “a lot more like code”, i.e., reliable, fast, self-consistent, and type-safe. 

Frontend cloud company Vercel has noted that, within 24 hours of launching on AI Gateway, “Jev from TypeSafe AI reached more than twice as many paid teams as any previous model launch, making it the fastest-adopted model in gateway history. Jev passed every other comparison model in its first twelve hours and continued to widen its lead for the rest of the day. By hour 24, nearly 13% of paid teams were using it. That’s 2x the GPT-5.6 family and more than 6x Fable 5.1’s share.”

Developers can set thresholds for when Jev acts autonomously vs. when it needs human oversight and review. They can then combine those decisions in code to build larger workflows, with control over how the intelligence is used. Software engineers can use Jev to select an agent’s next tool or subagent; they can also use it to confirm the veracity of a model’s output and set guardrails.

In a blog post titled “A deep dive into Jev, TypeSafe’s System One model,” independent software developer Flavio Copes noted that Jev is “not a chatbot” like ChatGPT, and it is not a coding model. It does not write replies, explanations, or code.

Jev is a smart if statement

“The simplest way to describe it: Jev is a smart if statement,” wrote Copes. “The important difference is where the AI sits. With ChatGPT or a coding agent, the AI is the main interface or worker. Jev is a small component inside a regular application. You add it where code needs one judgment, while the rest of the product stays ordinary code.”

“You add it where code needs one judgment, while the rest of the product stays ordinary code.”

Copes reiterates TypeSafe’s stated performance levels: most calls to Jev complete in about 100 milliseconds, input tokens cost $0.042 per million, and (as already noted) output tokens are free.

You send it some data and a list of typed questions, and it sends back one answer per question: a yes/no probability, one option picked from a list you defined, or a position on a scale you defined. Every answer comes with probabilities. 

One developer gave Jev the “one thing it can’t handle”

To put Jev to the test, AI engineer Bartosz Mikulski tells The New Stack that because Jev is advertised as a text-only model, he gave it the one thing it can’t handle: pictures.

“I turned 400 hand-drawn sketches into Scalable Vector Graphics (SVG) coordinates and asked what they were,” Mikulski says. “It got about 35% right, where just ‘guessing’ typically returns 10%, but it answered ‘airplane’ for more than half of the drawings, so that number is part real ability, and part a heavy bias toward one label.”

To be fair, Mikulski notes that TypeSafe says in its own documentation that Jev reads text only and handles words better than numbers. 

“I fed it numbers that encode pictures, which is close to the least fair test anyone could design, and it still beat chance by a wide margin. I mean that as a compliment, not as a benchmark. It tells you nothing about how Jev does on the text classification it’s actually sold for,” Mikulski clarifies.

“I fed it numbers that encode pictures, which is close to the least fair test anyone could design, and it still beat chance by a wide margin. I mean that as a compliment, not as a benchmark.”

Why is TypeSafe Jev called Jev?

Jev is named after the 19th-century economist William Stanley Jevons and his Jevons Paradox: the economic principle that as technology increases the efficiency with which a resource is used, that resource’s total consumption actually rises rather than falls. 

When steam engines became more efficient, we used more coal, not less; when LED lighting dropped lighting costs, we used more lighting; when data compression algorithms lowered the bandwidth needed to stream video, global web data traffic increased… and so on.

Almeida concluded his X video post with a nod to developer productivity and said that, “As we say at TypeSafe, we’re building prod, not God.” The company’s comedy disclaimer is shown below.

The post TypeSafe launched Jev because sequential LLMs are “totally useless for computers” appeared first on The New Stack.

Read the whole story
alvinashcraft
59 minutes ago
reply
Pennsylvania, USA
Share this story
Delete

Why TechBash 2026 Should Be On Your Calendar

1 Share

Every year, TechBash brings together developers, architects, and technologists who want to grow — not just in skill, but in confidence, creativity, and community. It’s the kind of event where you walk in curious and walk out changed. And this year, the keynote lineup captures that spirit perfectly.

Before the breakout sessions and hallway conversations that make TechBash unforgettable, attendees will gather for two keynotes that speak directly to the heart of modern software development: navigating uncertainty and embracing possibility.

These aren’t just talks. They’re catalysts.

Competence Is Overrated — Amy Norris

Amy Norris opens TechBash with a message every developer needs to hear: growth doesn’t come from knowing everything — it comes from showing up anyway. Her keynote reframes self‑doubt as a sign that you’re pushing into new territory, not falling behind. It’s a reminder that the best developers aren’t the ones who have all the answers — they’re the ones who stay curious, stay resilient, and keep moving forward.

This is the kind of talk that makes you sit up a little straighter. The kind that stays with you long after the conference ends.

AI Software Factory: How to Deliver Features During Lunch — Jeffrey Palermo

Jeffrey Palermo brings the future into focus with a keynote about building real, sustainable velocity in an AI‑powered world. Not hype. Not shortcuts. Actual engineering discipline that helps teams ship faster and smarter. He shows how AI can amplify human creativity — not replace it — and how teams can build processes that unlock the kind of productivity that once felt impossible.

It’s a vision of what’s next, grounded in what’s real.

Why This Matters

TechBash isn’t just about learning new tools or techniques. It’s about becoming the kind of developer who thrives in a world that’s constantly changing. These keynotes set the tone for that journey — inspiring, challenging, and energizing attendees before they dive into everything else the conference offers.

So, are you ready to register? You can do so today by clicking here.



Read the whole story
alvinashcraft
59 minutes ago
reply
Pennsylvania, USA
Share this story
Delete

Your Adaptive UI Has No Screenshot

1 Share

Part 2 of The Death of the Static UI — how to test, review and ship an interface that renders differently for every user

Everything here runs. Clone it, run the tests, drag the sliders: github.com/rudrakshshukla/context_aware_transit

A bug report lands on a Tuesday. This is all it says:

“The Buy ticket button was gone. Pixel 8, around 8am. No screenshot, sorry.”

You open the app. The button is there. QA opens the app. The button is there. You check the crash logs, the feature flags, the release diff. Nothing.

The ticket sits in triage for eleven days. Then someone closes it: cannot reproduce.

But it was reproducible. Just not at your desk, at 3pm, sitting still, on office Wi-Fi. And that is the only context your tests have ever run in.

This is what Part 1 costs you. Once your UI is built from live context instead of a fixed layout, “does the screen look right?” has no answer. There is no screen. There are thousands of them, one for every combination of context, and your tests have seen about four.

The good news: other fields solved this long ago. Mobile just hasn’t caught up.

Three ways an adaptive UI breaks

Most teams treat these as one problem. They are three, and each needs a different test.

1. Wrong screen. The app read the context correctly, then picked the wrong layout. Someone running for a train gets a browse grid. This is a logic bug, and logic is cheap to test.

2. Flickering screen. The app picked correctly twice, three seconds apart, and the layout changed under the user’s thumb. Every single frame is correct. The bug only exists over time. This is almost certainly our Tuesday ticket.

3. Screen nobody sees. A layout that is correct, stable, and never happens. You build a feature that only appears in bright sunlight, while driving, above 90% battery. That is 0.3% of sessions. The feature is dead and nobody notices.

Widget tests catch the first one badly. They cannot see the other two at all.

First, make context a plain value

Everything else depends on this one move.

In Part 1, the context engine gave us a stream. Streams are fine in production and painful in tests, because you have to drive them. What you want instead is a plain value you can type out in one line.

class UiContext {
const UiContext({
required this.motion,
required this.daypart,
required this.lux,
required this.batteryPct,
required this.online,
required this.quickActionConfidence,
});
// ... plus copyWith
}

Six fields. That is the whole input to your UI.

Add copyWith, and do not skip it. You will write hundreds of test contexts, and almost all of them are “the normal one, but walking” or “the normal one, but offline”. Without copyWith your test files get unreadable, and once they are unreadable people stop adding cases.

Now separate the decision from the drawing:

LayoutSpec decideLayout(UiContext c) {
// Rule 0 — offline. Never show something that needs the network.
if (!c.online) return const Discovery([kCachedTickets, kOfflineMap]);
  // Rule 1 — nearly dead battery. Show one thing only.
if (c.batteryPct < kLowBatteryThreshold) {
return const QuickAction(kBuyTicket, reason: 'low_battery');
}
  // Rule 2 — the commuter from Part 1. Moving, and the model is sure.
if (c.quickActionConfidence >= kQuickActionThreshold &&
c.motion != Motion.still) {
return const QuickAction(kBuyTicket, reason: 'commuter_intent');
}
  // Rule 3 — otherwise, let them browse.
return const Discovery([kRoutes, kPasses, kOffers]);
}

No widgets. No async. No plugins. No clock. This function runs about a hundred thousand times a second.

And there is not one if statement in home_screen.dart. All the branching lives here, where a test reaches it instantly.

One small thing that matters more than it looks: give LayoutSpec real value equality, and leave reason out of it. The reason is for your logs, not for the user. If two different rules both say “show the buy button”, the screen did not change. The stability test later counts changes the user can see, so including reason would make it fail on refactors nobody could notice. And if you skip equality altogether, every “did the layout change?” check returns false, every stability test passes without testing anything, and you ship the flicker bug with a green board.

Test the decision, not the pixels

final cases = <(String, UiContext, Matcher)>[
('sitting at home, just browsing',
base, isA<Discovery>()),
('walking, model is confident — show one action',
base.copyWith(motion: Motion.walking, quickActionConfidence: 0.9),
isA<QuickAction>()),
('walking, model is unsure — let them browse',
base.copyWith(motion: Motion.walking, quickActionConfidence: 0.5),
isA<Discovery>()),
('very confident but standing still — still browse',
base.copyWith(quickActionConfidence: 0.99), isA<Discovery>()),
('offline — never offer a purchase',
base.copyWith(online: false, quickActionConfidence: 0.99),
isA<Discovery>()),
('battery about to die — one action only',
base.copyWith(batteryPct: 4), isA<QuickAction>()),
];
for (final (name, ctx, matcher) in cases) {
test(name, () => expect(decideLayout(ctx), matcher, reason: '$ctx'));
}

This file is your product spec. Not a document somewhere. This file.

When a product manager says “push people to buy when they’re clearly in a rush”, that sentence becomes a row here before anyone touches a widget. Read the file top to bottom and a non-engineer should follow it.

Look at the fourth row. Very confident, but standing still. The model is more sure than in row two, and the app deliberately does less.

I did not think of that case when I wrote the rule. I found it ten seconds after dragging a slider in the Context Lab, which I will come back to.

Screenshots: test the edges, not every combination

Six context dimensions with a few useful values each gives you thousands of combinations. You cannot screenshot all of them, and you should not try. A golden file is only worth having if a human will actually look at it when it fails, and nobody reviews four thousand images.

So don’t cover the space. Cover its edges. For every rule, take the context just below its threshold and the context right at it. Then one normal example per branch.

These ten are exactly the ones that break when someone changes a number:

Two habits make this work.

Name the file after the context, not the screen. “walk_confidence_0.72_at.png” tells a reviewer what broke. “home_screen_2.png” tells them nothing, and they will approve the diff without looking.

Render through the same code production uses. If your test builds its own MaterialApp, your golden is testing that MaterialApp, not your app.

Load real fonts, or your tests are green and blind

This one cost me an afternoon, and it is the most fitting bug in the whole project.

When you run flutter test, Flutter uses a placeholder font. Every letter is drawn as a solid black rectangle.

My first ten screenshots had perfect layout, perfect spacing, and black bars where the words should be. Every test passed.

Think about that. A screenshot suite can be green and blind at the same time. That is the exact shape of the bug this article opens with.

Fixing it takes two steps, and only one is obvious:

  • Icons are in the test bundle. Setting uses-material-design: true puts MaterialIcons there. Reading FontManifest.json loads them. This is what golden_toolkit does, and it works.
  • Roboto is not. The default Material text style asks for a font that never ships inside your app. It lives in the Flutter SDK folder on your machine.

So the usual fix gives you perfect icons and black-box text. That is worse than no fix, because it looks like it worked.

In the repo, loadAppFonts() handles both. It finds the SDK by walking up from the running Dart executable, so nothing gets committed and nothing gets downloaded, and it behaves the same on your laptop and in CI. If it cannot find the fonts, it fails the test instead of quietly saving black boxes. A silent pass is the enemy here.

Properties: catching the cases you didn’t think of

Edge screenshots cover the contexts you imagined. Adaptive UIs break on the ones you didn’t. So write down the things that must be true everywhere, then throw thousands of random contexts at them.

test('invariants hold across 20000 random contexts', () {
final r = Random(42); // fixed seed: failures repeat
for (var i = 0; i < 20000; i++) {
final c = randomContext(r);
final spec = decideLayout(c);
    // 1. Same input, same output. Always.
expect(decideLayout(c), spec, reason: 'not deterministic at $c');
    // 2. Never show the user an empty screen.
expect(spec.surfacedFeatureIds, isNotEmpty, reason: 'empty at $c');
    // 3. Offline means no purchase path. No exceptions.
if (!c.online) {
expect(spec.surfacedFeatureIds, isNot(contains(kBuyTicket)));
}
}
});

The first one looks pointless. It isn’t. The moment someone puts a DateTime.now() or a cached value inside the policy, this test goes red. And that is the worst bug you can have here: a UI you cannot reason about, because it is no longer a function of its inputs.

The third one is the one that pays off over years. Personalisation rules pile up over time. What eventually breaks is never the main path. It is some safety rule nobody realised everything depended on.

Make the stability budget a real test

Part 1 mentioned stability budgets as an idea. Turn it into a test that can fail.

The trick is a minimum waiting time. Once a layout is on screen, it stays for at least twenty seconds, whatever the model says:

LayoutSpec apply(LayoutSpec candidate, DateTime now) {
if (_current == null) { _current = candidate; _changedAt = now; return candidate; }
if (candidate == _current) return _current!;
if (now.difference(_changedAt!) < dwell) { _suppressed++; return _current!; }
_current = candidate; _changedAt = now;
return candidate;
}

Then test it over time, not in one frame. Replay sixty seconds of realistic sensor noise sitting right on the threshold:

60s of sensor noise at the policy threshold
without governor: 28 layout changes
with governor: 2 layout changes (28 suppressed, budget 3)

Twenty-eight rearrangements in one minute. That is what “the button was gone” feels like from the other side of the glass.

This is the only test in the suite that can see problem number two, because it is the only one that looks at time.

Two more things I learned writing it.

Be honest about which assertions really test something. “At most 3 changes per minute” with a 20-second wait is guaranteed by the maths. No random seed can ever break it. Running that across 25 seeds looks rigorous and proves nothing. The assertion with teeth is the one next to it: two changes the user can see are never closer together than the waiting time, in any trace.

Test the opposite failure too. Almost nobody does. If you tune the waiting time too high, your app stops adapting at all, and you are back to a static screen. There is a test for that.

Reachability: the number nobody measures

Code coverage tells you a widget was built. It does not tell you a real person ever saw it.

You can measure this privately, because a context is six numbers, not personal content. Collect them on device, send aggregates, and check what your users actually reach:

reachability over 50000 contexts
buy_ticket 16.09%
routes 78.91%
passes 78.91%
offers 78.91%
cached_tickets 5.00%
offline_map 5.00%

Put that table in any pull request that changes a threshold. It shows the real effect of a one-character diff.

It also answers a question product teams actually care about: what share of real sessions can reach this feature? That beats “is it on the home screen?”.

One more test in that file deliberately hides a feature deep in the rules, then checks that the detector catches it. A passing test is only worth trusting if you have proved it can fail.

The parts that aren’t code

Designers review the rules, not the mockups. Give a designer one Figma frame and you get approval for one context. Give them the rule table plus the edge screenshots and you get approval for the whole system. They pick this up quickly. They have been doing responsive breakpoints for fifteen years, and this is the same idea with more inputs.

Better still, give them the real thing. Running the repo opens a Context Lab: a phone on one side, six sliders on the other. Drag the confidence slider past 0.72 and the interface turns into a different interface in your hand.

It is not a toy. It is where I found the “confident but standing still” case. Someone holding the Lab explores far more of the context space than someone reading a spec.

Log the context with every event. If you record buy_ticket_tapped without the context that produced that layout, you have thrown away the thing that explains it. Log the confidence, the layout you chose, and whether the governor blocked a change. Those three fields turn “conversion dropped 4%, not sure why” into something you can debug.

What actually changes

None of this is new thinking. It is the move compilers made decades ago: stop checking the output, start checking the function that produces it, then prove some things are true for every possible input.

What is new is that mobile teams now need it too.

The fixed screen was never only a design choice. It was the thing that made testing possible. Give it up and you have to replace it with something: a pure decision function, a set of edge screenshots, a few invariants, a test that understands time, and a reachability number.

Do that, and “cannot reproduce” stops being a category of bug. The context that caused it is six numbers. Six numbers fit in a test.

The code: github.com/rudrakshshukla/context_aware_transit — a runnable Flutter app and all 29 tests, with no dependencies beyond Flutter itself. On a fresh clone, flutter test works straight away.

Part 1: The Death of the Static UI


Your Adaptive UI Has No Screenshot was originally published in Flutter Community on Medium, where people are continuing the conversation by highlighting and responding to this story.

Read the whole story
alvinashcraft
1 hour ago
reply
Pennsylvania, USA
Share this story
Delete
Next Page of Stories