今日已更新 279 条资讯 | 累计 38972 条内容
关于我们

标签:#EV

找到 5284 篇相关文章

AI 资讯

Add Livewire modals in Laravel with Wiremodal

Wiremodal is a framework-agnostic modal package for Laravel, which allows to handle modals, so you don't have co configure them in all your projects. It ships a few Livewire-side helpers that make exactly this pleasant. This post is the Livewire integration end to end: opening and closing from PHP, delivering a payload on open, the one trap to avoid, and the optional form panel for when a modal happens to be a form. How to install Pull the package in and get the assets onto the page. composer require edulazaro/wiremodal php artisan vendor:publish --tag = wiremodal-assets The service provider auto-registers and there is no config file. Point your layout at the published files: <link rel="stylesheet" href="{{ asset('vendor/wiremodal/css/wiremodal.css') }}"> <script src="{{ asset('vendor/wiremodal/js/wiremodal.js') }}" defer></script> If you bundle with Vite, skip the publish and import straight from the vendor directory instead, so a package update flows through without re-publishing anything: /* resources/css/app.css */ @import "../../vendor/edulazaro/wiremodal/resources/css/wiremodal.css" ; // resources/js/app.js import ' ../../vendor/edulazaro/wiremodal/resources/js/wiremodal.js ' ; Opening and closing from Livewire Define the modal once with the <x-wiremodal> component, give it a name , and fill the body and footer slots. Here is a delete confirmation: <x-wiremodal name="confirm-delete" title="Delete record?" size="sm"> <x-slot:body> <p>This action cannot be undone.</p> </x-slot:body> <x-slot:footer> <button type="button" data-wm-dismiss>Cancel</button> <button type="button" wire:click="destroy">Delete</button> </x-slot:footer> </x-wiremodal> The Cancel button carries data-wm-dismiss , and any element with that attribute closes the modal it sits in, so you never write a cancel handler. To open and close from the component itself, use the macros the package registers on every Livewire component: public function confirmDelete (): void { $this -> openModal ( 'confirm

2026-08-05 原文 →
AI 资讯

Can IP Geolocation Personalise Content with Node.js?

A visitor lands on a website and immediately sees prices in the wrong currency, content written for another region, and shipping information that does not apply to them. Nothing is technically broken, yet the experience feels poorly designed. For international websites, location can be a useful personalization signal. Instead of asking every visitor to manually select a country before displaying relevant information, developers can use IP based geographic data as an initial indication of where a request originates. That is where ip geolocation for content personalisation can become useful. The objective is not to identify a person. It is to make an otherwise anonymous visit more contextually relevant. How can location improve content personalisation? Location can influence many small decisions that collectively affect the user experience. An ecommerce website may display a local currency. A news publisher may surface regional stories. A software company may show country specific documentation or availability information. The process is relatively simple. A visitor sends a request to a website. The server obtains the request's public IP address. That IP is sent to a geolocation service. The response provides geographic information. The application then selects content according to predefined rules. The crucial part is the final step. Geolocation provides data, but business logic determines what the visitor actually sees. Which approaches can websites use? One approach is manual location selection. The user chooses their country or region from a menu. This is transparent and usually accurate because the user explicitly provides the information. However, it adds friction and may be forgotten during future visits. Browser based location is another option. It can provide more precise positioning, but it normally requires permission and is not always appropriate for simple content personalization. IP based geolocation sits between these approaches. It requires no location

2026-08-05 原文 →
开发者

Customizing Hugo PaperMod Without Forking the Theme

Sites that start from a stock theme tend to look like it. This one did too — until recently it was the default PaperMod screen. The editorial homepage and unified article styling you're looking at came out of a single day of customization. This guide is that work written down, with the code. One principle drove all of it: never fork the theme. The theme stays a submodule and keeps receiving updates; you win with site-level files only. Hugo resolves same-path site files ahead of theme files, which makes this possible. The entire customization of this site is a handful of files: layouts/index.html ← full homepage replacement data/home/ko.yaml, en.yaml ← homepage copy (per language) assets/css/extended/home.css ← homepage styles assets/css/extended/custom.css ← unifying every other page The starting point is a Hugo site with PaperMod as a submodule, deployed to GitHub Pages. Basic installation is well covered by the PaperMod wiki , so I'll skip it. 1. Replace the homepage wholesale Create a single layouts/index.html and the homepage is yours. The theme's home template stays untouched. The key move: don't hardcode copy into the markup — pull it from data files. On a bilingual site, one template then serves both languages: {{- $copy := index .Site.Data.home .Site.Language.Lang -}} {{- $posts := first 4 (where .Site.RegularPages.ByDate.Reverse "Section" "blog") -}} <section class= "editorial-hero" > <p class= "editorial-eyebrow" > {{ $copy.hero.eyebrow }} </p> <h1> {{ range $i, $line := $copy.hero.titleLines }}{{ if $i }} <br> {{ end }}{{ $line }}{{ end }} </h1> <p class= "editorial-intro" > {{ $copy.hero.intro }} </p> </section> data/home/en.yaml holds nothing but words: hero : eyebrow : " IDEAS · PRODUCTS · OPPORTUNITIES" titleLines : - " Where ideas become products," - " and products become new opportunities." Copy edits stop requiring template changes, and adding a language is one more yaml file. Latest posts are pulled dynamically as above — handle the {{ else }} emp

2026-08-05 原文 →
AI 资讯

Reading Karpathy's Lord of the Rings Demo: What Long Context Plus Autonomy Opens for Builders

A demo Andrej Karpathy posted over the weekend stuck with me. He gave Opus 5 a million-token context and the first paragraph of The Lord of the Rings, and asked for a procedural 3D rendering of the scene in Three.js. The model worked alone for about two hours, wrote 5,500 lines, and coordinated polygon placement, camera paths, and animation on its own. Total cost: about $10. The result is faster to watch than to describe. Most reactions read it as the next step past "draw a pelican SVG" benchmarks. Something else looked bigger to me. What changed isn't the model's artistry. It's the unit of delegation. The unit of delegation changed Until now, the work we handed agents came in prompt-sized pieces. One function, one bug, one file. Anything bigger, we decomposed ourselves. The reason was simple: with a small context, the early parts of a long job slide out of view, and coherence goes with them. A million tokens erases that premise. Everything the model wrote and tried across a two-hour session stays in view. When the desk is big enough, there is no reason to hand work over in slices. Delegation moves from the task to the session. That is the difference between a function call and a work session. The first, we decompose and supervise. The second, we hand over material and intent, and receive a result. Karpathy's entire contribution was picking the paragraph and watching the output two hours later. Where the builder's work moves When execution costs $10 and two hours, execution is no longer the bottleneck. Two things remain. On the way in: the brief. What goes into the context. Karpathy's input was one paragraph, but choosing it was the design act. Translated to our work, it becomes choosing which spec, brand guide, reference, or codebase goes in whole — and what stays out. On the way out: judgment. By what standard do you accept the result? Reviewing 5,500 lines one by one doesn't match session-sized delegation. Instead, you define "done" before the run, then judge the

2026-08-05 原文 →
AI 资讯

Top 10 CLI Tools Every Developer Should Try in 2026

Graphical tools are great, but most of my daily development now happens in the terminal. A good CLI tool saves time, integrates with automation, and keeps my workflow consistent across local development and CI/CD. Here are the 10 CLI tools I use the most. Apidog CLI If you're working with APIs, this is the tool I've found myself using the most. I use it to run API test scenarios, manage environments, and reuse the same tests in GitHub Actions instead of maintaining separate GUI workflows. Git Still the foundation of every development workflow. Docker CLI The fastest way to spin up local services and reproduce production environments. GitHub CLI Creating pull requests, reviewing issues, and managing repositories without leaving the terminal is a huge productivity boost. HTTPie Perfect for quick API requests when debugging or exploring endpoints. jq If you work with JSON every day, jq is almost indispensable. ripgrep (rg) Lightning-fast code searching. Once you start using it, it's hard to go back. fd A simpler and faster replacement for the traditional find command. kubectl Essential for anyone deploying applications to Kubernetes. just A lightweight task runner that helps automate repetitive development commands. Final Thoughts The biggest improvement to my workflow has been moving repetitive tasks into the terminal. API testing, deployments, version control, and automation all become easier when everything is scriptable. Among these tools, Apidog CLI has had the biggest impact because it lets me keep API testing in the same terminal-first workflow that I already use for development and CI/CD. What CLI tool couldn't you live without?

2026-08-05 原文 →
AI 资讯

New HTTP QUERY Method (RFC 10008) Explained | Stop Using POST for Search

Introduction In June 2026, the IETF published RFC 10008 - the first new general-purpose HTTP method since PATCH was introduced in 2010. The method is called QUERY . In simple terms: QUERY = Safety of GET + Body of POST You can now send complex search/filter queries in the request body, while the server knows the operation is safe and idempotent . This means caching, automatic retries, and CDNs can all work properly. This single change can finally end the long-standing practice of using POST for search. The Problem We Had 1. Limitations of GET With GET, query parameters go in the URL: GET /products?category=electronics&price_min=1000&price_max=50000&brand=samsung,apple&sort=-rating&page=1&limit=20 When filters become complex (JSON filters, nested conditions, many tags), the URL easily exceeds 8,000 characters. Many servers, proxies, and browsers struggle with this. URLs also get logged, bookmarked, and shared — which is often undesirable. 2. Problems with POST So many developers started using POST for search: POST /products/search Content-Type: application/json { "filters": { "category": "electronics", "price": { "min": 1000, "max": 50000 }, "brands": ["samsung", "apple"] }, "sort": "-rating", "page": 1, "limit": 20 } But POST is not safe and not idempotent . That means: Caches and CDNs cannot safely cache the response Automatic retries after network failures are risky The server may treat it as a state-changing operation We have been pretending that a read operation is a write operation for years. What is the QUERY Method? According to RFC 10008: A QUERY requests that the request target process the enclosed content in a safe and idempotent manner and then respond with the result of that processing. In plain English: You send the query in the request body (like POST) The server processes it and returns the result It does not change any server state (like GET) Sending the same request multiple times produces the same result (idempotent) Comparison Table Property GET Q

2026-08-05 原文 →
AI 资讯

SkiaSharp 4.0 Establishes Milestone-Aligned Release Cadence

Microsoft and Uno Platform have released the first stable versions in the SkiaSharp 4 series, beginning with SkiaSharp 4.148.0 and followed shortly afterward by 4.150.0. A 4.151.0 prerelease line is also available, demonstrating the project’s new approach of aligning package versions and release cadence with upstream Skia milestones. By Edin Kapić

2026-08-05 原文 →
AI 资讯

CSS Challenges for 200 IQ

Do you ever get that feeling when you’re working on a task, hit a wall with some problem, and something inside you whispers that there has to be a solution? When it seems like all is lost, like you’ve run into a fundamental limit of reality, but your refusal to accept it keeps driving you deeper into spec docs, 10-year-old GitHub threads, and articles from giants who’ve already blazed this trail and shared their findings? And then, after hours of intense brain-grinding, you add that final line of code, refresh the page, and there it is — the exact result you wanted, staring back at you from the screen? That rush of success is probably familiar to every engineer in some form or another. In those moments, I always want to share the win with my colleagues and, if it could help others, write an article about it. In this post, I’ve collected 3 such cases from our work where we came up with solutions that, as far as I know, are pretty unique and haven’t been fully documented before. I invite you to share in the joy of discovering a solution that seemed impossible! Fixed inside a Scroll Container For a warm-up, let’s take an easier task. One of my most popular CodePens is an example of a fixed block inside a scrolling container. People find it via Stack Overflow answers, so it’s an in-demand problem, so it might come in handy for you too. I’ve been working on an Angular component library called Taiga UI for many years. Everything I’ll talk about in this article comes from there, but that’s just the backstory. We won’t need Angular or any of its specifics here. We’re talking pure CSS. Our library uses a custom scrollbar. While modern browsers let you tweak its appearance a bit , for full control over behavior and visuals, we need to place our own elements inside the container to act as the scrollbar. But how do you do that when absolutely positioned elements fly to the top on scroll, and fixed-position ones are pinned to the viewport? Experienced devs will immediately think

2026-08-05 原文 →
AI 资讯

Audit Your AI Dev Tool's Data Boundary Before You Paste Real Code Into It

Last month I watched a teammate paste a stack trace into a hosted AI assistant. The trace contained an internal hostname, a database connection string, and a customer email. None of it was secret enough to trip a DLP rule, but all of it left our network through an endpoint nobody had audited. The failure wasn't the tool — it was that we had never written down which data classes are allowed to reach which inference endpoint , and we had no test that would fail when the boundary was crossed. This article builds that boundary as a reproducible fixture: a data-classification decision matrix, a canary-leak test you can run against any hosted or self-hosted model endpoint, and a prevent/detect/recover table. The fixture works whether your endpoint is a cloud API, a free hosted tier, or a GPU box under your desk. The invariant I1: A prompt containing data of classification level L may only egress to an endpoint whose trust level is explicitly approved for L . Everything below exists to make I1 testable in CI rather than aspirational in a wiki. Step 1: Write the decision matrix before touching any tool Data class Examples Free hosted model tier Self-hosted / VPC endpoint C0 – Public OSS code, docs, public CVEs ✅ Allowed ✅ Allowed C1 – Internal-generic Boilerplate, config shapes, anonymized traces ✅ Allowed with review ✅ Allowed C2 – Internal-sensitive Real hostnames, schemas, ticket content ❌ Not without a signed DPA + retention terms you've actually read ✅ Preferred C3 – Regulated/secrets Credentials, PII, customer data, keys ❌ Never ⚠️ Only with controls (see below) Two rules make this matrix enforceable: Default deny. If a data class isn't in the matrix, it's C3 until someone argues it down in writing. The matrix is code. Keep it as a YAML file in the repo so the fixture in Step 2 can assert against it. Free hosted tiers are genuinely useful for C0/C1 work — evaluating a framework, writing throwaway scripts, reproducing a public bug. That is where something like MonkeyCo

2026-08-05 原文 →
AI 资讯

GPT-6 Killed Prompt Engineering: Here’s What Running Infrastructure Looks Like in the Age of Agent Swarms

The GPT-6 news is doing the rounds and the framing is everywhere: prompt engineering is dead, the future is hierarchical memory and autonomous agent swarms. I mostly agree with the framing, but almost every take I've seen treats it as an AI story. It's not. For anyone who actually runs infrastructure, it's an operations story, and it's a slightly alarming one. Let me explain what changes on the ground, because the interesting part isn't the model, it's what a swarm of these things does to your cloud account. The part everyone got right: prompt engineering was always a workaround Prompt engineering was never a discipline. It was a coping mechanism for models that forgot everything between turns and couldn't reliably use tools. We wrote elaborate prompts because we had to hand-carry all the context in, every single time. Calling it "engineering" flattered it. So "the era of prompt engineering is over" is true, but for an unglamorous reason: the crutch is being removed. Hierarchical memory means the model retains structured state across sessions, it remembers your environment instead of being re-briefed on it hourly. When the model holds the context, the prompt shrinks to intent. That shift is real and it's been coming all year; every major cloud shipped managed agent memory in 2026. GPT-6 is a milestone on that curve, not a lightning bolt. The skill that replaces prompt engineering isn't a better prompt. It's context engineering , deciding what goes into that hierarchical memory, what's authoritative, what's stale, who's allowed to write to it. That's a data-governance problem wearing an AI hat, and infra teams are better positioned for it than prompt tinkerers ever were. The part that should worry you: swarms multiply your blast radius Here's where the ops reality diverges hard from the AI hype. "Autonomous agent swarms" sounds like a productivity feature. From an infrastructure-safety standpoint, it's a blast-radius multiplier , and I don't think that's priced into

2026-08-05 原文 →
AI 资讯

Designing a Reliable PDF Translation Job Pipeline in TypeScript

Uploading a PDF and calling a translation model looks like a two-step feature. In production, it is a job pipeline with untrusted input, two different extraction paths, several expensive stages, and an output that can be fluent while still being wrong. That distinction matters for a small SaaS team. The translation request may come from support, sales, or an internal operations task. Nobody wants to operate a document platform, but the workflow still needs to answer basic questions: Was the upload actually a PDF? Does the file contain selectable text or scanned page images? Can a retry create a second charge or a conflicting result? What happens when page 37 fails after the first 36 pages succeed? How do we know the translated PDF is not blank or visually broken? When are the source and result deleted? The translation model is one component. Reliability comes from the system around it. Define the Job Contract First I would not let a file reach an extractor until the API has established a narrow contract. For example, a translation request might include: type TranslationStyle = " general " | " technical " | " academic " ; interface CreateTranslationJob { uploadId : string ; sourceLanguage : string | " auto " ; targetLanguage : string ; style : TranslationStyle ; idempotencyKey : string ; containsRestrictedData : boolean ; } The request should be rejected when the source and target languages are identical, the upload is missing, the target language is unsupported, or policy says the document cannot leave an approved environment. File validation should also be explicit. Do not trust the filename or browser-supplied MIME type. Check at least: the actual byte size; the file signature; whether the parser can open the document; whether the PDF is encrypted; the page count; whether the job fits the account or product limit. A 20 MB limit is simple to explain in a user interface, but size alone is not a good predictor of work. A compressed 200-page text PDF can be smaller th

2026-08-05 原文 →
AI 资讯

Building an Editable 3D Indoor Map in the Browser

Indoor maps are often treated as a rendering problem: take a floor plan, extrude a few walls, and display the result. That is useful for a viewer, but it breaks down when a team needs to edit a real space, place assets, or hand the result to another application. We are building KiMap around a different boundary: turn a floor plan into an editable indoor scene in the browser, then keep the resulting structure useful for an SDK consumer. Why a floor plan is not enough A production indoor workflow needs more than a textured image on a plane. At minimum, the editor has to preserve the relationships between walls, floors, rooms, openings, and the objects placed in the space. Those relationships determine whether the result can later support navigation, facility workflows, a digital twin, or a custom web experience. That is why the current KiMap workflow starts with structure. You can define the indoor geometry, inspect it in 2D and 3D, and keep editing instead of committing to a static export too early. The browser editor boundary The editor is built with React and Three.js. The goal is not to replace every DCC tool. It is to make the early spatial workflow accessible to teams that need to test an indoor experience before investing in a full custom pipeline. The parts we are concentrating on are: editable floor-plan structure and bounded spaces 2D and 3D scene inspection in the same workflow reusable 3D furniture and local asset handling saving an indoor project without dropping the referenced model data a path toward SDK-oriented rendering and integration The last point matters. A scene that looks correct in an editor is not automatically useful to an application. We want the data boundary to be explicit enough that an SDK consumer can load the geometry and assets without rebuilding the scene from scratch. What we are testing next KiMap is in free early access. The most useful feedback is not generic interest; it is a concrete blocker from someone building an indoor-nav

2026-08-05 原文 →
AI 资讯

Episode 6 — Watching Something You Can't See

Week 3. "The deploy is done. Everything's green. Now what am I actually supposed to be looking at?" Previously Runner ↓ Cache ↓ Artifact ↓ Deployment Today ↓ Monitoring Junior Engineer: The canary rolled out fine yesterday. 100% traffic, all healthy. I closed my laptop. Was that wrong? Senior Engineer: Not wrong, exactly. But let me ask you something first. Your service is running on a server somewhere. Right now, this second — is it healthy? Junior Engineer: I mean... I assume so? Nobody's messaged me. Senior Engineer: "Nobody's messaged me" isn't an answer. It's the absence of one. That's the entire problem monitoring exists to solve. The Thing Nobody Says Out Loud Senior Engineer: Here's an uncomfortable fact about production systems: you cannot see them. Not directly. You're not standing next to the server, watching electricity move through it. Everything you know about whether it's healthy is a claim — something a piece of software told you, that you're choosing to trust. Junior Engineer: That sounds obvious when you say it, but I don't think I've ever actually thought about it that way. Senior Engineer: Most engineers don't, until the gap between "the system told me it's fine" and "the system is actually fine" bites them. Monitoring is the discipline of shrinking that gap — of making sure what you're told is close to what's actually true, and told to you fast enough to matter. 📒 Senior Engineer's Notebook You don't monitor a system because you don't trust it. You monitor it because you can't see it. Trust isn't the issue — visibility is. The Car Dashboard Analogy Junior Engineer: Can you make this concrete? Senior Engineer: Think about driving a car. You can't see the engine. You can't see the oil level, the coolant temperature, how much fuel is actually left in the tank, mid-drive. All of that is invisible to you, sealed inside metal, while you're doing 100 km/h. So the car gives you a dashboard. Speed, fuel, engine temperature, warning lights. You're not wat

2026-08-05 原文 →
开发者

What I learned reading ten EU company registers

I built a free tool that checks a supplier before you pay them. The part that took most of the work, and taught me most, was reading ten national company registers instead of relying on the EU's own VIES service. This is what I found out, mostly so the next person doesn't have to. The problem with "the VAT number is valid" VIES — the European Commission's VAT Information Exchange System — answers one question: is this VAT number currently registered. That sounds like the question you want answered. It isn't. A company that has gone into liquidation keeps a cleanly resolving VAT number in VIES. So does one that has been struck off the register. Deregistration and insolvency are run by different authorities on different timetables, and the gap between "this company has stopped being a going concern" and "the VAT number stops validating" can be months. So you can check a supplier, get a green tick, and be looking at an insolvency estate. The national registers know. VIES doesn't ask them. Ten registers, and what each actually gives you I found free, public, machine-readable-enough sources for ten countries: Bulgaria, Czechia, Estonia, Finland, France, Greece, Latvia, Poland, Romania and Slovenia. They are not equivalent, and this is the thing I'd have liked written down somewhere before I started: Six of them report company *state * — inactive, in liquidation, bankrupt, insolvent, terminated, ceased, struck off: Romania, Estonia, France, Greece, Bulgaria, Latvia. This is the valuable one. Three report whether the company is actually VAT-active — Poland, Romania, Slovenia. That matters more than it sounds, because VIES does not distinguish "this is a real company that isn't VAT-registered" from "this number belongs to nobody". The rest give you a name and not much more. Czechia, for instance, is in the ten but in neither of the other two groups. It confirms a name. That's it. Worth knowing before you build a feature around it. Poland is the interesting one Poland is the

2026-08-05 原文 →
AI 资讯

I Wanted to Hear Every Telnyx Voice in One Scene, So I Built a Multi-Character Narrator

Telnyx ships over 700 Ultra voices across 36 languages with sub-100ms time-to-first-byte. The voices are not the problem. Hearing them is. The docs list three. The Voices API returns 4,000+ across every provider. Voice pickers play a fixed sample sentence per voice. None of that tells you how a voice handles emotion, pacing, or character inside a real scene. So I built a small app that lets you do exactly that. You write a short scene with a few characters, assign each character a different Telnyx Ultra voice and an SSML emotion, and render the whole thing into one MP3. Every voice speaks in character, in context, in one continuous audio file. The Telnyx code example is: https://github.com/team-telnyx/telnyx-code-examples/tree/main/multi-character-narrator-python The Use Case Voice pickers exist. They play a fixed sample sentence per voice. What they do not do is let you hear a voice inside a real scene — a tense argument, a calm narrator, a panicked character, a reassuring guide — because a single sample sentence does not tell you how a voice handles emotion, pacing, or character. This example solves that. You write a short scene with a few characters. Each character gets a different Telnyx Ultra voice. Each character gets an SSML emotion. You hit render. The app fans out parallel TTS calls, stitches the per-line audio in script order, and plays you one continuous MP3 with every voice speaking in character. The default scene is the Ides of March from Julius Caesar. Five characters, ten lines, five distinct voices, five different emotions: Cassius — determined, plotting the assassination Caesar — surprised, realizing the betrayal Brutus — apologetic, justifying the act Mark Antony — angry, mourning the fallen leader Narrator — calm, setting the scene One render, one MP3, every voice in context. That is the demo. The Eight Curated Ultra Voices The app ships with eight pre-built Telnyx Ultra voices curated for the most common use cases. Each one is a real Telnyx voice

2026-08-05 原文 →
AI 资讯

Maintaining Foreground Services in the Era of Android Doze Mode

The Silent Disruptor The silence in the room was absolute, broken only by the rhythmic scraping of pens on paper during a high-stakes meeting. Then, it happened. My pocket erupted into a frantic, brassy ringtone that seemed to last an eternity before I could fumble to silence it. My face turned crimson as the room’s focus shifted from the presentation to my vibrating trouser pocket. I had remembered to check my calendar, but I had completely forgotten to toggle my phone to silent mode. That moment of pure, concentrated embarrassment was the catalyst for me building Muffle. The Friction of Manual Control We live in an age of automation, yet our phones—the very devices meant to assist us—remain stubbornly manual when it comes to basic social etiquette. Every day, millions of people walk into mosques for prayer, classrooms for lectures, or medical offices for consultations, and every day, a percentage of them forget to silence their devices. This isn't just a minor annoyance; it is a persistent source of social friction. Before I started building Muffle, I looked for existing solutions. Most apps were either bloated with unnecessary permissions, required invasive cloud accounts, or simply failed to trigger at the right time. The fundamental problem wasn't just the lack of features like GPS-based prayer times or calendar-specific automation; it was the lack of reliability. If an automation app fails once, the user loses trust in it forever. If I am in a meeting, I cannot afford for the app to 'sleep' because the system decided to save battery at the expense of my configured routine. I needed something that could handle these state changes consistently, regardless of whether the phone was in my pocket, sitting on a desk, or buried in a bag. Architecting for Reliability When I began writing the core logic for Muffle, I immediately hit the wall that every Android developer eventually faces: Doze Mode. Android’s aggressive power management is designed to preserve battery by

2026-08-05 原文 →
AI 资讯

Environment Variables the Safe Way

Environment Variables the Safe Way Environment variables are the standard way to configure applications without hardcoding secrets or environment-specific details. But they're easy to misuse. I've seen API keys committed to repos, configs that crash when a variable is missing, and defaults that silently override production settings. Here's how I handle them safely. Never Commit Secrets The most important rule: never put real secrets in your code or commit them to version control. That includes .env files. Add .env to your .gitignore immediately. If you're using a framework like Laravel or a tool like Vite, the default .env.example is your friend. Commit that, but never the real one. For local development, you can generate a .env from the example and fill in your own values. For production, set variables through your hosting provider's dashboard or a secrets manager like AWS Secrets Manager or HashiCorp Vault. Read Variables Explicitly Don't access process.env directly all over your codebase. Instead, centralize your configuration. Create a config.js (or config.ts ) that reads and validates all the variables you need. // config.js const required = [ ' DATABASE_URL ' , ' JWT_SECRET ' , ' PORT ' ]; const missing = required . filter ( key => ! process . env [ key ]); if ( missing . length ) { throw new Error ( `Missing required environment variables: ${ missing . join ( ' , ' )} ` ); } module . exports = { databaseUrl : process . env . DATABASE_URL , jwtSecret : process . env . JWT_SECRET , port : parseInt ( process . env . PORT , 10 ) || 3000 , }; Now your app imports config and uses config.port . This has several benefits: Fail fast: if a required variable is missing, the app crashes at startup, not later when you try to use it. Type safety: you can parse and validate values once. Easy to mock in tests. Use Defaults Carefully Defaults are convenient, but they can hide problems. For example, if you default PORT to 3000 in production, you might accidentally run on the w

2026-08-05 原文 →