AI 资讯
Designing Idempotent Decision Endpoints That Survive Real Retries
Retries are normal in distributed systems. A caller may time out after the server commits a decision, a queue may redeliver a message, or a webhook sender may repeat an event. A decision API that treats every request as new can double-charge, duplicate actions, or record conflicting outcomes. Give each business operation a stable key The idempotency key should identify the logical business request, not a network attempt. Store it with a normalized request fingerprint, processing state, outcome, rule version, and response. If the same key arrives with a different payload, reject it rather than returning an unrelated prior result. Handle concurrent duplicates atomically Two workers can receive the same key before either writes a result. Use a unique constraint, transaction, or compare-and-set operation so only one execution owns the request. Other attempts should wait, return an in-progress response, or read the completed outcome according to the API contract. Choose retention from business risk A short cache may stop immediate duplicates but fail when a delayed queue redelivers. A permanent record may create unnecessary storage or privacy burden. Document key expiry and what happens if a key is reused after that boundary. Put side effects behind the idempotent boundary If rule evaluation triggers a message or database write, use a transactional outbox or equivalent pattern so the decision and pending event are committed together. Consumers still need their own deduplication because downstream delivery is often at least once. Return decision provenance Include the decision ID, status, rule artifact version, timestamp, and whether the response was replayed. Do not regenerate a result under a newer rule version for a duplicate key unless the caller explicitly requests a new business operation. Test the failure modes, not only the happy path Cover concurrent duplicates, payload mismatch, worker crash after commit, delayed redelivery, key expiry, and downstream retry. Obs
AI 资讯
Laravel Development Process: From Idea to Production
Building a Laravel application involves much more than writing PHP code. A production application needs to solve a real business problem, handle users and data reliably, survive deployments, remain secure, and continue to be maintainable as requirements change. Laravel provides an excellent foundation for building modern web applications, but the framework is only one part of the development process. A successful Laravel project typically moves through several stages, from understanding the original business idea to deploying, monitoring, and improving the application in production. Here is what that process looks like. 1. Start With the Business Problem Before thinking about controllers, models, databases, or cloud infrastructure, the first step is understanding what the application actually needs to accomplish. A project might begin with a simple request: "We need a customer portal." That's a starting point, but it isn't a specification. What should customers be able to do? Create and manage accounts? Upload documents? Manage subscriptions? Make payments? View reports? Communicate with employees? Receive notifications? Manage multiple users within an organization? These questions start turning an idea into actual application requirements. One of the easiest ways for a software project to become unnecessarily expensive is to begin development before the problem has been clearly defined. Laravel can make development faster, but building the wrong application faster doesn't solve the underlying problem. 2. Define the MVP Once the requirements become clearer, the next step is determining what belongs in the first release. I generally separate features into two categories: What does the application need in order to provide value? and What can be added later? The first category becomes the Minimum Viable Product, or MVP. For example, a new SaaS application might initially require: User registration Authentication Account management Subscription billing The application's
AI 资讯
sample
What is a Media Query? A media query is basically a condition in CSS. You tell the browser: IF the screen satisfies this condition, THEN apply these CSS rules. For example: @media (min-width: 768px) { .container { display: flex; } } Meaning: "If the viewport is at least 768px wide, make .container a flex container." So think: IF condition is TRUE ↓ apply these CSS rules 2. Why do we need Media Queries? Because users don't have one fixed screen. Your website could be opened on: 📱 Phone 375px wide 📱 Large phone 430px wide 📱 Tablet 768px wide 💻 Laptop 1366px wide 🖥️ Desktop 1920px wide You don't want to create five completely different websites. Instead: ONE HTML + BASE CSS + MEDIA QUERIES ↓ Responsive website 3. What does "Responsive" mean? Responsive means: The website adapts its layout and appearance according to the available screen/device size. `For example: Mobile [ Card ] [ Card ] [ Card ] [ Card ] but on desktop: [ Card ][ Card ][ Card ][ Card ]` Same HTML. CSS changes the layout. 4. The basic Media Query syntax The basic structure is: ``` @media media-type AND (condition) { /* CSS rules */ } For example: @media screen and (max-width: 600px) { body { background: lightblue; } } There are three important pieces: @media ↓ screen ↓ and ↓ (max-width: 600px) ↓ { CSS } Let's understand each one. 5. What is @media? @media tells CSS: "I'm about to write a media query." Example: @media (...) { } It's an at-rule in CSS. Similar CSS at-rules you'll eventually see: @media @import @font-face @keyframes For now, just remember: @media = start a media query 6. What are Media Types? You mentioned: screen / speech etc. YES. 👍 A media type tells CSS what kind of output/device the document is being presented on. Common media types include: screen For screens. Examples: 📱 Smartphone 📱 Tablet 💻 Laptop 🖥️ Desktop Example: @media screen and (max-width: 600px) { ... } print For printed documents / print preview. For example, your webpage looks like: Website [Header] [Navigation] [Button
AI 资讯
The iOS Safari keyboard scroll bug, fixed with one line of CSS
If you build a full-screen mobile editor as a position: fixed overlay with a fixed toolbar on top and a nav bar on the bottom , iOS Safari will happily scroll your entire chrome off-screen the moment the soft keyboard opens — but only when the content is short . The fix isn't a JavaScript viewport dance. It's one line: .editor .ProseMirror { padding-bottom : 60vh ; } Give the inner scroll container something to scroll , and iOS keeps the scroll inside it instead of falling back to scrolling the document (which drags your "fixed" elements along). No html / body locking required. I hit this while building the mobile editor for PenPage , a local-first WYSIWYG markdown notes app (React + TipTap/ProseMirror). Everything below is verified on a real iOS device. The setup Picture a mobile note editor that takes over the whole screen: ┌──────────────────────────┐ │ Toolbar (absolute,top) │ ← stays put ├──────────────────────────┤ │ │ │ Editable content │ ← scrolls │ (overflow-y: auto) │ │ │ ├──────────────────────────┤ │ Nav bar (absolute,bottom)│ ← stays put └──────────────────────────┘ The outer container is position: fixed; inset: 0 . The toolbar and nav bar are position: absolute inside it. The middle is the only thing that scrolls. Standard app-shell layout. Works great on desktop and Android. The symptom Tap into the editor, the iOS keyboard slides up, and: Long document (taller than the viewport): perfect. The content scrolls under the keyboard, the toolbar and nav bar stay nailed in place. Short document (shorter than the viewport): broken. Trying to scroll drags the whole screen — toolbar and nav bar included — as if the entire fixed overlay were a normal scrolling page. That "only when short" detail is the whole story. The root cause This is the long tail of WebKit bug #191204 : when the soft keyboard appears, iOS Safari's layout viewport gets shorter than the visual viewport , and the document itself becomes scrollable by the keyboard's height. Worse, in that stat
AI 资讯
DASTAN The Taste of Home Every culture has a taste of home.
DASTAN — The Taste of Home 🍲 This is my submission for the Frontend Challenge – Comfort Food Edition, Perfect Landing. What I Built For this challenge, I wanted to create something that felt more like a story than a typical food website. That idea became DASTAN — The Taste of Home . “Dastan” means a story, and the concept behind the project is simple: food is rarely just food. A dish can remind us of a person, a place, a family gathering, or a moment we haven't thought about in years. DASTAN is a visual, editorial-style landing page that explores comfort food from different parts of the world through photography, cultural stories, ingredients, and the people behind the memories. The goal was to make the experience feel warm, premium, and personal from the moment someone opens the page. The Idea The line that shaped the whole design was: Every culture has a taste of home. I wanted the website to communicate that feeling without relying on a traditional recipe-blog layout. Instead, I treated each dish almost like a magazine story. You can discover dishes from different regions, read the story behind them, and explore how food connects people across cultures. The Design I went for an editorial-inspired visual direction rather than a conventional modern dashboard. The design uses: Warm cream backgrounds Deep charcoal sections Muted gold accents Large serif typography Editorial-style food photography Rounded cards Generous spacing Strong visual hierarchy Story-focused content Subtle borders and details I wanted the interface to feel like opening a beautifully designed food magazine. At the same time, I made sure the experience remains comfortable to use on smaller screens. What You'll Find 🌍 Global Comfort Food DASTAN brings together dishes and stories from different parts of the world. Examples include: Tonkotsu Ramen — Japan Hyderabadi Dum Biryani — India Kimchi Jjigae — Korea Lasagna alla Bolognese — Italy Lahori Chicken Karahi — Pakistan Each one is presented as more
AI 资讯
TypeScript 6.0 `--noPropertyAccessFromIndexSignature`: The Flag That Forces Honest API Contracts
TypeScript 6.0 --noPropertyAccessFromIndexSignature : The Flag That Forces Honest API Contracts This article was written with the assistance of AI, under human supervision and review. The Silent Type Hole in Your Codebase Most runtime property access errors stem from index signatures pretending to guarantee properties they don't. Teams define Record<string, T> or { [key: string]: T } for objects where specific properties might not exist, then access those properties with dot notation as if the type system proved their presence. The compiler stays silent. Production crashes follow when the property is undefined. The --noPropertyAccessFromIndexSignature flag eliminates this false confidence. When enabled, TypeScript prohibits dot notation for properties defined only through index signatures. The type system forces bracket notation instead, making the uncertainty explicit at every call site. This distinction is critical—it transforms implicit runtime failures into compile-time enforcement of honest contracts. When developers adopt this flag, the contract becomes explicit. Index signatures signal "this property might not exist" and the syntax enforces that uncertainty. Explicit properties signal "this property is guaranteed" and dot notation confirms the guarantee. The codebase gains honesty. Key Takeaways The --noPropertyAccessFromIndexSignature flag prevents dot notation on properties defined only through index signatures, forcing bracket notation that signals uncertainty. Index signatures ( [key: string]: T ) describe unknown property sets; explicit properties describe guaranteed contracts—the flag enforces this semantic difference. Enabling this flag exposes implicit runtime failures as compile errors, converting production crashes into immediate feedback during development. The migration path involves converting dot access to bracket notation for index-signature properties while keeping dot notation for explicit properties. Combining this flag with --noUncheckedInd
开发者
The ACF Block.json Migration Matrix Nobody Published
Search "acf_register_block_type to block.json mapping" and you get tutorials. Each one converts a single testimonial block and calls it done. None of them hand you the full key-by-key table: every legacy PHP argument, its block.json destination, and the handful of settings that have no destination at all. I migrated forty-plus blocks across two client themes this year. Some keys moved with zero friction. Others sat in gray areas I only resolved by testing in the block editor and watching what broke. This is the matrix I wish existed before I started. Why the gap exists ACF's own documentation covers acf_register_block_type() on one page and the block.json acf key on another. Both pages are accurate. Neither cross-references the other. A developer migrating a block has to hold both pages open and manually match render_template to renderTemplate , post_types to postTypes , and so on. Miss one, and a block silently loses a feature instead of throwing an error. Three categories of keys make this worse: Renamed keys. Same feature, different casing, different location. snake_case becomes camelCase , and the key moves from the flat settings array into a nested acf object. Relocated keys. Some legacy settings aren't ACF-specific at all. They belong to WordPress's core block registration and move to the top level of block.json, outside the acf object entirely. Orphaned keys. A few legacy settings have no documented block.json equivalent. You either drop the behavior, replicate it with WordPress's native supports API, or handle it in your render template instead. The full matrix Legacy acf_register_block_type() key block.json location Notes name Top-level name Must be namespaced, e.g. acf/testimonial instead of testimonial title Top-level title Direct match description Top-level description Direct match category Top-level category Direct match icon Top-level icon Direct match, including the array form for background/foreground colors keywords Top-level keywords Direct match p
AI 资讯
How to Build a First Test Suite From Scratch for a New Project?
The worst test suite I ever inherited had 400 tests, and I trusted about six of them. The rest were either testing implementation details nobody cared about, duplicating each other, or so tightly coupled to internal function names that a harmless refactor broke thirty tests for no real reason. Reading that codebase taught me more about what not to do than any greenfield project ever has. So when you're starting from zero, the goal isn't "write a lot of tests fast." It's building a suite you'll still trust a year from now. If you're new to this, getting the software testing basics right early matters more than covering everything - learning how to build a first test suite from scratch teaches you what to prioritize in a way that inheriting someone else's bloated suite never will. Here's roughly how I'd approach it. Start with what would actually hurt if it broke Before writing a single test, list the handful of things that would be genuinely bad if they silently broke - checkout completing, auth working, the core thing your product does actually happening. Not every function, not every branch. Just the stuff where a silent failure costs you money, users, or trust. This list is usually shorter than people expect. Five to ten flows for most early-stage products. That's your actual test suite's job in the first few months, not "100% coverage." Unit tests for logic, not for plumbing Unit tests are for things with actual decision-making in them - pricing calculations, validation rules, state transitions, anything where "given this input, is the output correct" is a real question with a wrong answer possible. They're fast, they're cheap, and they should make up the bulk of your suite. Skip unit-testing pure plumbing: a function that just calls another function and returns its result doesn't need its own test. That's the kind of test that pads a coverage number without catching anything real, and it's exactly the kind of test that made that 400-test suite so hard to trust.
开发者
Still Warm: a museum where comfort food is the art
This is a submission for Frontend Challenge - Comfort Food Edition, Perfect Landing Most food...
AI 资讯
is-kit Reached 50 Stars ⭐ Here’s How We Use It in Production
Hoi hoi! I'm @nyaomaru, a frontend engineer who is trying to lose weight. 🐖🙀 I maintain a type...
AI 资讯
React 19's useFormStatus Fixed My Prop Drilling. Then It Sat There Returning False
Part 1 was about waiting well. Part 2 was about not waiting at all. This one is about a value I...
AI 资讯
Stop Fine-Tuning Your Model. Your Architecture Is the Problem.
I spend a lot of time in the AI space -- reading papers, building things, talking to engineers who are actually shipping. And there is a gap between what the demos show and what production systems actually look like that nobody is being fully honest about. So here is my honest take on where things actually are. The Problem With How We Talk About AI Agents Everyone is calling everything an "agent" right now. A function that calls a tool? Agent. A chatbot with memory? Agent. A script with a loop? Agent. This dilution is not just semantic. It is causing real engineering mistakes. When you do not have a precise definition for what you are building, you end up over-engineering simple pipelines and under-engineering genuinely complex ones. I have seen teams spend weeks adding "agentic" orchestration to workflows that would have been fine as a single well-structured prompt. Here is the definition I keep coming back to: an agent is a system that has an objective, not just an instruction. It decides what to do next. It handles failure. It knows when it is done. Everything else is just a fancy function call. 🟢 If your system needs a human to tell it each step, it is not an agent. It is a chat interface. 🔵 If your system can recover from a failed tool call and try a different approach, you are getting somewhere. ✅ If your system can decompose a goal into subtasks and delegate them, that is the real thing. What Is Actually Happening in Production Right Now The honest picture from teams I follow and talk to: Most real agent deployments are narrow. They do one thing well. Customer support triage. Document extraction. Code review on a specific codebase. They are not general-purpose reasoning engines. They are purpose-built pipelines with some intelligence in the decision layer. The teams getting good results are not chasing the latest model release. They are obsessing over: ☑️ Tool design -- what can the agent actually call, and how clean is the interface ☑️ Failure handling -- wh
AI 资讯
Why Retrieval-Augmented Generation Is Harder Than Every Tutorial Makes It Look.
I spend a lot of time in the AI space -- reading papers, building things, talking to engineers who are actually shipping. And there is a gap between what the demos show and what production systems actually look like that nobody is being fully honest about. So here is my honest take on where things actually are. The Problem With How We Talk About AI Agents Everyone is calling everything an "agent" right now. A function that calls a tool? Agent. A chatbot with memory? Agent. A script with a loop? Agent. This dilution is not just semantic. It is causing real engineering mistakes. When you do not have a precise definition for what you are building, you end up over-engineering simple pipelines and under-engineering genuinely complex ones. I have seen teams spend weeks adding "agentic" orchestration to workflows that would have been fine as a single well-structured prompt. Here is the definition I keep coming back to: an agent is a system that has an objective, not just an instruction. It decides what to do next. It handles failure. It knows when it is done. Everything else is just a fancy function call. 🟢 If your system needs a human to tell it each step, it is not an agent. It is a chat interface. 🔵 If your system can recover from a failed tool call and try a different approach, you are getting somewhere. ✅ If your system can decompose a goal into subtasks and delegate them, that is the real thing. What Is Actually Happening in Production Right Now The honest picture from teams I follow and talk to: Most real agent deployments are narrow. They do one thing well. Customer support triage. Document extraction. Code review on a specific codebase. They are not general-purpose reasoning engines. They are purpose-built pipelines with some intelligence in the decision layer. The teams getting good results are not chasing the latest model release. They are obsessing over: ☑️ Tool design -- what can the agent actually call, and how clean is the interface ☑️ Failure handling -- wh
AI 资讯
Test your Supabase RLS before you ship: a free red/green fixture and the 9 SQL checks a linter cannot run
If you built a Supabase app quickly - with an AI coding tool or by hand - the row-level-security policies were often written last, or generated for you. That is fine. What is not fine is shipping without knowing whether those policies actually isolate one user's rows from another. Supabase ships a database linter, and you should run it first - it is free and it catches the obvious cases: RLS switched off, and RLS switched on with no policy behind it. But a linter checks whether a policy exists , not whether the policy is correct . Those are different questions, and the second one is where cross-user leaks live. The 2-second test I put a minimal, synthetic reproduction on GitHub: supabase-rls-leak-demo . Same test suite on two branches, differing only by db/policies.sql : broken -> 4 failed, 1 passed (an authenticated user reads another user's row) fixed -> 5 passed npm ci npm run test :ci No Docker, no Supabase project, no credentials. The tests run PostgreSQL in PGlite locally and exercise database-level row security. They do not model Supabase Auth, PostgREST, the Data API, or the network path - the result proves only the row-level gate in the fixture, which is exactly the gate people get wrong. On broken , the failing assertion is readable on purpose: x does not let user B read any row owned by user A -> user B received 1 row(s) belonging to another user: ["A: card ending 4471, expiry 09/29"] (That is synthetic seed data, not a real card.) Run the free checks against your own database The repo also ships audit/rls-audit.sql - nine read-only queries against the system catalogs, MIT-licensed, nothing to install and nothing to send anywhere. Every one is SELECT -only, so it is safe to paste into the Supabase SQL editor. They tell you: RLS coverage per table Every policy and the roles it actually applies to (an empty roles array means no TO clause, so the policy is evaluated for anon too) The effective write check, and which columns its predicate never mentions What
AI 资讯
Angular 22: The End of Boilerplate and the Consolidation of the Reactive Era
If you have been following the evolution of Google's framework over the last few years, you know it has been undergoing a silent reconstruction — piece by piece. With the release of Angular 22 on June 3, 2026, this reconstruction is no longer a promise and has become the standard. We are not looking at another batch of experimental features: we are looking at the consolidation of an entirely rethought ecosystem. For those who live and breathe enterprise applications, Clean Architecture, and Microfrontend ecosystems, this is the version that finally delivers what has been promised since Angular 16: an end-to-end reactive framework, zone-less by nature, and with much less ceremony along the way. The experiments are over. Below is what has actually changed — and what you need to do before running ng update . 📖 If you are just starting out: several technical terms in this article (change detection, Signals, SSR, dependency injection, microfrontends...) are explained in a glossary at the end. Read the article from end to end and use the glossary as a reference whenever you have a doubt. What Arrived in Angular 22 OnPush is the new default change detection (the old Default became Eager and is deprecated). Stable Resource API: resource , rxResource , and httpResource are ready for production. Stable Signal Forms: featuring the Submission API, dynamic schemas (Zod/Valibot), and interop with Reactive Forms. New @Service() decorator: shortening @Injectable({ providedIn: 'root' }) . injectAsync : for lazy dependency injection, with prefetch via onIdle . debounced : for native debounce in Signals/Resources. Incremental Hydration: enabled by default. HttpClient : uses FetchBackend by default ( withFetch() is deprecated). Important Router and bootstrap improvements designed for Microfrontends . 1. OnPush as the New Default Change Detection The moment the community has always asked for has arrived: ChangeDetectionStrategy.OnPush is now the default behavior for any new component. T
AI 资讯
AGENTS.md vs CLAUDE.md: Where Agent Context Actually Lives
AGENTS.md vs CLAUDE.md: Where Agent Context Actually Lives If you have opened three different repos this month and found three different context files (AGENTS.md in one, CLAUDE.md in another, both in a third, out of sync), you are not imagining the mess. AGENTS.md is now an open, vendor neutral standard that most major coding agents read, but CLAUDE.md has not gone away, and knowing which file wins where saves you from an agent quietly following stale instructions. What AGENTS.md actually is AGENTS.md started as a proposal from Sourcegraph's Amp team to fix a specific problem: every coding agent invented its own context file, so teams ended up maintaining CLAUDE.md, .cursorrules, .windsurfrules, and whatever else, all describing the same project. OpenAI and Google backed the standard, and it has since moved under the Linux Foundation's Agentic AI Foundation. Guides tracking adoption report 28+ supporting tools and more than 60,000 open source repos containing the file (secondary source, treat the exact counts as approximate, not audited). The pitch is simple: one Markdown file, one format, every agent reads the same source of truth instead of you hand syncing five files that drift within a week. Which tools actually read it This is the part that matters when you are deciding whether to migrate. Tools with native AGENTS.md support include: GitHub Copilot coding agent Cursor Amp Factory RooCode Zed Warp Notice what is not confirmed on that list. Reports that Claude Code reads AGENTS.md natively circulate in comparison guides, but I could not verify this against Anthropic's own changelog, so I am stating it qualitatively here rather than as fact: treat it as unconfirmed until you see it in Anthropic's own docs, and keep CLAUDE.md in place as your safety net if you rely on Claude Code specifically. AGENTS.md vs CLAUDE.md vs the well known directory Three layers get conflated constantly, and they solve different problems. Layer What it is Scope AGENTS.md Vendor neutral p
AI 资讯
We shipped an MCP server for WhatsApp link generation — no API key required
We shipped an MCP server for WhatsApp link generation — no API key required If you've ever needed an AI agent to validate a WhatsApp number, build a wa.me link, or generate a QR code on the fly, you've probably hand-rolled it: scrape a regex off Stack Overflow, write your own phone-format validator, maybe hit some undocumented endpoint. We got tired of watching that happen and shipped a small, open MCP server that does it directly. What it is WhatsUsernames.link already runs a free public REST API for validating WhatsApp usernames/phone numbers and generating wa.me links + QR codes. We just exposed the same logic over the Model Context Protocol , so Claude, and any other MCP client, can call it as native tools instead of you writing a fetch wrapper. Endpoint: https://whatsusernames.link/api/mcp No API key. No account. No signup form. Same open, IP-rate-limited model as the REST API (60 req/min for JSON tools, 20 req/min for QR generation, sliding window via Upstash Redis). The five tools Tool What it does validate_username Checks WhatsApp username ( @username ) format validate_phone Checks phone number format (8–15 digits, international) username_link Builds a wa.me link (+ short link) from a username, optional prefilled text phone_link Builds a wa.me link from a phone number, optional prefilled text qr_code Renders a QR code (PNG or SVG) for a wa.me link, custom size/colors Every tool wraps the exact same services/ and validate-* functions the REST API uses — there's no separate business logic to drift out of sync. If the REST endpoint says a number is valid, the MCP tool agrees, because it's the same code path. Connect it Drop this into your MCP client config: { "mcpServers" : { "whatsusernames" : { "url" : "https://whatsusernames.link/api/mcp" } } } That's it. No stdio process to spawn, no local install — it's a stateless Streamable HTTP transport running on Vercel, same domain as the site. Why build this Two reasons. Practical: every agent that needs to hand a u
AI 资讯
ShowDev: I built a bulk HTML-to-Markdown converter that runs entirely in the browser
Most HTML-to-Markdown tools handle one file at a time. You paste some HTML, get Markdown back, repeat. That works for a quick snippet but not when you have 200+ pages from a help center export sitting in a folder. I needed exactly that. I had a full site mirror (grabbed with wget --mirror ) and wanted clean Markdown I could feed into an LLM knowledge base. Nothing I found could handle it without uploading files to a server or converting one by one. So I built HTML to Markdown AI . How it works You drop a ZIP file (or individual HTML files) into the browser A Go-based conversion pipeline compiled to WebAssembly processes everything locally You get a ZIP back with clean GitHub-Flavored Markdown, folder structure preserved No server involved. Your files never leave your machine. The conversion pipeline The heavy lifting happens in Go/WASM. The pipeline: Strips navigation, footers, scripts, styles, and other boilerplate noise Extracts the main content from the page Converts to GFM with proper heading hierarchy, tables, code blocks, and links Handles batch processing so you can throw hundreds of files at it Why no built-in crawler? Intentional decision. Downloading HTML from someone else's site has legal implications depending on jurisdiction and terms of service. I don't want to be in that business. Downloading is also the easy part: wget -r -l 0 -np -k -E -p -e robots = off \ --reject-regex '\.(png|jpe?g|gif|svg|webp|woff2?|ttf|css|js|zip|pdf)$' \ -w 0.5 --random-wait \ https://docs.example.com/ That gives you a local folder with all the HTML. The hard and annoying part is turning that into clean, usable Markdown. That's what this tool solves. Stack Frontend: Astro + Tailwind Conversion engine: Go compiled to WebAssembly Processing: Entirely client-side, zero backend Try it https://www.html-to-markdown-ai.com Use cases I've tested it with: Help center exports (Zendesk, Confluence, custom wikis) Documentation sites mirrored with wget/httrack Scraped content for RAG pipe
AI 资讯
OOP Object-Oriented Programming
Advantages of using OOP: Is faster and easier to execute. Provides a clear structure for the programs. Helps to keep code DRY "Don't Repeat Yourself" and makes code easier to maintain, modify, and debug. Makes it possible to create fully reusable applications with less code and shorter development time. Define a Class: A class is defined by using the class keyword, followed by the name of the class and a pair of curly braces {} . All its properties and methods go inside the braces. Delegation: Delegation means that you use an object of another class as an instance variable. We can create multiple objects from a class. Each object has all the variables and functions defined in the class. An object of a class is made using the new keyword. Note: The $this keyword refers to the current class and is only available inside methods. __construct() function: Automatically runs at the beginning of the class. __destruct() function: Automatically runs at the end of the class. Encapsulation: The wrapping up of data and methods is a protection mechanism for the variables and functions inside the class. Access Modifier: Public: Variables or functions can be accessed from everywhere. Private: Variables or functions can ONLY be accessed inside the class. Protected: Variables or functions can be accessed inside the class and by child classes that extend from the parent class. Constants: It can’t be changed once it is declared. Declared inside a class with the const keyword. It is recommended to name the constants in all uppercase letters . Access outside the class by using the class name followed by the scope resolution operator :: . Access a constant inside the class by using the self keyword. Static Functions and Variables: Static functions or variables can be called directly - without creating an instance of the class first. Static functions or variables are declared with the static keyword. To access a static function or variable, use the class name , double colon :: , and the fu
AI 资讯
I built 109 tools that never touch a server - here is the architecture
I built 109 tools that never touch a server - here is the architecture Most "tools" sites you have used do this: You upload a file It goes to a server The server processes it You download the result Sometimes the server stores it. Sometimes it leaks. Sometimes it disappears with the company. I wanted something different. Every tool on korelyy.com runs 100% in your browser . Zero backend. Zero upload. Zero tracking. Here is the actual architecture, the real numbers after 90 days, and what I learned. What "no server" actually means For each of the 109 tools: The entire app is a static HTML + CSS + JS file It is served as-is from a CDN (Cloudflare Pages) All file processing happens in your browser via FileReader , canvas , Web Crypto API , or OffscreenCanvas Your file never leaves your device Closing the tab = the data is gone (no cookies, no localStorage, no account) This is not a marketing claim. It is verifiable: Open DevTools -> Network tab Use any tool that requires a file (image converter, JSON formatter, etc.) Reload. The only network request is for the static HTML/CSS/JS bundle. No fetch() to a server. No XHR . No upload. The file is read, processed in-memory, and downloaded. The 4 browser APIs that do 90% of the work When you remove a backend, you are left with the browser. The browser is more capable than most people think. 1. FileReader and URL.createObjectURL Read any file the user gives you: const file = document . querySelector ( ' input[type=file] ' ). files [ 0 ]; const url = URL . createObjectURL ( file ); const img = new Image (); img . onload = () => { // process image canvas . toBlob ( blob => { const downloadUrl = URL . createObjectURL ( blob ); // trigger download }); }; img . src = url ; Image conversion, PDF generation, audio trimming - all the same pattern. Read blob, process, create new blob, download. 2. crypto.subtle (Web Crypto API) Hashing, encryption, signing - all client-side: const hash = await crypto . subtle . digest ( ' SHA-256 ' , a