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

标签:#java

找到 620 篇相关文章

AI 资讯

# Building a Lightweight Product Filter with Vanilla JavaScript

Building a Lightweight Product Filter with Vanilla JavaScript While building a small e-commerce project, I wanted users to filter products instantly without refreshing the page. Instead of relying on a frontend framework, I opted for a simple solution using HTML data attributes, vanilla JavaScript, and a little CSS. The goal was straightforward: let visitors filter items by size while keeping the interface fast, responsive, and easy to maintain. HTML Structure Each product card stores its information in data-* attributes. This keeps the markup clean and makes filtering straightforward. <div class= "filters" > <button class= "filter-btn" data-filter= "all" > All </button> <button class= "filter-btn" data-filter= "small" > S </button> <button class= "filter-btn" data-filter= "medium" > M </button> <button class= "filter-btn" data-filter= "large" > L </button> </div> <div class= "product-grid" > <div class= "product-card" data-size= "medium" data-style= "cargo" > Cargo Shorts </div> <div class= "product-card" data-size= "large" data-style= "chino" > Chino Shorts </div> <!-- More product cards --> </div> Using data attributes means you can add new filter categories later without changing your overall structure. JavaScript Filtering Logic The filtering logic listens for button clicks and simply shows or hides product cards based on the selected size. const filterButtons = document . querySelectorAll ( " .filter-btn " ); const productCards = document . querySelectorAll ( " .product-card " ); filterButtons . forEach (( button ) => { button . addEventListener ( " click " , () => { const filterValue = button . dataset . filter ; productCards . forEach (( card ) => { const cardSize = card . dataset . size ; if ( filterValue === " all " || cardSize === filterValue ) { card . classList . remove ( " hidden " ); } else { card . classList . add ( " hidden " ); } }); filterButtons . forEach (( btn ) => btn . classList . remove ( " active " )); button . classList . add ( " active "

2026-07-15 原文 →
开发者

Why Your TypeScript 7 Upgrade Broke ESLint, ts-jest, and ts-morph

You installed TypeScript 7, ran your build, and something broke. Maybe ESLint crashed with a cryptic TypeError: Cannot read properties of undefined (reading 'Cjs') . Maybe ts-jest stopped transforming your test files. Maybe your CI pipeline just went red for no reason you can point to. You're not doing anything wrong. TypeScript 7 shipped tsgo, a genuine Go port of the type-checker, not a rewrite from scratch. But the tools that plug into TypeScript don't talk to the type-checker directly, they talk to a programmatic API. That API isn't stable yet, it lands in 7.1. Until then, a chunk of the ecosystem throws errors the moment you point typescript at the new version. The 10-second version Don't replace typescript in your dependencies with the 7.x line if you use typescript-eslint, ts-jest, ts-morph, or any tool doing programmatic type-checking. Keep typescript pinned to 6.x for those tools, and install @typescript/native-preview alongside it purely for fast type-checking in CI or a manual tsgo --noEmit command. Two compilers, living side by side, each doing a different job. Why this is happening The TypeScript team calls this Project Corsa: a line-by-line port of the compiler from the old JavaScript codebase (Strada) into Go (Corsa), preserving identical type-checking behavior while getting roughly 10x faster builds from real OS threads instead of Node's single-threaded event loop. That preservation is impressive, but it's a port, not a reimplementation with a new API surface. Tools like typescript-eslint depend on the programmatic API to walk your AST and pull type information out of the compiler, and that API isn't ready until 7.1. What's actually broken right now typescript-eslint — npm refuses to install alongside typescript@7 at all (ERESOLVE error), because the published peer range only allows versions below 6.1.0. Force it through and ESLint crashes deep inside typescript-estree . Tracked as typescript-eslint issue #12518, closed as not planned since the real

2026-07-15 原文 →
AI 资讯

How to run your first OpenAI-compatible API call with curl, Python, and Node.js

When you are testing an OpenAI-compatible API endpoint, the fastest path is not to wire it into a full app immediately. Start with one small request, confirm the base URL, API key, model name, and response shape, then move the working call into your product. I put together a compact examples repo for that exact first-call workflow: https://github.com/OriginStartAI/openai-compatible-api-examples It includes curl, Python, Node.js, streaming responses, JSON structured output, migration notes, and a small error reference. 1. Set environment variables first Keep credentials out of source code and use environment variables: ORIGINSTARTAI_API_KEY = your_api_key_here ORIGINSTARTAI_BASE_URL = https://your-api-base-url/v1 ORIGINSTARTAI_MODEL = your_enabled_model The important parts are simple: base_url or baseURL points to your OpenAI-compatible endpoint. api_key or apiKey is your provider key. model must be enabled for your account. Streaming support should be tested separately. 2. Test with curl Curl is useful because it removes SDK behavior from the equation: curl " $ORIGINSTARTAI_BASE_URL /chat/completions" \ -H "Authorization: Bearer $ORIGINSTARTAI_API_KEY " \ -H "Content-Type: application/json" \ -d '{ "model": "' " $ORIGINSTARTAI_MODEL " '", "messages": [ {"role": "user", "content": "Say hello from OriginStartAI"} ] }' If this works, your endpoint, key, and model are probably configured correctly. 3. Then test Python from openai import OpenAI import os client = OpenAI ( api_key = os . environ [ " ORIGINSTARTAI_API_KEY " ], base_url = os . environ [ " ORIGINSTARTAI_BASE_URL " ], ) response = client . chat . completions . create ( model = os . environ [ " ORIGINSTARTAI_MODEL " ], messages = [{ " role " : " user " , " content " : " Write one friendly onboarding sentence. " }], ) print ( response . choices [ 0 ]. message . content ) 4. Then test Node.js import OpenAI from " openai " ; const client = new OpenAI ({ apiKey : process . env . ORIGINSTARTAI_API_KEY , baseURL : p

2026-07-15 原文 →
AI 资讯

Production-Ready AI Agents in Node.js: Iteration Caps and Tracing

Your AI Agent Needs Tracing, Not Just Logs You've probably already called an LLM from a Node.js backend. That part's easy — every provider ships a solid SDK. The part that actually trips people up is what happens after : turning that one API call into an agent that reasons, uses tools, loops a few times, and still behaves once real users are hitting it. Here's a small, honest pattern for that — plus the one thing most tutorials skip: making the loop debuggable. Why Node.js is doing this job Node has quietly become the default home for the application layer around AI. It's become the preferred middle layer for deploying modern AI agents, wrapping heavier model inference behind fast Node APIs. Python still owns training and the heavy orchestration frameworks — Node owns the gateway, the auth, the streaming UI, and the business logic wrapped around all of it. On the SDK side, things consolidated fast: OpenAI's Node SDK holds roughly a third of weekly npm downloads across the major JS AI SDKs, and Anthropic's TypeScript SDK has grown nearly tenfold in a year. And despite all the framework noise, most production teams just use the Claude or OpenAI SDK directly — reaching for LangChain.js or Mastra only once multi-agent coordination actually earns its keep. The loop: reason, act, repeat Almost every "agent" in 2026 runs on the same loop: reason about the task, act through a tool call, look at what came back, reason again — repeat until done. That's it. The engineering is in the guardrails around it, not the loop itself. // agent.js import Anthropic from " @anthropic-ai/sdk " ; const anthropic = new Anthropic (); // reads ANTHROPIC_API_KEY from env const tools = [ { name : " get_order_status " , description : " Look up the status of a customer order by order ID. " , input_schema : { type : " object " , properties : { orderId : { type : " string " } }, required : [ " orderId " ], }, }, ]; async function getOrderStatus ({ orderId }) { // stand-in for a real DB/service call r

2026-07-15 原文 →
AI 资讯

JavaScript has no sorted containers. I built one for TypeScript.

JavaScript ships with Array , Set , and Map — but nothing that keeps its elements sorted as you insert. If you've ever built a leaderboard, an order book, or anything that answers "give me the items between X and Y", you know the workaround: push into an array and .sort() after every insertion. It works, until scale punishes you — you're paying O(n log n) over and over for data that was already 99.9% sorted. Python solved this years ago with sortedcontainers , built on an elegant "list of lists" design instead of balanced trees. I just published sorted-collections , which brings that idea to TypeScript — with full credit to the original as its inspiration. What you get SortedList, SortedSet, SortedMap — always sorted, no manual re-sorting, range queries built in. O(log n) insertions, O(√n) positional access via sqrt-decomposition into buckets. Zero runtime dependencies , ~2KB gzip, types included, dual ESM/CJS. Package quality gated in CI with publint , arethetypeswrong , and size-limit . The API in 30 seconds import { SortedList , SortedSet , SortedMap } from " sorted-collections " ; // SortedList: stays sorted on every insert const list = new SortedList ([ 5 , 1 , 4 , 2 , 3 ]); list . add ( 0 ); console . log ([... list ]); // [0, 1, 2, 3, 4, 5] console . log ( list . at ( 2 )); // 2 — positional access on sorted order // SortedSet: no duplicates, plus set algebra const a = new SortedSet ([ 1 , 2 , 3 , 4 ]); const b = new SortedSet ([ 3 , 4 , 5 ]); console . log ([... a . intersection ( b )]); // [3, 4] // SortedMap: keys always in order, range queries built in const prices = new SortedMap < number , string > ([ [ 104.5 , " order-3 " ], [ 99.2 , " order-1 " ], [ 101.0 , " order-2 " ], ]); for ( const [ price , id ] of prices . irange ( 100 , 105 )) { console . log ( price , id ); // 101.0 order-2, then 104.5 order-3 } Custom comparators are fully typed: number and string get natural ordering for free; for your own types, TypeScript requires a comparator at compile

2026-07-15 原文 →
开发者

Conditional Operator (`?:`) in Java

The conditional operator ( ?: ) — The Only Ternary Operator is one of the most useful operators in Java. It lets you write simple decision-making logic in a single line, making your code cleaner and more concise. It's also a favorite topic in Java interviews because of its syntax, nesting behavior, and type compatibility rules. In this article, you'll learn: What the conditional operator is Why it's called a ternary operator Syntax and working Nested conditional operators Difference between ?: and if-else Practical examples Interview questions Memory tricks What is the Conditional Operator? The conditional operator is represented by: ? : It is the only ternary operator in Java . A ternary operator takes three operands , unlike: Operator Type Number of Operands Example Unary 1 ++x , !flag , ~5 Binary 2 a + b , a > b , a && b Ternary 3 (a > b) ? a : b Syntax result = ( condition ) ? valueIfTrue : valueIfFalse ; How It Works condition │ Is it true? / \ Yes No │ │ valueIfTrue valueIfFalse │ │ └────── Result ──────┘ If the condition is true , Java returns the value before the colon ( : ). If the condition is false , Java returns the value after the colon ( : ). Example 1 int x = ( 10 > 20 ) ? 30 : 40 ; System . out . println ( x ); Output 40 Step-by-Step Evaluate the condition: 10 > 20 ↓ false Since the condition is false, Java selects the value after : . 40 Therefore, x = 40 Example 2: Finding the Maximum int a = 10 ; int b = 20 ; int max = ( a > b ) ? a : b ; System . out . println ( max ); Output 20 This is one of the most common uses of the conditional operator. Example 3: Even or Odd int number = 7 ; String result = ( number % 2 == 0 ) ? "Even" : "Odd" ; System . out . println ( result ); Output Odd Example 4: Absolute Value int x = - 5 ; int absolute = ( x < 0 ) ? - x : x ; System . out . println ( absolute ); Output 5 Nested Conditional Operators One of the biggest advantages of the conditional operator is that it can be nested . Example int x = ( 10 > 20 ) ? 30 :

2026-07-14 原文 →
开源项目

🔥 songquanpeng / one-api - LLM API 管理 & 分发系统,支持 OpenAI、Azure、Anthropic Claude、Google Ge

GitHub热门项目 | LLM API 管理 & 分发系统,支持 OpenAI、Azure、Anthropic Claude、Google Gemini、DeepSeek、字节豆包、ChatGLM、文心一言、讯飞星火、通义千问、360 智脑、腾讯混元等主流模型,统一 API 适配,可用于 key 管理与二次分发。单可执行文件,提供 Docker 镜像,一键部署,开箱即用。LLM API management & key redistribution system, unifying multiple providers under a single API. Single binary, Docker-ready, with an English UI. | Stars: 35,709 | 30 stars today | 语言: JavaScript

2026-07-14 原文 →
AI 资讯

Stop Writing try/catch in Every Controller

When I first started building APIs with Express.js, every async controller looked the same. I would write a try block, perform some database operations, and then write a catch block that called next(error) . It worked, so I copied the same pattern into every controller. One controller became ten. Ten became fifty. Eventually, I realized that half of my controller code wasn't actually business logic, it was just repetitive error handling. That's when I discovered the Async Handler pattern. The Problem A typical Express controller often looks like this: export const getUser = async ( req , res , next ) => { try { const user = await User . findById ( req . params . id ); if ( ! user ) { throw new Error ( " User not found " ); } res . json ( user ); } catch ( error ) { next ( error ); } }; There's nothing wrong with this code. The problem is that every async controller ends up looking exactly the same. Every file contains: try, catch and next(error) over and over again. Besides being repetitive, it's also easy to forget. Miss one try-catch block, and Express won't automatically catch errors thrown inside async functions. What Is an Async Handler? An async handler is a small wrapper function that automatically catches errors from async controllers. Instead of every controller handling its own errors, the wrapper does it for you. A Simple Analogy Imagine an office where every employee has to stop working whenever someone rings the front door. Besides doing their own job, they also have to greet every visitor. This quickly becomes repetitive and inefficient. Instead, the company hires a receptionist to handle every visitor. Now the employees can focus on their actual work while the receptionist takes care of the door. An async handler works the same way. Controllers focus on handling requests, while the async handler catches errors and passes them to Express's error handler. Without an Async Handler export const createUser = async ( req , res , next ) => { try { const user

2026-07-14 原文 →
AI 资讯

Stop Arguing About Code Style — Set Up Prettier, ESLint & Husky Once

Why this matters I’ve worked on a few frontend projects where code reviews turned into style debates—tabs vs spaces, semicolons, quote styles… you name it. It slows everything down and adds zero value. At some point, I realized this shouldn’t even be a discussion. So now, whenever I start a project, I set up Prettier + ESLint + Husky on day one. No debates. No manual fixes. No messy PRs. This post is exactly how I do it. 🧰 What each tool actually does Prettier → formats your code automatically ESLint → catches bad patterns & enforces rules Husky → runs checks before commits (so no one skips them) Together → clean, consistent code without thinking ⚙️ Step 1 — Install dependencies npm install -D prettier eslint husky lint-staged 🎯 Step 2 — Setup Prettier Create: prettier.config.js module . exports = { semi : true , singleQuote : true , trailingComma : ' all ' , tabWidth : 2 , }; Create: .prettierignore node_modules dist build 🔍 Step 3 — Setup ESLint Initialize: npx eslint --init Then tweak your config: .eslintrc.js module . exports = { extends : [ ' eslint:recommended ' , ' plugin:react/recommended ' , ' prettier ' ], rules : { ' no-unused-vars ' : ' warn ' , ' react/react-in-jsx-scope ' : ' off ' , }, }; 👉 Important: "prettier" disables ESLint rules that conflict with Prettier. 🔗 Step 4 — Connect ESLint + Prettier Install: npm install -D eslint-config-prettier That’s it. Now ESLint won’t fight Prettier. 🐶 Step 5 — Setup Husky Initialize Husky: npx husky init Add pre-commit hook: npx husky add .husky/pre-commit "npx lint-staged" 🚀 Step 6 — Setup lint-staged Add to package.json : "lint-staged" : { "*.{js,jsx,ts,tsx}" : [ "eslint --fix" , "prettier --write" ] } 💡 What happens now? Every time you commit: ESLint checks your code Prettier formats it Only clean code gets committed No more: “fix formatting” PR comments broken lint rules in main branch inconsistent code styles 🧠 Real impact (from experience) After adding this to a team project: PR noise dropped a lot reviews

2026-07-14 原文 →
开发者

Making ServiceLoader usable: a provider factory

I keep coming back to java.util.ServiceLoader . I have used it to put a JSON layer behind a contract, so the core code carries no direct dependency on any particular JSON library and I can swap the implementation without touching callers. The same shape works for JWT handling, where the concrete library might be jose4j or another JOSE implementation, and you can easily find other decoupling use-cases. The motivation is always the same: the application should depend on a capability, not on a vendor. A while back I wrote about exactly that idea in Rediscovering Java ServiceLoader: Beyond Plugins and Into Capabilities , where the argument was to treat ServiceLoader as capability discovery rather than a plugin system. That piece hit the limitation everyone hits — the no-argument constructor — and worked around it with a default constructor plus a dynamic proxy that built the real object through a factory on each call. It works, but it is indirection bolted on after the fact, not a design. This post is the part I never pinned down back then: turning that workaround into a small, explicit pattern. The running example below is a mock payments system, with Stripe and PayPal specializations, because it is compact enough to show end to end. The JSON and JWT cases cited can be built with the same structure. The two limits ServiceLoader leaves you The first is the no-argument constructor. Whatever ServiceLoader instantiates must have a public, parameterless constructor. My StripePaymentService takes an API key, so it cannot be the class ServiceLoader loads — not unless I bolt on some init-after-construction step, which I would rather avoid. The second is selection, or rather the lack of it. ServiceLoader gives you every implementation it finds, in roughly classpath order. There is no id, nothing to prioritise on, and no way to ask whether a given one even applies in the current environment. With two backends on the classpath and only one configured, working out which to use is

2026-07-14 原文 →
AI 资讯

Add Arrow-Key Shortcuts to a Confirmation Dialog Without Breaking Accessibility

Two buttons in a confirmation dialog look simple: Cancel and Confirm. Keyboard behavior makes the component a small state machine. A recent MonkeyCode change gives us a concrete example. Issue #862 and PR #863 add these shortcuts to the slash-command confirmation: ArrowLeft -> focus Cancel ArrowRight -> focus Confirm The reviewed implementation at commit c58bcd4 moves focus through button refs. That is a useful extra interaction. It is not a replacement for the dialog's accessibility foundation. Keep the baseline first For an alert-style confirmation, users still need: an accessible name and description; focus moved inside when the dialog opens; Tab and Shift+Tab constrained to dialog controls; Escape to dismiss when cancellation is allowed; visible focus; focus returned to the trigger after close; actual buttons whose labels explain the actions. The WAI-ARIA Authoring Practices Alert Dialog Pattern describes the modal semantics and keyboard foundation. Left/right mapping is a product shortcut, not a required AlertDialog convention. That means we must not steal keys from the established behavior around it. Isolate the extra mapping The companion keyboard.mjs starts with a pure function: export function arrowAction ( key ) { if ( key === " ArrowLeft " ) return " cancel " ; if ( key === " ArrowRight " ) return " confirm " ; return null ; } The event handler ignores unrelated and modified keys: export function handleDialogArrow ( event , controls ) { const action = arrowAction ( event . key ); if ( ! action || event . altKey || event . ctrlKey || event . metaKey ) return false ; event . preventDefault (); controls [ action ]. focus (); return true ; } Notice what is absent: no handler for Tab , Shift+Tab , Escape , or Enter . The native <dialog> and buttons in the minimal demo retain their normal jobs. In a React component, use a well-tested modal/dialog primitive for focus containment and dismissal, then add this narrow handler to its content. A complete minimal dialo

2026-07-14 原文 →
AI 资讯

SilentShare — A Browser-Based Peer-to-Peer File Sharing App

Have you ever been in a computer lab, classroom, or office where you needed to quickly send a file between your phone and laptop? I run into this problem all the time. Sometimes there's no USB cable, no pendrive, Bluetooth is painfully slow, or uploading to cloud storage just to download the file on another device feels unnecessary. So I decided to build SilentShare . What is SilentShare? SilentShare is a browser-based peer-to-peer file sharing application that lets you instantly share: 📁 Files (up to 50 MB) 💻 Code snippets 📝 Text 🖼️ Images No installation. No account. No server storing your files. Your data goes directly from one device to another using WebRTC . Whether you're sending files from your phone to your laptop, between classmates, or across the internet, SilentShare keeps the process simple. Why I Built It I wanted something that: Opens instantly in any browser Doesn't require creating an account Doesn't upload files to someone else's server Works on desktop and mobile Feels lightweight and fast Instead of relying on cloud storage, I wanted the browser itself to become the transfer tool. Features ✨ Peer-to-peer file transfer using WebRTC 📂 File sharing up to 50 MB (including ZIP files) 🔒 Optional end-to-end encrypted rooms using AES-GCM 📷 QR code invitations with built-in camera scanner 📊 Live progress, transfer speed, ETA, pause & resume 🖼️ Preview support for: Images Audio Video PDFs 💻 Share code snippets with syntax highlighting 👥 Multi-user rooms (around 5 participants) 🌙 Dark & Light mode 📱 Installable as a Progressive Web App (PWA) How It Works Create a room Receive a random room code Share the code, QR code, or invite link Other devices join Start sharing instantly The files are transferred directly between devices instead of passing through a storage server. Privacy One of the goals of SilentShare was privacy. No user accounts No cloud storage No permanent database Nothing stored after the browser tab closes If you set a room password, all transf

2026-07-14 原文 →
AI 资讯

I Built an AI-Powered CLI That Migrates Legacy Java Code to Java 17/21/25

I Built an AI-Powered CLI That Migrates Legacy Java Code to Java 17/21/25 If you've spent any time in enterprise Java, you know the feeling. You open a service that's been running since 2014 and you're greeted by walls of anonymous inner classes, verbose null checks, Collections.unmodifiableList wrapping a new ArrayList , and switch statements with more break keywords than actual logic. Individually each pattern takes 30 seconds to fix. But across a codebase with 300 files, it's a week of mechanical work — and that's before you factor in the code review. So I built java-migrate : a CLI tool that scans your Java files, detects legacy patterns, and sends them to Claude with a precise system prompt to get them modernised. One command, instant diff, no surprises. What it looks like in practice Here's a typical legacy file before migration: public class LegacyService { // POJO with getters/setters public static class User { private String name ; private int age ; public String getName () { return name ; } public void setName ( String name ) { this . name = name ; } public int getAge () { return age ; } public void setAge ( int age ) { this . age = age ; } } public List < User > sortUsers ( List < User > users ) { // Anonymous Comparator users . sort ( new Comparator < User >() { @Override public int compare ( User a , User b ) { return a . getName (). compareTo ( b . getName ()); } }); return Collections . unmodifiableList ( users ); } public String describeObject ( Object obj ) { // instanceof + cast if ( obj instanceof String ) { String s = ( String ) obj ; return "String of length " + s . length (); } return "Unknown" ; } public String classify ( int value ) { // switch statement String result ; switch ( value ) { case 1 : result = "one" ; break ; case 2 : result = "two" ; break ; default : result = "other" ; } return result ; } } Run java-migrate LegacyService.java --dry-run --verbose and you get this diff: - public static class User { - private String name; - privat

2026-07-14 原文 →
AI 资讯

The Everyday Backend Engineer: Step 10 — The Observer Pattern

Welcome back to The Everyday Backend Engineer: Practical Design Patterns . In our last post, we made our core algorithms interchangeable using the Strategy Pattern. Today, we close out our design patterns roadmap with arguably the most native pattern in the entire Node.js ecosystem: The Observer Pattern . Let’s look at how to master event-driven decoupling to trigger secondary workflows seamlessly without bloat. 🔴 The Problem: Direct Inline Side-Effects Imagine you are writing a video processing engine or a simple order fulfillment system. When a specific event happens—such as an order being finalized—multiple unrelated departments want a piece of the action: The Notification Service needs to send an SMS and Email receipt. The Logistics Service needs to generate a warehouse fulfillment ticket. The Analytics Service needs to update marketing tracking boards. If you don't decouple these events, your primary execution service ends up managing a giant web of secondary micro-services: // ❌ Bad Practice: The primary service is drowning in secondary dependencies const EmailService = require ( ' ../services/email ' ); const WarehouseService = require ( ' ../services/warehouse ' ); const AnalyticsTracker = require ( ' ../services/analytics ' ); class OrderProcessor { async finalizeOrder ( order ) { console . log ( " Saving primary order to the database... " ); // Core business logic ends here // The codebase smell: Procedural cascading dependencies await EmailService . sendReceipt ( order . userEmail ); await WarehouseService . createShipment ( order . id ); await AnalyticsTracker . trackSale ( order . totalAmount ); } } module . exports = OrderProcessor ; Why does this slow your system down? Your core OrderProcessor is now structurally dependent on three separate systems. If the AnalyticsTracker throws a network timeout error or if the warehouse API changes its interface, your core transaction fails or hangs. Furthermore, adding a fourth side-effect (like an auditing logger

2026-07-14 原文 →
AI 资讯

How We Built DJ ROOTS: An AI-Powered Music Recommendation Platform

🎧 DJ ROOTS – Building a Real-Time Collaborative Music Platform with Gesture Control Crowd Vibes. You Control. Music is one of the best ways to bring people together. However, during parties, college events, hostel gatherings, or study sessions, one common problem always exists— who gets to control the music? Usually, one person owns the playlist while everyone else keeps requesting songs. This often creates confusion, interruptions, and arguments over what should play next. Our team wanted to solve this problem by creating a platform where everyone in the room gets an equal voice. Welcome to DJ ROOTS . 🚨 The Problem Traditional music streaming at group events has several limitations: Only one person controls the playlist. Song requests are ignored or forgotten. No real-time collaboration. Existing queue systems don't truly represent the crowd's choice. There is no simple browser-based solution that works instantly without downloading an app. We wanted to build something that makes music democratic . 💡 Our Solution DJ ROOTS is a real-time collaborative DJ platform where anyone can join a room using a simple room code. Participants can: Create or join a music room Add songs using YouTube Upvote or downvote tracks Automatically reorder the queue based on crowd votes Watch every change happen instantly across all connected devices Let the host control playback using webcam hand gestures Instead of one person deciding the playlist, the entire crowd decides what plays next. 🛠 Tech Stack Frontend React 19 Vite Tailwind CSS v4 Framer Motion Three.js GSAP OGL Backend Node.js Express.js Database & Authentication Supabase PostgreSQL Supabase Authentication Supabase Realtime Computer Vision Google MediaPipe Gesture Recognizer Audio Pipeline yt-dlp youtube-dl-exec HTML5 Audio API Web Audio API Deployment Vercel (Frontend) ⚙️ How It Works Users create or join a room using a unique room code. Songs are added using a YouTube link or search. Song metadata is automatically fetched. E

2026-07-14 原文 →
开发者

Commerce And Secrets Without An IAP Tax

Commerce is the easiest feature in this release to misunderstand, so the first sentence has to be blunt: What is Codename One? Codename One is an open-source framework for building native iOS, Android, desktop, and web apps from a single Java or Kotlin codebase. Learn more at codenameone.com . Commerce does not replace IAP and never will. Purchases still go through Apple, Google, or the payment processor you chose. Codename One does not process the payment, does not touch the money, and does not take a percentage. PR #5300 adds infrastructure around the annoying backend work that comes after a purchase: validation, entitlement checks, subscription lifecycle, webhooks, and reporting. That backend work is real. Anyone who has shipped subscriptions knows the trap. Buying a SKU is not the same as knowing whether the user has the right to a feature right now. Renewals, grace periods, refunds, billing retry, product changes, trials, family sharing and store server notifications all show up later. The device has one view. The store has another. Your backend usually needs a third. Commerce is the optional service that turns that mess into an entitlement. Entitlements Instead Of SKU Branches Your app should not need to know every SKU that grants pro . It should ask for pro . CommerceManager cm = CommerceManager . getInstance (); cm . setAppUserId ( accountId ); if ( cm . isEntitled ( "pro" )) { unlockProFeatures (); } Purchases are still delegated to the existing Purchase API: cm . subscribe ( "pro_monthly" ); // or cm . purchase ( "remove_ads" ); After a purchase, or when the app starts, refresh off the EDT: new Thread (() -> { CommerceManager cm = CommerceManager . getInstance (); cm . refresh (); CN . callSerially (() -> { if ( cm . isEntitled ( "pro" )) { unlockProFeatures (); } }); }). start (); refresh() validates the current receipts with the cloud when the build has a build_key and commerce is enabled. In a local build or simulator, it safely falls back to the normal

2026-07-13 原文 →
AI 资讯

How a Simple Screen Share Feature Turned Into a WebRTC Rabbit Hole

Introduction I've spent way too much time trying to come up with some generic introduction for this story, but then I realized none of you probably want to read that anyway. So instead, I'll just jump straight into the story—which is why you're here in the first place. The day I received the requirements The story begins when I received the requirements for a new feature that allows Teachers to share their presentation to review slides before the Lecture begins, so we would have teachers aids using the web version and seeing a screenshare from the main pc powerpoint, at first I thought maybe we can use HLS or RTMP for this and be okay with the 3 seconds delay that it has, but then I continued reading the ticket, we also needed the user to move to the next and previous slides via the web application, which immediately threw my initial idea out of the window. This is because if the user needs to interact with the application there is no way it will be usable without almost immediate feedback. Since we needed to show this to the client quickly we had 2 weeks to implement this feature, so before I did anything, I stopped and started drafting a simple design doc, which besides the fancy name was really just a document with my raw notes taken from research and comparisons between different solutions. After spending some time doing research and looking into different architectures and engineering blogs from companies like Twitch, Slack and Discord, I narrowed the possibilities down to four common architectures used for this type of use case. Architecture Options P2P Mesh This approach revolved around a user establishing WebRTC connections with every other user in the room. Besides being difficult to manage in terms of connections and sessions, it had one fatal flaw: network and CPU overhead. If we had twenty users in the room, every participant would maintain nineteen separate peer connections while sending nineteen streams, quickly consuming both CPU and bandwidth. MCU (M

2026-07-13 原文 →
AI 资讯

Java News Roundup: TornadoVM 5, JHipster, Google ADK, OmniFish Build of Payara, Introducing Vidocq

This week's Java roundup for July 6th, 2026, features news highlighting: the GA release of TornadoVM 5.0; point releases of JHipster, Keycloak and Google ADK; maintenance releases of GraalVM Native Build Tools and Micronaut; the OmniFish Build of Payara and introducing Vidocq, a new implementation of the Jakarta EE 11 Core Profile and MicroProfile 7.1. By Michael Redlich

2026-07-13 原文 →