AI 资讯
I built an embeddable screen-time calculator that doesn't phone home
Most embeddable widgets are surveillance with rounded corners. You paste one script tag, it opens a socket back to someone else's server, drops analytics, fingerprints the page, and turns your article into their funnel. I wanted the opposite. I had built a small screen-time calculator for an iPhone side project. You enter daily phone hours, how much of that time you'd actually want back, and your age. It returns the number not just as hours per year, but as waking years of the life you have left . The surprising part was not the maths. The surprising part was that the calculator itself was the first marketing asset I had built that people might reasonably link to. So the next step was obvious: make it embeddable. Constraints I gave myself four rules: No tracking script No backend callback No cookie or storage requirement Useful standalone, but with a real reason to click through That ruled out the normal widget pattern immediately. I did not want a script that asks the host page for DOM access. I did not want the embed to send typed values back to me. And I did not want to bolt analytics onto a tool whose whole public claim is "nothing leaves your device". So the widget became a single static iframe page. The embed snippet This is the whole thing: <iframe src= "https://shantj.github.io/sproutguard/embed.html" width= "100%" height= "620" style= "border:0;max-width:600px" loading= "lazy" title= "Screen time calculator" ></iframe> <p style= "font-size:13px;opacity:.7;margin:6px 0 0" > <a href= "https://shantj.github.io/sproutguard/screen-time-calculator.html?ct=embed-credit" > Screen Time Calculator </a> — free, no signup, runs in your browser. </p> No JavaScript include. No SDK. No npm package. Just an iframe and a credit link. The iframe points at a page that contains the calculator UI and the arithmetic. Because it is a static page, the host site never has to trust my script with its DOM. The actual calculator logic The core number is intentionally boring: const LIF
AI 资讯
Zero Dependency 2026 — Build Real Software With No Packages. Prove It.
Half your code is now written by an AI that hallucinates the other half's package names. That's not a joke. Across 576,000 samples, 19.7% of the packages AI coding models suggested didn't exist — and attackers have started pre-registering those exact hallucinated names, waiting for someone to npm install a package that was never real to begin with. Meanwhile, public registries catalogued 454,600 new malicious packages in 2025 alone, pushing the cumulative total past 1.2 million. A modern web app now pulls in 1,200+ dependencies once you count the full transitive tree — for software that, ten years ago, would have shipped with a fraction of that. That's precisely what Zero Dependency 2026 is about. Organized by Hackathon Raptors , Zero Dependency is a 72-hour online global hackathon where participants build genuinely useful software — CLIs, parsers, servers, databases, security tools — using nothing but their programming language's standard library. No frameworks. No packages. No supply chain to inherit. Just your language and your engineering skill. Why Zero Dependency? Modern AI coding assistants can generate code fast, and they reach for a dependency by reflex — sometimes one that doesn't exist. But real engineering isn't judged by how many packages you imported. It's judged by questions like: Do you actually understand what the library you'd normally import is doing underneath? Can you build the thing yourself, correctly, from primitives? Does your code handle the edge cases a package would've handled for you? Is the implementation idiomatic, or a fight against the standard library? Could a judge verify your dependency manifest is empty in five seconds? Zero Dependency is designed around these questions. Instead of rewarding whoever pulls in the most packages the fastest, the hackathon rewards teams who can prove they didn't need to. About the Hackathon 🌍 Global Online Hackathon ⏳ 72 Hours 💰 $1,800 Prize Pool 👥 Solo or Teams of up to 4 🎓 Open to students, profess
AI 资讯
AWS Route 53 — DNS Fundamentals, Hosted Zones, Routing Policies & Resolvers
Part of my AWS learning journey — transitioning from Systems Engineer to Cloud/DevOps. Route 53 is where networking meets the internet — how domain names reach your applications, how traffic gets distributed intelligently, and how AWS and on-premises networks resolve each other's names. 📋 Topics Covered # Topic Type 1 DNS Pre-Requisites — How DNS Works Concept 2 Complete DNS Resolution Flow Concept + Interview 3 What is Route 53 Concept 4 Hosted Zones — Public vs Private Concept + Lab 5 Hosted Zone ID Concept + DevOps 6 DNS Record Types and Use Cases Concept + Cert 7 NS and SOA Records — Auto-Created, Never Delete Concept + Interview 8 Alias Record — AWS-Specific Concept + Cert 9 Landing Zone — Brief Context Concept 10 Route 53 Routing Policies — All 8 Concept + Cert 11 Route 53 Traffic Policies Concept + DevOps 12 Route 53 Resolvers Concept + Interview 13 Inbound vs Outbound Resolver Endpoints Concept + Interview 14 Route 53 Forwarders Concept + Interview 15 Split-Horizon DNS Concept + Interview 16 Interview Questions Interview 17 Practice Tasks Practice DNS Pre-Requisites — How DNS Works DNS is the reason you type google.com instead of 142.250.195.46 . Before understanding Route 53, these fundamentals must be solid. Core Vocabulary Term What it means Domain Human-readable name — google.com , tejascloud.in IP Address Machine address — 54.21.11.90 — what computers actually use DNS The translation system — converts domain names → IP addresses TLD Top-Level Domain — the last part after the final dot TTL Time To Live — how long a DNS response is cached before re-querying Recursive Resolver Finds the answer for the client by querying other DNS servers, caches the result Authoritative DNS Server Stores the official DNS records for a domain — returns the definitive answer Common TLDs: .com → commercial · .org → organizations · .net → network · .in → India · .uk → United Kingdom · .edu → education · .gov → government The Complete DNS Resolution Flow This is the full journe
AI 资讯
I stopped hardcoding locales, and adding a language became a one-line change
Most i18n tutorials stop at "put your strings in a JSON file". That covers labels. It does not cover the thing that actually breaks: URLs. I run a personality test site in five locales (French, English, Brazilian Portuguese, European Portuguese, Spanish). Same site, five language trees, roughly 96 articles each. The first version had the shape every project seems to grow by accident: $prefix = $locale === 'en' ? '/en' : '' ; That line, or a cousin of it, spread across controllers, views and helpers. Every one of them was correct when written and wrong the moment a third locale showed up. The bug it produces is the worst kind: nothing throws, the page renders, and the Spanish version quietly links to French URLs. The rule that fixed it One rule, enforced by a test: no locale literal anywhere outside the config file. Not in controllers, not in views, not in helpers. If code needs to know something about a locale, it asks the config. Adding a locale then becomes: content files, plus one entry in config/locales.php . Nothing structural. 'default' => 'fr' , 'available' => [ 'fr' , 'en' , 'pt-br' , 'pt-pt' , 'es' ], Three helpers cover essentially every call site: locale_prefix () // '' for the default locale, '/es' otherwise locale_url ( '/disc' ) // prefixed, canonical, ready to print locale_slug ( 'groupe' ) // the localized route segment The part nobody warns you about: slugs are data Labels translate. Slugs are a different problem, because a slug is simultaneously a URL, a cache key, an SEO asset and a foreign key into your own content. The decision that saved me: one locale is canonical, always. French, in my case. Every slug in every other language resolves back to a French slug before anything else happens. $slugs = app ( SlugService :: class ); $slugs -> toLocale ( 'quatre-tendances' , 'es' ); // 'cuatro-tendencias' $slugs -> resolveToCanonical ( 'cuatro-tendencias' ); // 'quatre-tendances' Without that pivot you get N-to-N translation tables and, eventually, two
AI 资讯
I find reading hard, so I built a text-to-speech reader for Android — here's how
I've always found reading hard. Long documents slide off my attention, and I lose my place constantly. What I really wanted was something that would read to me and show me the words as it went — so my eyes and ears stayed in sync. Nothing did exactly that, so I built it. It's called ReadAloud , it's on Google Play, and this post is the "why" and the interesting bits of the "how." The moment it became real The first person I showed a rough build to was my Sister, Praise . She'd come to town to officiate a Women's Premier League match at Auntie Aku Astro Turf Park, and I pulled out my phone between everything else. She watched a paragraph read itself aloud with each word lighting up and got genuinely excited — that was the push I needed. She became tester #1. My colleague Reggie became tester #2. Between them they found the rough edges I'd stopped seeing, and the app settled into something stable. What it is A text-to-speech reader for PDFs, EPUB, DOCX, plain text and web articles . It reads aloud in natural voices, highlights each word as it speaks , and auto-scrolls to follow along. There's offline listening, English/French/Spanish, speed-reading (RSVP), a vocabulary builder, and reading stats. The stack: Kotlin, Jetpack Compose + Material 3, MVVM + Clean Architecture, Hilt, Room, DataStore, WorkManager , minSdk 26 . Now the parts that were actually interesting to build. 1. Word-by-word highlighting This is the whole product, so it had to be right. On-device voices are easy — Android's TextToSpeech gives you onRangeStart (API 26+), which fires per spoken range: override fun onRangeStart ( utteranceId : String , start : Int , end : Int , frame : Int ) { // highlight the substring [start, end) in the reader _currentRange . value = start to end } The catch: the natural cloud voices people actually want don't emit onRangeStart . So for cloud synthesis I wrap each word in an SSML <mark> and ask Google Cloud TTS to return timepoints : <speak><mark name= "w0" /> Every <mar
AI 资讯
Building a Chrome Extension to Auto-Save Gemini Chat Logs using AI (Part 1)
This article was originally published on e-shikumi-labo . Hello, I'm Shin from e-Shikumi-Labo. How do you all manage your conversations with Gemini? When you manage to extract a useful response from the AI, have you ever thought, "I want to keep this somewhere"? It all started from a simple, practical desire in my daily work: "I want to automatically save useful conversations from Gemini to a spreadsheet before they fade away." So, borrowing the power of Generative AI (Gemini), I tried making my own personal Chrome extension. Over this four-part series, I will write about "systematized thinking"—the process of utilizing AI to build tools and independently maintaining them. In Part 1, I'll share the developmental dialogue process: "How did I instruct the AI, what information did I provide, and how did we complete the prototype?" 1. A Prompt That Says: "Don't Guess, Ask for the Information You Need" As the very first step in development, I threw this prompt directly at Gemini itself. "I want to save Gemini's responses to a spreadsheet using a Chrome extension. Tell me how to build it without using your imagination. If you need any specific information, please point it out." The key here lies in two constraints: "without using your imagination" and "point out if you need information." When you try to build a web data extraction tool using AI, the AI often tends to "guess" the internal structure of the webpage (like HTML tags and class names) on its own and write the code. And even when you test this supposedly completed code, you fall into the trap of it not working because it doesn't align with the actual screen structure. To avoid this trap, I explicitly communicated, "Don't guess on your own. If there's missing information, I want you to demand it from the human side." 2. A Game of Catch with AI Using DevTools When I threw this prompt, the AI returned the following response: AI: "Understood. To create code that works reliably while eliminating guesswork, please retr
开发者
Is this $450 laptop from an unknown brand too good to be true?
Finding a good laptop under $500 was hard enough before RAMageddon. They nearly always had cheap hardware and underpowered, often outdated chips. That's what made the MacBook Neo so disruptive: It offered great build quality and good-enough performance starting at $599. Windows laptops couldn't touch it. Even though it's gone up to $699, it's still […]
科技前沿
The first self-driving vehicle on Mars has proven to be a smashing success
About 90 percent of the distance driven by Perseverance has been autonomous.
科技前沿
Xteink X4 Pro Pocket E-Reader Review (2026): Fun but Limited
Xteink’s new X4 Pro e-reader is its best yet, but the lack of an ebook store can be limiting.
AI 资讯
A 200 From the Wrong System: How Two Pages Stayed Invisible for 17 Days
Two pages on my site went live on July 22. On August 8 they had zero impressions in Google. Not low. Zero, across three weekly exports. URL Inspection didn't say "crawled, not indexed." It said Google could not recognise the URL. Referring sitemap: none detected. Referring pages: none detected. Last crawl: not applicable. Never discovered. Seventeen days. The pipeline was green the entire time My deploy is a small chain: rsync the file, import it into MySQL, restart the service, ping IndexNow. Every step returned success. The last step returned 200 on every URL, every deploy, for three weeks. Here's what I'd never examined: IndexNow doesn't feed Google. It's Bing, Yandex, Seznam, Naver. My green light was real — it was just about a different search engine than the one whose console I was reading. That's the whole bug, and it isn't an SEO bug. It's the generic one: system A returns 200 → I conclude something about system B → nothing in the response object ever objected If you've ever read a webhook 202 as "the downstream processed it," or a CDN purge 200 as "the edge is cold," it's the same shape. What actually broke Search Console's Sitemaps report: Submitted: 2026-07-22 Last read: 2026-07-22 ← seventeen days ago Discovered: 101 URLs ← the file has had 117 for weeks The two pages went live on July 22 — the same day as the only read. Google fetched the sitemap and moved on, within hours of the file changing. Then nothing brought it back, because a sitemap changing on your server notifies nobody. There is no push. It's a pull-only resource with no cache invalidation, and if the consumer doesn't happen to return, your new URLs live in a document no one is reading. Resubmitting took two minutes. Read immediately, 117 URLs. So I wrote the check. It doesn't catch the bug. This is the part worth more than the fix. I wrote a post-deploy verifier. It does two things: // 1. every published, non-redirected page appears in the live sitemap const missing = published.filter((p) =
AI 资讯
Domain-Driven Infrastructure: Organize Your Terraform by Reason to Change
One morning, a new engineer on the team asked me a simple question. "The Lambda for the new notification feature — does it go under modules/ , or somewhere else?" I didn't have a good answer. We had a modules/lambda/ directory, so the obvious move was to put it there, and I nearly said so before something stopped me. The notification feature was part of the order workflow. Was this a reusable part, or a piece of the order domain? Two different questions were hiding inside one "where does it go?", and our directory structure couldn't tell them apart. The conversation ended the way these conversations always end. "Let's just put it in modules/lambda/ for now." The layout everyone uses You've probably seen this structure. Most Terraform repositories look like it: ├── modules/ │ ├── vpc/ │ ├── ecs/ │ ├── rds/ │ ├── iam/ │ └── lambda/ └── environments/ ├── dev/ └── prod/ It works. It plans, it applies, it looks organized. Nothing about it is wrong until the business asks for something. "Ship the new feature." "Traffic doubled, scale it up." "Compliance changed, revisit the permissions." Each request is one business change. And each one sends you into vpc/ , ecs/ , rds/ , iam/ , secrets/ , cloudwatch/ . Different requests, same sprawl. One reason to change, six directories to touch. Back when I worked this way, review time didn't go where you'd expect. Whether the change was correct was the easy part. The hard question was whether it was safe to apply, and nobody could answer that from the diff, so we asked whoever remembered what else depended on the security group being edited. Software design has a word for this: low cohesion. Things that change together are stored apart. We'd never accept this in application code. We learned — from decades of work on cohesion, coupling, and separation of concerns — to keep things that change together in one place. Somehow that vocabulary never made it down to our infrastructure repositories. This is not a Terraform problem. It is a de
AI 资讯
Hairmax LaserBand 82 ComfortFlex Review: Putting Down New Roots
Hairmax’s LaserBand 82 ComfortFlex took only 90 seconds per treatment, and it produced visible results along my widening part.
AI 资讯
Teaching Your AI Web Design Some Actual Taste
Hello, I'm Maneshwar. I'm building git-lrc, a Micro AI code reviewer that runs on every commit. It is...
开发者
I Know the Recipe. I Miss the Winter Kitchen.
This is a submission for Frontend Challenge - Comfort Food Edition, CSS Art. ...
AI 资讯
A Practical Guide to Converting Inches, Centimeters, Meters, Feet and Millimeters
If you work with measurements often enough, you eventually run into the same problem: the value you have isn't in the unit you need. A product specification might be in inches. A construction drawing might use feet. A European supplier might give you dimensions in centimeters or millimeters. The actual formulas are usually simple. Finding the right conversion, avoiding rounding mistakes, and checking a large list of values can be more annoying than the math itself. Here are the conversions I use most often and a few practical ways to work with them. Inches to centimeters The basic relationship is: 1 inch = 2.54 centimeters So the formula is: centimeters = inches × 2.54 For example: 10 inches × 2.54 = 25.4 cm This is probably the most common conversion when moving between imperial and metric measurements. If you just need to check a value quickly, Pulgadas a CM has an interactive converter along with a conversion table and frequently asked questions. Centimeters to inches Going in the opposite direction means dividing by 2.54: inches = centimeters ÷ 2.54 For example: 25.4 cm ÷ 2.54 = 10 inches You can use the CM a Pulgadas converter when you need to work in this direction. This is particularly useful when a measurement is provided in centimeters but the product, tool, or specification you're working with uses inches. Meters to inches Meters are larger units, so the conversion factor is correspondingly larger. One meter contains approximately: 39.3700787 inches Therefore: inches = meters × 39.3700787 For example: 2 meters ≈ 78.7401574 inches For a quick calculation, you can use the Metros a Pulgadas converter . This conversion can come up when working with room dimensions, furniture measurements, fabric, sports equipment, or other products where metric and imperial specifications are mixed. Inches to meters The reverse calculation is: meters = inches × 0.0254 For example: 100 inches × 0.0254 = 2.54 meters The Pulgadas a Metros converter is useful when an imperial meas
产品设计
WhatsApp Gets a Handy @all Feature for Group Chats
A new software update builds on WhatsApp’s group chat chops by adding anonymous polls and introducing an easier way to start a smaller private chat away from the larger group.
AI 资讯
Nitecore’s latest power bank is the lightest and most compact yet
There's two things you should know about me, your intrepid reviewer: I hate the feature creep associated with modern power banks, and I love shaving grams off the gear I carry when backpacking, bikepacking, and trail running. So imagine my delight when Nitecore released a new generation of its ultralight NB10000 battery. After a few […]
AI 资讯
I Kept Hearing "Didn't We Already Send That?" So I Built a Tool to Fix It
I'm a self-taught developer. No CS degree, no funding, no team. Just me, a laptop, and a problem I kept watching people struggle with. The Problem Every freelancer and small agency I know deals with the same mess: client details scattered across WhatsApp chats, email threads, Google Drive folders, and random Notion pages. Nothing lives in one place. When a client asks "wait, didn't we already send you the logo files?" you're digging through three different apps trying to remember. I didn't just hear about this problem — I lived it. So four months ago, I started building Kray. What Kray Actually Does Kray gives freelancers and agencies one organized workspace per client — projects, links, and notes, all in a single place instead of scattered across five different tools. The part I'm most proud of: when you share a project with a client, they can open the link and see everything instantly — no sign-up, no account creation, no friction. Just a clean, simple view of what they need to see. The Stack Since I was building this entirely solo with zero budget, I leaned on tools that let me move fast without infrastructure headaches: React 19 + Vite + TypeScript (strict mode — no shortcuts) Tailwind v4 for styling Supabase for auth, database, and storage Deployed on Vercel No backend servers to manage. No DevOps to worry about. Just me shipping features. What I Learned Building Solo You will hit bugs that eat entire days. I spent hours debugging a sitemap indexing issue that turned out to be one missing header. That's the job — most of building isn't writing new features, it's fixing the thing that should've worked but didn't. Deploy discipline matters more than you think. I once tested a feature locally, assumed it was live, and spent 20 minutes confused about why production wasn't behaving — because I'd forgotten to push. Lesson learned: always verify what's actually deployed before debugging further. Marketing is its own skill, and it's humbling. I've spent the last severa
AI 资讯
Your firewall is your AI policy — I probed 18 major sites to read it
Everyone's arguing about AI search visibility. Almost nobody is measuring the boring part: whether AI crawlers can fetch your pages at all . So I built a small open-source tool — geo-crawl-audit — that probes any site with the user-agents of every AI crawler that matters (GPTBot, OAI-SearchBot, ClaudeBot, PerplexityBot, ChatGPT-User, and friends), measures how each is treated versus a normal browser, and checks the thing most people never think about: how many words exist in the raw HTML before any JavaScript runs . Because here's the detail the industry keeps missing — GPTBot, ClaudeBot, and PerplexityBot don't execute JavaScript. For most sites, Googlebot (feeding Gemini) and Applebot are the only AI-adjacent crawlers that render it. A site can rank #1 in Google and be a blank page to nearly everything else. I pointed it at 18 major sites on August 7. Five findings worth your time. 1. Access patterns line up with the business relationships The Guardian — which has a content deal with OpenAI — serves my simulated GPTBot, OAI-SearchBot, and ChatGPT-User a clean 200 . The same request wearing ClaudeBot, PerplexityBot, or CCBot : 403 , and those names are in its robots.txt disallow list too. Policy and enforcement agree. The New York Times — in litigation with OpenAI — 403s nearly everyone: GPTBot, OAI-SearchBot, ClaudeBot, PerplexityBot, Common Crawl, meta-externalagent. Two user-agents got through: bingbot and Amazonbot. I want to be careful about the claim here: a status code tells you who is blocked , not why . Any individual 403 has mundane explanations. But when the allow/deny matrix maps this cleanly onto public deals and public lawsuits, the firewall config has become a business document — and it's readable by anyone with a terminal. 2. robots.txt is a polite sign. Some doors are unlocked anyway. Reddit's robots.txt blocks every AI bot in my list — fourteen tokens, no exceptions. Enforcement tells a different story: my GPTBot UA got a 403 and ClaudeBot and CCB
AI 资讯
Docker for Beginners: Images, Containers, Ports, and Volumes Explained
Docker for Beginners: Images, Containers, Ports, and Volumes Explained If you've ever followed a programming tutorial and seen something like: docker run ... you've probably wondered: What exactly is Docker doing? I had the same question when I started learning Docker. At first, I thought Docker was simply a way to "run applications in containers." But there is much more to it. Once I understood four concepts — images, containers, ports, and volumes — Docker became much easier to understand. So let's break it down from the beginning. What Is Docker? Docker is a platform for building, packaging, and running applications in isolated environments called containers . The basic idea is simple: Package an application together with the things it needs to run, and make that package portable. For example, imagine you build a Python application. Your application might depend on: Python 3.12 FastAPI Uvicorn Several Python packages Environment variables Certain system libraries On your computer, everything works. Then someone else downloads your project. They install a different Python version. A package is missing. Something behaves differently. Now you have: "It works on my machine." Docker helps reduce this problem by allowing you to define the environment your application should run in. The Four Concepts You Need to Understand Before learning Docker commands, understand these four things: Docker Image ↓ Docker Container ↓ Ports ↓ Volumes Let's look at each one. 1. What Is a Docker Image? A Docker image is a packaged, read-only template used to create containers. Think of it like a blueprint. For example: Docker Image │ ├── Ubuntu ├── Python ├── Application code ├── Dependencies └── Configuration An image contains the instructions and filesystem needed to create a container. You can download images from container registries such as Docker Hub. For example: docker pull nginx This downloads the Nginx image. You can see your downloaded images with: docker images You might see s