Celebrating 10,000 Total Views on DEV! 🥳 Let’s Check the Stats 😸
Hoi hoi! I'm @nyaomaru, a frontend engineer who recently watched a flock of geese march through...
找到 12189 篇相关文章
Hoi hoi! I'm @nyaomaru, a frontend engineer who recently watched a flock of geese march through...
Local semantic search for AI agents Discussion | Link
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
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
Seedance 2.5's API opens on August 7. ByteDance published the pricing ahead of it, and there is a detail in there that will quietly break your cost model if you carry it over from 2.0. Video is quoted per second and metered per token: tokens = (input_video_seconds + output_seconds) × width × height × fps / 1024 fps is fixed at 24. Multiply by the per-million-token rate and that is the bill. The published rates USD per million tokens: Model No video input With video input Seedance 2.5 (480p, 720p) 10.70 6.40 Seedance 2.0 (480p, 720p) 7.00 4.30 Seedance 2.0 (1080p) 7.70 4.70 Seedance 2.0 (4K) 4.00 2.40 2.5 costs 52.9% more per token without video input and 48.8% more with it. Only 480p and 720p are published for 2.5. No 1080p, no 4K, and offline inference reads "not supported yet". Look at the 4K row before you move on. It is the cheapest tier per token, 43% below 480p, and it is also the most expensive output on the board, because a 3840×2160 frame carries 19.4 times the pixels of what 480p actually renders. The rate drops 43% while the token count climbs 1940%. Comparing providers by scanning the rate column gets you the wrong answer by roughly a factor of eleven. The 480p frame changed and nobody said so This is not in any release note. It falls out of dividing ByteDance's own worked examples by their own token rates. Their published five-second, 16:9, no-reference examples: Model 480p 720p Seedance 2.5 $0.514 ($0.103/s) $1.156 ($0.231/s) Seedance 2.0 $0.352 ($0.070/s) $0.756 ($0.151/s) Divide price by token rate to recover the token count, then by 24/1024 to recover pixels: const tokens = pricePerVideo / ( ratePerMillion / 1 e6 ); const pixels = ( tokens / outputSeconds ) * ( 1024 / 24 ); // Seedance 2.5, 480p: 0.514 / (10.70/1e6) / 5 = 9,607 tokens/sec // 9,607 * 1024/24 = 409,899 px -> ~854 x 480 // Seedance 2.0, 480p: 0.352 / (7.00/1e6) / 5 = 10,057 tokens/sec // 10,057 * 1024/24 = 429,105 px -> ~873 x 491 720p resolves to 21,600 tokens per second on both versi
Search "best project management software for startups" and you get the same dozen names every time: Trello, Asana, ClickUp, Notion, Linear, monday.com, Basecamp. Ranking them by feature count tells you almost nothing, because they are not really competing for the same job. The useful question for a startup is not which tool has the most features. It is two narrower ones: does your work run through engineering or through the whole company, and does per-seat pricing or flat-rate pricing fit a headcount that is about to change? Answer those and the shortlist collapses to two or three. The split that actually decides it Two forks matter more than any side-by-side feature grid. The first is who the tool is built for. Issue trackers like Linear are built around the engineering workflow (issues, cycles, a keyboard-first interface) and feel wrong the moment a marketer or a founder tries to run a launch plan in them. General work tools like Asana, ClickUp, monday.com and Trello are built for any team, which makes them flexible but also less opinionated about how software actually ships. The second fork is the shape of the bill. Almost everything in this category charges per seat per month, so the cost scales directly with hiring. A small number, Basecamp most notably, offer a flat rate that does not. For a company planning to double headcount inside a year, that difference can outweigh any feature comparison. If your team is mostly engineers For an engineering-led startup, an issue tracker usually beats a general project tool. Linear's free plan includes unlimited members, two teams and up to 250 issues, which is enough to run a small product team before paying anything; its Basic plan is $10 per user per month billed yearly and lifts the cap to unlimited issues and five teams. The trade-off is scope: Linear is deliberately narrow, so non-engineering work does not fit it well. The larger, more familiar alternative is Jira, which startup roundups still name as the default for
If you've experimented with AI-driven testing, you've probably lived this cycle: you ask an AI agent to "test the checkout flow," and it does something — clicks around, declares success, and leaves you unsure what was actually verified. The next day you ask again and it does something different. The browser automation works; the testing discipline is missing. That gap is what Snagly is for. Rather than describe it, I pointed it at softwaretestingtrends.com — my own production site, nothing fixed beforehand — and recorded the whole thing. It found eleven issues, including a critical accessibility bug on my own signup page. One of its findings turned out to be wrong, and I'll come back to that, because it matters more than the ones it got right. 📺 Watch the full walkthrough — installed from an empty folder, run against production, ~20 minutes. What it is Snagly is a free, MIT-licensed set of 30 skills for AI coding agents — GitHub Copilot , Claude Code , Cursor, Codex and 70+ others — that turn "an AI that can drive a browser" into "an AI that tests like a QA professional." A skill, if you haven't met them yet, is a reusable instruction set that teaches the agent a specific working method — when to use it, what rigor it requires, what evidence to capture, and what it must never do. Each skill in Snagly has one job, and they hand off to each other the way a real testing practice does: start-testing is the front door — say "what can you test here?" and it routes you to the right skill, checking prerequisites before handing off. Discovery & strategy : scenario-mapper explores your site and produces a prioritized list of test scenarios; test-case-writer expands any of them into a reviewable spec; test-plan sets strategy, cadence, and release exit criteria; qa-onboarding writes the guide for your next hire. Execution : flow-runner drives real user journeys step by step, asserting outcomes (not just that clicks happened) and capturing evidence the moment anything fails. cru
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
Four days after I published a piece arguing LLMs can't make the jump, OpenAI announced that an...
A slow AI feature does not feel smart. It feels broken. That is the uncomfortable truth many AI SaaS builders hit after the demo works. The prototype answers well, the agent can call tools, and the RAG pipeline looks impressive. Then real users arrive. Prompts get longer. Queues form. Streaming starts late. One tenant uploads huge documents. Another runs bulk jobs at noon. Suddenly the same workflow that felt magical in testing feels like a spinner with an invoice attached. The fix is not simply “use a faster model.” You need an LLM latency budget : a small set of rules that says how fast each AI workflow must feel, how many tokens it can spend, when to stream, when to cache, when to route to another model, and when to stop before cost and latency drift together. This guide is for solo SaaS developers, micro SaaS builders, and AI SaaS teams shipping production features with LLM APIs, RAG, agents, or self-hosted models. Why latency budgets matter now AI platform news points in the same direction: builders are moving from chat demos to production workflows. Agent tools, web context APIs, voice agents, coding assistants, and RAG platforms are all getting more capable. At the same time, inference cost and reliability are under pressure. Latency is now a product metric. Inference efficiency is becoming a business metric. Yet many articles stop at TTFT, TPOT, quantization, batching, or model serving. Fewer show how a SaaS builder turns those ideas into a product-level budget with code, dashboards, fallbacks, and customer-safe limits. The simple model: TTFT, TPOT, and total time You do not need a PhD in serving systems to start. Track three numbers. Time to First Token Time to First Token (TTFT) is the delay between the user action and the first streamed token. It includes network time, queue time, provider overhead, tool setup, retrieval, and the model’s prefill phase. High TTFT is why a chat box feels dead. Time Per Output Token Time Per Output Token (TPOT) is the averag
Use multimodal chat with a strict JSON schema when your policy needs explainable labels for uploaded images; otherwise reach for a managed, fixed-taxonomy service. There is no dedicated image moderation endpoint here, so the practical design is a policy prompt, a vision-capable chat model, schema validation, and a conservative fallback. That is my short answer. I would not ship the model's prose directly into an allow/block decision. I keep the original decision for audits, translate it into a small internal status, and make the eval set the release gate. The model is one component of the policy system — not the policy system itself. What should a Python image upload moderation example classify for NSFW and violence? The categories should come from the app's actual rules. For a general user-content product, I start with nudity, graphic violence, hate symbols, drugs, and minors-risk. I don't pretend those labels are universal: a medical forum and a marketplace need different thresholds, and a historical archive may legitimately show symbols that a profile-photo product should reject. My first notebook pass is deliberately boring. I assemble a small set of allowed, blocked, and ambiguous pictures; write the expected category labels; and record the policy reason in plain English. Then I run the same prompt and schema across every candidate model. The score I care about first is false negatives on the block set, followed by false positives on harmless uploads. Overall accuracy can hide both. This is also where a JSON schema earns its keep. A response containing "graphic_violence": "high" can be validated, stored, and compared. A paragraph such as “this appears concerning” can't reliably drive a queue or an appeal. Keep the provider response beside a normalized status such as allow , review , or block ; when policy changes, you can replay the raw decisions without migrating every old record. I learned the cost side the annoying way: one evaluation run consumed 18.7 milli
Looking for Contributors to Build Zentrail IDE — An AI-Native Open Source Desktop IDE Hello everyone! 👋 I'm building Zentrail IDE , an open-source, AI-native desktop IDE designed for the next generation of software development. The goal isn't to build another code editor. The goal is to create an IDE where multiple AI agents can collaborate with developers in a single workspace to plan, write, review, test, and manage code. We're still in the early architecture and planning phase, and I'm looking for developers, designers, and AI enthusiasts who want to help build it from the ground up. 🎯 Project Vision Create an AI-first development environment that combines: 🧠 Multi-Agent Collaboration 💻 Native Desktop Performance 🤖 AI CLI Integration 📦 Plugin & Skill Ecosystem 🌍 Open Source Community ⚡ Modern Developer Experience ✨ Planned Features Workspace System Multi-project workspaces Workspace memory Persistent sessions Task management AI Workspace Agents Multiple AI agents running simultaneously Shared workspace memory Parallel task execution Intelligent task orchestration AI CLI Support Claude Code Gemini CLI OpenAI-compatible providers Local AI models Custom AI CLIs Git Automation AI-assisted commits Pull requests Code reviews Branch management Repository insights Skill System Install reusable AI workflows with a single command. Examples: Security Review Code Refactoring API Generator Documentation Writer Test Generator Plugin SDK A modular extension system for adding custom functionality without modifying the core IDE. 🛠 Tech Stack Frontend TypeScript React Tauri v2 Monaco Editor Tailwind CSS Backend Go gRPC WebSocket AI Runtime Python MCP LangGraph Database SQLite 🤝 We're Looking For We're looking for contributors interested in: Frontend React TypeScript UI/UX Monaco Editor Backend Go gRPC WebSocket Performance optimization AI Python MCP Agent orchestration Prompt engineering Desktop Tauri Windows development Cross-platform architecture Design UI/UX Design Icons Develo
Firstly the whole conversation: https://share.gemini.google/NmMAhtBdsbtJ The TLDR (for ~100 head dept) 2 Pizza teams (8-10) turn into Domain teams (2-3) for a 75% reduction as roles vanish or merge. A 75% reduction in eng department head does not alter the departments Capacity. This is the 1x outcome. Staying at 100 gives 5-10x capacity. No change is ~$16m 25 heads in Domain is ~$5m (big saving!) with big workload lump on that 25, capacity probably drops 100 heads in Domains is $26m (costs went up!) with no backlog or idea left behind. org becomes hyper efficient and productive. operating costs drop, revenue climbs. Believable, or not? submitted by /u/Lower-Impression-121 [link] [留言]
Protocols let you define what a type can do without caring about what it actually is. Once...
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
Is your snoring just a nuisance, or is it a health warning? Obstructive Sleep Apnea (OSA) affects nearly 1 billion people worldwide, yet most remain undiagnosed due to the high cost of clinical polysomnography. Today, we are pushing the boundaries of AI Healthcare by repurposing OpenAI Whisper from a speech-to-text powerhouse into a clinical screening tool. In this tutorial, we will explore how to leverage Audio Signal Processing , Hugging Face Transformers , and Librosa to detect breathing patterns. By fine-tuning Whisper on non-speech acoustic events, we can transform a standard smartphone recording into a high-precision OSA screening device. Pro-Tip : If you're looking for more production-ready examples and advanced architectural patterns for AI-driven health monitoring, be sure to check out the deep-dives over at WellAlly Tech Blog . The Architecture: From Raw Audio to Clinical Insight To build an OSA screening algorithm, we don't just need to hear the sounds; we need to understand the rhythm and absence of sound. We use Whisper's robust encoder to capture the spectral features and a custom classification head to identify Apnea-Hypopnea events. graph TD A[Raw Sleep Audio .wav] --> B[Preprocessing: Librosa] B --> C[Noise Reduction & VAD] C --> D[Segmenting: 30s Windows] D --> E[OpenAI Whisper Encoder] E --> F{Event Classification} F -->|Normal| G[Healthy Breathing] F -->|Snore| H[Snore Phase Analysis] F -->|Silence/Choke| I[Apnea Event Detected] I --> J[AHI Index Calculation] J --> K[Final OSA Risk Report] Prerequisites To follow this advanced guide, you'll need: Tech Stack : Python 3.9+, transformers , librosa , torch , and evaluate . Dataset : Ideally, the UCD Snore Database or similar PSG-synchronized audio data. Step 1: Audio Preprocessing with Librosa Before feeding audio into Whisper, we need to clean the signal. Sleep environments are noisy (fans, traffic, etc.). We use librosa to normalize the audio and detect "Voice" (or in our case, Breath) Activity. im
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
submitted by /u/IamMichaelSalim [link] [留言]
This article is an English translation of the original Japanese article. In my club management app, I use the following invite URL for both web and iOS app: https://squad-note.com/invite/{orgId} If the app is installed, Expo Router opens the invite screen in the app. If not, the web page displays. Using Universal Links lets me share a single URL rather than splitting it into web and app versions. Expo Router File Structure I place the invite screen as a dynamic route. apps/mobile/src/app/invite/[orgId]/index.tsx The screen retrieves the orgId from the URL via useLocalSearchParams . import { useLocalSearchParams , useRouter } from " expo-router " ; export default function InviteScreen () { const { orgId } = useLocalSearchParams < { orgId : string } > (); const router = useRouter (); const { data : org , isLoading } = api . organization . getPublic . useQuery ( { id : orgId ! }, { enabled : !! orgId }, ); // Display invite content and execute join process } When opened with /invite/abc , orgId receives abc . I also provide a page with the same path on the web side. Setting a Custom Scheme To handle app-specific URLs, I set a scheme in the Expo config. export default ({ config }: ConfigContext ): ExpoConfig => ({ ... config , scheme : " squadnote " , }); This allows handling URLs like the following during development and authentication callbacks: squadnote://invite/abc However, I use HTTPS for the invite URLs shared with users. Because custom schemes can be declared by different apps with the same scheme, I use Universal Links as the entry point to securely associate normal web URLs with the app. iOS Associated Domains In app.config.ts , I separate domains for production and development. ios : { bundleIdentifier : IS_PROD ? " com.squadnote.app " : " com.squadnote.app.dev " , associatedDomains : IS_PROD ? [ " applinks:squad-note.com " ] : [ " applinks:dev.squad-note.com " ], } Adding the configuration alone does not make it work. I also serve apple-app-site-association
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