AI 资讯
Chasing the Light: How the June Solstice Game Jam Turned One Prompt Into a Hundred Different Games
Every game jam lives or dies by its theme, and this year's June Solstice Game Jam handed developers something deceptively simple: the longest day of the year. What emerged from that single prompt wasn't a wave of near-identical sunrise simulators — it was a scattershot of genres, mechanics, and emotional registers, all orbiting the same core idea of light and time. One Theme, a Dozen Interpretations The solstice lends itself to more than one reading, and jam entrants leaned into that ambiguity. Some treated "longest day" literally, building puzzle games where a slowly arcing sun becomes a physical obstacle — light that reveals hidden platforms, burns away fog, or casts shadows players must dodge or exploit. Others went abstract, using the solstice as a metaphor for endurance, building narrative pieces about characters pushing through their hardest, brightest, most exhausting day. Sci-fi submissions reframed the concept entirely: distant planets with artificial suns, space stations timing their orbits to a 24-hour light cycle, or crews racing against a ship's failing life-support "day" before darkness means death. Meanwhile, a handful of more grounded, historically-minded entries used the solstice as a backdrop for ritual and tradition, drawing on centuries of human fascination with the year's turning point. Light and Time as Game Mechanics What makes this jam interesting from a design standpoint is how consistently teams turned an atmospheric theme into an actual mechanic rather than just window dressing. Light became a resource to manage, a weapon, a timer, or a stealth tool. Time compression and dilation showed up frequently too — some games squeezed an entire day-night cycle into a five-minute play session, forcing players to make fast decisions as shadows visibly crept across the map in real time. This is a common jam trick: constraints breed creativity. When a 48- or 72-hour deadline collides with a theme built around a literal clock, developers naturally start
AI 资讯
wa.me/username doesn't work yet — I verified it two ways
wa.me/username doesn't work yet — I verified it two ways, here's what to use instead If you've tried to build a "share my WhatsApp" link using a @username instead of a phone number, you've probably assumed wa.me/username (or wa.me/u/username ) works the same way wa.me/15551234567 does. It doesn't — at least not yet, as of writing this. I wanted a definitive answer instead of trusting blog posts or AI chatbot answers (more on that below), so I tested it two independent ways. Test 1: server response curl -I https://wa.me/u/some_real_reserved_username Every username path I tried — including a certified-real, currently-reserved username — 302-redirects to: api.whatsapp.com/resolve/?deeplink=...¬_found=1 Compare that to the phone-number path, which redirects to: api.whatsapp.com/send/?phone=...&type=phone_number Different resolver, different outcome. The server-side route for usernames exists, but every lookup currently resolves as "not found" — even for real, live usernames. Test 2: real device Server response alone doesn't rule out Universal Links / App Links intercepting the URL client-side before it ever hits a server — curl can't see that. So I also opened all three link variants ( wa.me/username , wa.me/u/username , and a redirect through my own domain) on a real phone with WhatsApp installed. None of them opened a chat. Why this matters if you're building anything around WhatsApp usernames WhatsApp has rolled out @username handles as a real, user-facing feature — but it hasn't published a public deep-link spec for opening a chat from one, the way it has for phone numbers for years. If you're building a tool, a profile page, a business card generator, anything that assumes wa.me/username "just works," it doesn't, for anyone. One more data point: I asked Meta AI directly about this, with the counter-evidence above in hand. It kept asserting the link already works and didn't engage with the evidence when pushed. That's a useful reminder that chatbot answers about
AI 资讯
Data structures your CS degree kind of glossed over
Hello, I'm Maneshwar. I'm building git-lrc, a Micro AI code reviewer that runs on every commit. It is free and source-available on Github. Star git-lrc to help devs discover the project. Do give it a try and share your feedback. Every CS program hammers the same seven into you. Arrays, linked lists, hash tables, stacks, queues, graphs, trees. You could probably recite their Big O complexities in your sleep at this point, and honestly, for 90% of the code you'll ever write, that's plenty. But every now and then a system hits a wall that none of the seven basics can handle gracefully, and someone had to invent a weirder tool to patch the gap. I went down a rabbit hole recently looking at a handful of these, and I liked them enough that I wanted to write them up properly instead of just leaving forty open tabs to rot. Fair warning, there is some depth here. Get a drink. When your hash table can't promise you a fast answer: Bloom filters Normal hash tables are great until you need to ask "have I possibly seen this before" across a dataset way too big to store in memory. Think a crawler checking billions of URLs, or a database deciding whether it's even worth going to disk to look for a row. A Bloom filter solves this by giving up on certainty in one direction. It's a fixed array of bits, plus a small handful of independent hash functions. Adding an item flips a handful of bits on. Checking for an item hashes it the same way and checks whether those same bits are on. If any single bit is off, that item was never added, full stop, no ambiguity. If they're all on, the item was probably added, but two unrelated items can accidentally light up the same bits, so you might get a false alarm. The asymmetry is the entire design. Zero false negatives, occasional false positives. It's the data structure equivalent of a metal detector at a stadium gate. It'll never wave through someone with a knife, but it might beep at your belt buckle and make you empty your pockets for nothing.
AI 资讯
👾 🧚🏼♀️Maximizing Fable for Life Admin
TLDR: The most powerful AI on the planet, only a few days of access. Maximize it. I'd first like to give credit where it's due: @trickell - Thank you for sharing Network Chuck's youtube video with me. The reference video is found here guys if you missed it: Network Chuck's Video on Fable I first started by creating a nice template for tech documentation for personal use. It created a beautiful piece of work in about 5 minutes - something I could easily expand on in the future. Here is what it generated for me with after a one or two careful prompts: Clean UI, Easy Navigation! Created this personal reference guide for studying for CCNA (Network Chucks Summer of CCNA) Wanna see it? It lives here: Techdocs But after learning about the true span of Fable's power, I started asking the serious questions, the ones that are life-changing. How can I increase my quality of life based on my resume, experience, and current life circumstances? I wrote about 2 pages of life issues that needed fixing - you know the stuff that slowly eats away at your soul, like student loan debt and people that are challenging to work with? Yes - I told it my biggest issues and instructed it to give me actionable plans that are free or low-cost. Even fable told me that this was a lot. 😅 Getting Organized Knowing the scope of my own problems I knew that my thoughts and processes had to be organized. Luckily for me, I remembered I had a good place to do that. A place that Fable could connect to and place documentation in place for me with checklists, notes, summaries and actionable plans. That app is called Notion, and some of you may have heard of it. No one is going to organize your life for you, no one, except for AI I couldn’t think of a better place for lightning fast critical life-admin documentation on the spot. And I can tell you, this integration works like a charm, and I highly recommend it. For a busy person with a million ideas, this is great. Anxiety Relief I had a tremendous amount of
AI 资讯
Is Your Unity Game's Physics a Hidden Bottleneck?
Is Your Unity Game's Physics a Hidden Bottleneck? Unlock CPU Power with Jobs and Burst Introduction It's 2026, and player expectations for high-fidelity, responsive game worlds have never been higher. Yet, for many Unity developers, the pursuit of complex physics, intricate AI, or large-scale simulations often runs headlong into a critical bottleneck: the main thread. If your Unity game still relies primarily on MonoBehaviour.Update() for computationally heavy tasks like custom collision detection, advanced pathfinding, or sophisticated flocking behaviors, you're inadvertently sacrificing precious frames and player experience. The sequential nature of Update() becomes a severe limitation, preventing your game from fully utilizing modern multi-core CPUs. The solution isn't just an optimization; it's a fundamental architectural shift. Unity's Jobs System and Burst Compiler are no longer esoteric tools reserved for DOTS (Data-Oriented Technology Stack) purists. They are immediate, essential allies for extracting raw, predictable, and highly performant power from your CPU cores. By embracing these systems, you can transform your game's performance, delivering unparalleled fluidity and scalability. Code Layout and Walkthrough: Embracing Parallelism The core problem with MonoBehaviour.Update() is that it executes serially on the main thread. While fine for simple per-frame logic, complex calculations involving many entities quickly become a single-threaded choke point. The Jobs System, coupled with the Burst Compiler, offers a robust alternative. 1. The Power Duo: Jobs System and Burst Compiler Jobs System: This framework allows you to break down heavy computations into small, independent units of work (Jobs) that can be scheduled to run in parallel across multiple CPU cores. It handles the complexities of thread management, allowing you to focus on the logic. Burst Compiler: This incredible technology takes your C# code written for Jobs and compiles it into highly optimi
产品设计
This Buried Apple Feature Turns an iPhone Into the Perfect Kids’ Dumb Phone
Apple built a tool for people with cognitive disabilities, but I accidentally discovered it’s also the best kids’ phone setup no one is talking about—not even Apple.
开发者
From 0 Likes to Meme Engineer
We have all been there. You are sitting at your desk late at night, your code is throwing errors that...
AI 资讯
How to Compress Images in the Browser with Canvas API (No Uploads, No Server)
How to Compress Images in the Browser with Canvas API Every image you upload to a "free" online compressor is sent to a server — often without you knowing what happens to it afterward. For a tool that processes your private photos, that's a terrible design. Here's how to build (or use) an image compressor that runs entirely in the browser using the HTML5 Canvas API. No uploads, no server costs, and unlimited file sizes. The Core Technique: Canvas toBlob() The key API is HTMLCanvasElement.toBlob() : js const canvas = document.createElement('canvas'); const ctx = canvas.getContext('2d'); const img = new Image(); img.onload = () => { canvas.width = img.naturalWidth; canvas.height = img.naturalHeight; ctx.drawImage(img, 0, 0); canvas.toBlob((blob) => { const url = URL.createObjectURL(blob); }, 'image/jpeg', 0.8); }; img.src = 'your-image.jpg'; The second parameter is the MIME type (image/jpeg, image/png, image/webp, image/avif). The third is quality (0–1). Step-Down Resizing for Large Images If you're compressing a 6000×4000 px photo, drawing it at full resolution onto a canvas can eat 70+ MB of memory. Step-down resizing halves the dimensions repeatedly: function stepDownEncode(img, maxDim, quality) { let w = img.naturalWidth; let h = img.naturalHeight; let src = img; while (w > maxDim * 2 || h > maxDim * 2) { w = Math.floor(w / 2); h = Math.floor(h / 2); const temp = document.createElement('canvas'); temp.width = w; temp.height = h; temp.getContext('2d').drawImage(src, 0, 0, w, h); src = temp; } const canvas = document.createElement('canvas'); canvas.width = w; canvas.height = h; canvas.getContext('2d').drawImage(src, 0, 0, w, h); return new Promise((resolve) => { canvas.toBlob((blob) => resolve(blob), 'image/jpeg', quality); }); } This prevents memory crashes and actually produces better quality (step-down preserves more detail than a single jump). Comparing Real-World Results Format Avg Original Avg Compressed Avg Savings JPEG → JPEG (Q80) 3.2 MB 0.8 MB 75% PNG → We
科技前沿
Scientists Have Identified a New Fossil Species of Axolotl in Mexico
Ambystoma quetzalcoatli is the first fossil salamander to be formally identified in Mexico, revealing that axolotls have inhabited the country for millions of years.
产品设计
A New Personal Best: What Six Months of Locking In Can Do
Table of Contents Setting a New Benchmark for Myself My Most Productive Six Months Yet 2...
产品设计
Qi fan fan
Despite my initial skepticism, I'm now sold on wireless Qi chargers that add integrated fans to keep your phone cool while charging. I figured they'd be too loud, or too weak, or too gimmicky, but I'm a convert after spending a week with the new $59.99 Kuxiu D5 Qi2.2 charging dock. Its active cooling system […]
AI 资讯
Bruno — API Client แบบ Git-Native ที่เก็บทุกอย่างเป็นไฟล์
Bruno — API Client แบบ Git-Native ที่เก็บทุกอย่างเป็นไฟล์ เวลา dev team ต้องเทส API — เครื่องมือที่ทุกคนนึกถึงคือ Postman กับ Insomnia แต่ปัญหาคลาสสิกที่เจอกันแทบทุกทีม: "Postman collection อยู่ไหน?" — "ใน account ผมไง" "ขอ invite หน่อย" — "เดี๋ยวส่ง link ให้... เอ๊ะ หมด free tier แล้ว" นี่คือ pain point ที่ทำให้คนจำนวนมากมองหาเครื่องมือใหม่ — และหนึ่งในนั้นคือ Bruno Bruno คืออะไร Bruno เป็น API client แบบ desktop app (มีทั้ง macOS, Linux, Windows) ที่มีแนวคิดแตกต่างจาก Postman โดยสิ้นเชิง: Postman Bruno เก็บข้อมูลที่ไหน Cloud account ไฟล์ใน project (Git repo) ต้อง login ไหม ✅ ต้อง ❌ ไม่ต้อง Collection format JSON (binary-ish) Plain text (Bru files) Collaborate ผ่าน Postman cloud ผ่าน Git (PR, diff, review) Open source ❌ ✅ (GitHub: 45K+ stars) Offline ไม่ค่อยได้ ✅ ทำงานออฟไลน์ได้เต็มที่ หัวใจของ Bruno คือ "API Client ไม่ใช่ Platform" — มันคือเครื่องมือธรรมดาที่เก็บข้อมูลเป็นไฟล์ — เหมือนที่ dev ทั่วไปเก็บโค้ด จุดเด่น 1. Collection คือไฟล์ — เก็บใน Git ได้ my-project/ ├── src/ ├── bruno/ │ ├── users/ │ │ ├── GET users.bru │ │ ├── POST create user.bru │ │ └── DELETE user.bru │ ├── auth/ │ │ └── POST login.bru │ └── bruno.json └── .git/ ทุก API request เป็นไฟล์ .bru — plain text — diff ได้, PR review ได้, merge ได้ — เหมือนโค้ด meta { name: GET users type: http seq: 1 } get { url: https://api.example.com/users body: none auth: bearer } 2. ไม่มี Cloud — ข้อมูลอยู่กับคุณ Bruno ไม่เคยส่งข้อมูลขึ้น server — ทุกอย่างอยู่บนเครื่องคุณ ทั้ง request, response, environment variables สำหรับทีมที่ทำงานกับข้อมูล sensitive (banking, healthcare, government) — ข้อนี้สำคัญมาก 3. ใช้ Git เป็น Collaboration Tool แทนที่จะ "invite teammate เข้า workspace" (แบบ Postman) — คุณแค่: git add bruno/ git commit -m "add user API collection" git push เพื่อน git pull → เปิด Bruno → เห็น collection เดียวกันทันที 4. Environment Variables — แบบเดียวกับที่ dev ใช้ # environments/production.bru vars { base_url : https : //api.production.com api_key : {{ PROD_API_KEY }} } เปลี่ยน environment ด้วยการคลิก —
AI 资讯
Why I Ditched Socket.IO for Raw WebSockets (And What I Learned)
When you google "how to build a chat app in Node.js," the very first result will almost certainly point you to Socket.IO. It is the de facto standard for a reason. When I started my project, I used it without a second thought. It worked like magic. But as I got deeper into the project, that magic started to feel more like a black box. I eventually ripped out Socket.IO and replaced it with raw, native WebSockets. It was a daunting decision, but having built and managed it myself, I have some strong opinions on what Socket.IO abstracts away, what I had to build from scratch, and whether the headache was actually worth it. The Magic of Socket.IO (And Why We Use It) To understand why walking away from Socket.IO is hard, you have to understand exactly how much heavy lifting it does for you behind the scenes. It isn't just a WebSocket library; it is a real-time framework. The Polling Fallback: Historically, if a user's corporate firewall blocked WebSockets, Socket.IO would seamlessly downgrade to HTTP long-polling. Automatic Reconnections: If a user drives through a tunnel and loses the connection, Socket.IO automatically handles the exponential backoff to reconnect them when they emerge. Rooms and Namespaces: It gives you a beautiful socket.to("room-1").emit() API for broadcasting messages to specific groups of users. Heartbeats: It manages ping/pong messages under the hood to ensure the connection hasn't silently died. When you drop Socket.IO, you lose all of this for free. So, Why Did I Walk Away? First, the fallback mechanism is largely a relic of the past. Today, native WebSocket support across modern browsers and network infrastructure is essentially ubiquitous. I didn't need to ship a massive client bundle just to support HTTP polling for the 0.1% of edge cases. Second, the lock-in is real. If you use Socket.IO on the client, you must use a Socket.IO server implementation. You can't just connect to a standard WebSocket server. I wanted the freedom to swap out my ba
AI 资讯
Your PDF tool is storing your files. Here's proof.
Upload a file to any random "free" PDF tool online. Then check their privacy policy. Most of them say something like: "We may retain uploaded files for up to 24 hours" or "Files may be used to improve our services" Your client's contract. Your salary slip. Your ID card. Sitting on someone's server. I got tired of this and built a tool where your files never leave your browser. No upload happens at all. 80+ tools, nothing stored, no account needed. Roast it, use it, or ignore it. Up to you.
AI 资讯
TypeScript Branded Types vs. Nominal Types: Which Pattern Should You Use in 2026
TypeScript Branded Types vs. Nominal Types: Which Pattern Should You Use in 2026 Most type safety failures in TypeScript stem from treating all strings as interchangeable. The structural type system that makes TypeScript flexible also creates subtle bugs when developers pass a UserId where a PostId was expected. Both are strings at runtime, and TypeScript's compiler sees them as compatible. This compatibility becomes expensive in production. When an engineer accidentally passes an email address to a function expecting a username, the compiler stays silent. The bug surfaces only when users report authentication failures or data corruption. Teams that rely purely on structural typing pay this cost repeatedly. Branded types solve this by adding phantom properties that exist only at compile time. They transform primitives into distinct types without runtime overhead. The pattern has matured significantly since 2023, and production codebases now demonstrate clear advantages over both structural typing and runtime validation alone. Key Takeaways Branded types prevent primitive type confusion at compile time with zero runtime cost The unique symbol pattern creates true nominal typing behavior in TypeScript's structural system Combining brands with validation functions provides both type safety and runtime guarantees Branded types excel for domain identifiers, measurements, and validated strings Choose branded types when preventing accidental type substitution matters more than implementation flexibility Understanding Branded Types: Adding Identity to Primitives Branded types attach compile-time metadata to primitives through intersection with phantom properties. A UserId becomes structurally distinct from a plain string even though both compile to identical JavaScript. The technique exploits TypeScript's structural typing: if two types have different shapes, the compiler treats them as incompatible. Adding a property that exists only in the type system creates this distinc
AI 资讯
I built a Telegram bot that counts calories from food photos. It confidently called soup "berry compote"
My wife tracks her meals, and I watched her type "buckwheat, boiled, 100 g" into a calorie app for the hundredth time. Search, scroll, pick the wrong entry, fix the grams. Every meal, every day. At some point it's easier to teach a vision model to look at the plate. So I built a Telegram bot. You send a photo of your food, it identifies the dishes, estimates portion weights, and replies with a card: calories, protein, fat, carbs. Text and voice work too ("2 eggs and a toast"). The borscht incident The first version was hilariously confident about wrong answers. Borscht — a red beet soup, if you've never met one — came back as "berry compote" (a sweet berry drink). Red liquid in a bowl, what else could it be? Adding more example dishes to the prompt made it worse : the model just got magnetized to whatever was on the list. A cod fillet became "syrniki" (cottage cheese pancakes) because syrniki were mentioned and both are pale and pan-fried. What actually fixed it was making the model read the serving context before naming anything: liquid served in a deep bowl with a spoon and sour cream is soup, not a drink. Flaky texture that separates in layers is fish, not pancakes. Fried items are never served floating in liquid. A short list of physical rules beat a long list of dishes. Portion estimation works the same way — the model reasons from plate size, cutlery, how full the bowl is. My wife has been checking its gram estimates against her kitchen scale for a week and it lands closer than either of us expected. Stack, briefly Python + aiogram, a vision LLM with structured JSON output (with a fallback parser for the days the model decides to wrap JSON in prose), Pillow for rendering the result cards. Photos are analyzed on the fly and never stored. Payments are Telegram Stars, so there's no app store, no signup, no card form — the whole onboarding is "send a photo". Yesterday I also wired up inline mode: type @SnapPlateBot in any chat, describe the food, and it counts rig
AI 资讯
I built an entire agency management platform by myself. Here's what actually happened.
I used to deliver food on Zepto. 14-15 hours a day. Sun, rain, didn't matter. I saved up, bought a laptop, and started doing video editing for clients. That's when things got messy. I was managing clients on WhatsApp. Tracking who paid me in Google Sheets. Sending invoices as PDF attachments that nobody opened. Every new client meant another chat group, another row in my spreadsheet, another folder I'd forget about. I went looking for one tool that could handle all of this. CRM, invoicing, projects, client communication — in one place. Everything was either $200+/month (when you add up all the separate tools) or missing basic stuff like a client portal. So I started building my own. That was a month ago. What I actually built Arpixa. One dashboard for agencies and freelancers. CRM, invoicing, project boards, AI assistant, file manager, scheduling, analytics, and a client portal where your clients can view projects, pay invoices, and message you. Every agency gets a branded subdomain — youragency.arpixa.io. Your clients see your brand, not mine. I'm not going to dump the whole feature list here. You can check arpixa.io if you're curious. The hard parts nobody warns you about Subdomains are a nightmare. Giving every user their own subdomain sounds simple until you realize auth doesn't work across subdomains by default. I had to build a token handoff system where you log in on one domain and the session gets securely passed to your workspace subdomain. It took longer than I expected going in — auth is the part everyone assumes is solved and nobody explains. Two payment gateways, because one isn't enough. I integrated both Stripe and Razorpay. Stripe for international users, Razorpay for India (UPI is how everyone pays here). The app auto-detects your country and shows the right payment flow. Sounds fancy — mostly it was just a lot of logic and twice the amount of webhook handling. Security rules will humble you. I wrote database-level security rules for every single co
AI 资讯
AI For Fun! Électrique Chats at Hack the Kitty, Built with Kiro.
A cat astrologer, spec-driven and running on Amazon Bedrock A companion to A Builder in Paris: Do Devs Dream of Électrique Chats? Last month I wrote about the idea. Six rainy days in Paris, a closed laptop, and a hackathon I did not mean to enter, and somewhere between the Musée de l'Orangerie and a lot of walking, an idea arrived. Cats are inscrutable. The people who love them are obsessed with understanding them anyway. Astrology is an old framework for making the unknowable feel readable, and maybe, just maybe, it helps us understand them a little. Her name is Madame Minou , a French cat astrologer who reads your cat's stars from a café terrace. That first article was the idea . This one is the build. Vibe-coded, but on rails Was it vibe-coded? You know it! AI wrote the lines, and I said "no, not like that" more times than I can count. But it was vibe-coding on rails, and the rails were Kiro. Before a single line of app code, I wrote the requirements in EARS notation, a design doc, and a build-ordered task list, all living in .kiro/specs . Decide what "done" means before letting anyone, human or model, start building. The specs are what kept the vibes on track. Then the steering files. .kiro/steering held the enduring rules of the project: product principles, security guardrails, technical direction, and UI law. These were the thing that kept a long, multi-session build from drifting. When a new session opened, the steering files were already the shared context. "The café blue" was one token, not five guesses. Security was not optional. The garbled café sign was a deliberate easter egg, not a bug to fix. From there, the loop: Kiro implemented one approved block at a time, ran each task's PASS/FAIL QA gate on itself before moving to the next, and only stopped for my review on the two things that actually mattered. I directed and approved. Kiro proposed and built. Spec first, block by block, human in the loop. The facts are sacred Here is the part that looks like a
AI 资讯
Building Instant Translation Assistance for Book Translations with Python and LLMs
How we integrated real-time phrase translation feedback into our AI-powered book translation workflow, and what we learned about latency, context, and prompt engineering. When we launched LectuLibre, our AI-powered book translation platform, users loved the quality of full-chapter translations. But they kept asking for something else: while reading a partially translated book, they'd stumble on an untranslated phrase or an awkward auto-translation and want to quickly get a better version without leaving the page. So we built 即时翻译求助 (Instant Translation Help)—a feature that lets readers highlight any phrase and get a context-aware, human-quality translation within seconds, along with a brief explanation of tricky parts. Here's how we built it, the technical challenges we faced, and the lessons we learned about stitching LLMs into a real-time reading experience. Problem: Real-time, Context-Aware Translation Inside a Book Most web apps offer generic translation via API calls—send a sentence to Google Translate, get a result. But that doesn't work for literary texts. A phrase like "She let the cat out of the bag" needs to be translated idiomatically, and the appropriate rendering depends heavily on the surrounding paragraphs (is the tone formal? sarcastic? part of a metaphor chain?). Our existing translation pipeline processes entire chapters in bulk with carefully crafted prompts, but for instant help, we needed sub-second latency while preserving that same depth of context. Our Approach: Server‑Sent Events and a Smart Prompt Buffer We chose Server-Sent Events (SSE) over WebSockets because the communication is one-directional (server pushes translation tokens) and SSE is simpler to implement with FastAPI. The client (a React app) sends a POST request with: The phrase to translate The book ID and the exact location (chapter/paragraph index) The target language Our backend retrieves the surrounding text from PostgreSQL (we store the original book in chunks), feeds a care
AI 资讯
# What Happens When You Try to Build a Lawyer for Someone Who Can't Afford One?
The Problem That Wouldn't Leave Me Alone Pakistan has 220 million people. A functioning legal system. Hundreds of Acts, ordinances, and constitutional provisions that technically protect every citizen. Almost nobody can use them. The median lawyer's consultation fee in Karachi is more than what many families earn in a week. Legal aid is understaffed and geographically concentrated in major cities. And the laws themselves? Written in English — a language most of the population reads functionally at best, and doesn't speak at home at all. So when a landlord illegally locks someone out. When a factory worker gets fired without severance. When a woman wants to know her inheritance rights. When a tenant needs to understand what "Section 16 of the Rent Restriction Ordinance" actually means for their specific situation — they either find a lawyer they can't afford, ask someone who doesn't really know, or quietly give up. This isn't a knowledge problem. It's an access problem. I'm a CS student at Sukkur IBA University in interior Sindh — not Karachi, not Islamabad. The kind of city where you feel the gap between what the law says and what people actually know it says every single day. That gap is where HAQ started. HAQ is an Arabic and Urdu word. It means right — as in, what is rightfully yours. The name felt important. The Core Idea: Ask the Law, Get the Law There's a specific failure mode with AI and legal questions that drove every design decision I made, and it's worth naming clearly. Standard LLMs — any of them — will answer legal questions confidently. They'll cite "Section 144" or "the Transfer of Property Act" with total authority. They are often wrong. Sometimes subtly: the section exists but doesn't say what the model claims. Sometimes obviously: the Act doesn't apply in that province. Always uncitable: the user has no way to verify without finding the source themselves. For an accessibility tool, a confidently wrong answer isn't neutral. It's actively dangerous.