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

标签:#Google

找到 294 篇相关文章

AI 资讯

I Built a Web App That Finds the Fairest Meeting Spot for Any Group (and It's Free)

The Problem Nobody Talks About Picture this: You're trying to find a place to meet up with friends. Someone suggests a coffee shop. It's 8 minutes from their house. It's 45 minutes from yours. You say yes anyway, because suggesting a different place feels awkward. This happens all the time — with friends, with remote teams, with family scattered across a city. And the worst part? Most "meet in the middle" suggestions aren't actually in the middle. They're just the geographic midpoint, which completely ignores traffic, transit options, and the fact that roads don't go in straight lines. I got frustrated enough to build something about it. Meet Meetle Meetle is a free web app that finds the fairest meeting spot for any group of people — based on real travel times , not just distance. A Chrome Extension is coming soon so you'll have it one click away in your toolbar. You add everyone's starting location, choose how each person is traveling (driving, walking, or transit), hit Find Meeting Point , and Meetle does the math across every person simultaneously. It then surfaces the best nearby cafés, restaurants, parks, gyms, or whatever venue type you're looking for — ranked by actual fairness. No more "it's fine, I don't mind the drive." Now you have data. How It Actually Works Under the hood, Meetle uses three Google Maps APIs working together: Distance Matrix API calculates travel time from every person's location to every candidate venue, simultaneously. This is the core of the fairness scoring — you can't rank venues fairly without knowing everyone's actual travel time to each one. Places API finds candidate venues near the calculated center point. You can filter by type (coffee, food, parks, gyms, etc.), price level, minimum rating, and whether they're open right now. Maps JavaScript API renders everything visually — the map, the travel zones (isochrones), and the markers for each suggested venue. The scoring works two ways and you can toggle between them: Fairness mo

2026-06-14 原文 →
AI 资讯

I Built a Coding Mascot Generator with Google AI Studio — Meet Octo-Byte! 🐙

This post is my submission for DEV Education Track: Build Apps with Google AI Studio . What I Built I built MascotCraft Studio , an app that generates a cute mascot character for a coding/tutorial brand using Imagen for the visuals and Gemini for the name and personality bio. Here's the prompt I used: "Please create an app that generates a cute mascot character for a coding/tutorial brand, using Imagen for the visuals and Gemini to create a name and short personality description for the mascot. The user should be able to type in a few style keywords (like 'friendly owl', 'cool robot', 'cheerful fox') and get a unique mascot image along with its name and bio." Gemini went well beyond the basic ask — it added a "Character Designer" with quick preset ideas (Wise Python Owl, Cyberpunk JS Fox, Debugging Robo Kitty, and more), color palette options, multiple visual rendering styles (3D Chibi Toy, Minimal Vector, 16-Bit Retro Pixel, Circular Badge), and even a "Studio Gallery Showcase" using localStorage to save and revisit previously generated mascots. Demo 🔗 Live app: https://cute-coding-mascot-generator-924052444918.us-east1.run.app Using the "3D Chibi Toy" style with keywords for a friendly coding octopus, the app generated Octo-Byte — "Asynchronous learning, multi-threaded fun!" A cheerful deep-sea developer who discovered that having eight arms makes multitasking a breeze, whose tech specialty is multi-threaded asynchronous architecture, and whose favorite pastimes include typing on four mechanical keyboards at once. The artwork came out as a glossy 3D chibi-style purple octopus wearing glasses, sitting in front of a tiny code editor. My Experience Watching Gemini's "Thinking" process work through the build was the most interesting part — it planned out the UI sections, color palettes, and visual styles, then added bonus features I never asked for, like the gallery save feature. The whole thing went from a single paragraph prompt to a fully deployed, live web app in

2026-06-13 原文 →
AI 资讯

Switch an old script from Rhino to the V8 runtime

Originally written for bulldo.gs — republished here with the canonical link pointing home. I want to enable the V8 runtime on an existing Apps Script project so I can use modern JavaScript, but I am worried about breaking things that are already working. // appsscript.json — set runtimeVersion to enable V8 // Rollback: change V8 back to DEPRECATED_ES5 { " timeZone " : " America/New_York " , " dependencies " : {}, " exceptionLogging " : " STACKDRIVER " , " runtimeVersion " : " V8 " } // Code.gs — safe V8-compatible replacement for a common Rhino pattern // Rhino allowed: for each (var item in collection) {} // V8 requires standard for...of instead function listSheetNames () { var ss = SpreadsheetApp . getActiveSpreadsheet (); var names = []; var sheets = ss . getSheets (); for ( var i = 0 ; i < sheets . length ; i ++ ) { names . push ( sheets [ i ]. getName ()); } Logger . log ( names . join ( ' , ' )); } The one-line change and why it is a project-wide bomb Open the Apps Script editor, click Project Settings (the gear icon), and check "Show appsscript.json manifest file in editor." Then open that file and change "runtimeVersion": "DEPRECATED_ES5" to "runtimeVersion": "V8" . Save. That is the entire migration from a settings standpoint. What catches people off guard is the failure mode. V8 parses every .gs file in the project as a unit before running anything. One Rhino-only statement — a for each loop, a __iterator__ method, a Date.prototype.getYear call in an otherwise untouched utility file — causes a syntax or runtime error that prevents the whole script from initializing. Not just the file that contains the bad line. Every function, every trigger, the entire project goes dark. The first time I hit this it took me twenty minutes to figure out why a completely unrelated trigger had stopped firing. The error message pointed at the Rhino syntax in a helper file I had not touched in two years. V8 does not isolate the damage; it fails at parse time, before any executi

2026-06-13 原文 →
AI 资讯

Fix "Exceeded maximum execution time" in Apps Script

Originally written for bulldo.gs — republished here with the canonical link pointing home. I'm running a script that processes a large spreadsheet and it keeps dying with "Exceeded maximum execution time" before it finishes. // Checkpoint-resume pattern for long-running sheet jobs function processInBatches () { var props = PropertiesService . getScriptProperties (); var startRow = parseInt ( props . getProperty ( ' lastRow ' ) || ' 2 ' , 10 ); var sheet = SpreadsheetApp . getActiveSpreadsheet (). getActiveSheet (); var lastDataRow = sheet . getLastRow (); var BATCH = 200 ; var SAFE_MS = 5 * 60 * 1000 ; var started = Date . now (); var endRow = Math . min ( startRow + BATCH - 1 , lastDataRow ); var data = sheet . getRange ( startRow , 1 , endRow - startRow + 1 , 5 ). getValues (); for ( var i = 0 ; i < data . length ; i ++ ) { if ( Date . now () - started > SAFE_MS ) { props . setProperty ( ' lastRow ' , String ( startRow + i )); return ; } // process data[i] here } if ( endRow >= lastDataRow ) { props . deleteProperty ( ' lastRow ' ); deleteTrigger_ (); } else { props . setProperty ( ' lastRow ' , String ( endRow + 1 )); } } The 6-minute wall is per-execution, not per-task Apps Script enforces a hard 6-minute execution time limit per run, regardless of whether you're on a free account or a Workspace account (which bumps the limit to 30 minutes, but the same cliff exists). The error doesn't mean your logic is wrong; it means one continuous call to your function took too long. The fix is to stop thinking of your job as a single execution and start thinking of it as a pipeline of short runs. The first time I hit this, I wasted an afternoon trying to speed up the loop. Marginal gains didn't move the needle because the data volume was the real problem — 4,000 rows at one Sheets API call per row will always breach 6 minutes. The correct frame is: how do I save where I stopped and pick up there next run? Saving and restoring a cursor with PropertiesService PropertiesServic

2026-06-13 原文 →
开发者

Merge multiple docs into one in Google Docs

Originally written for bulldo.gs — republished here with the canonical link pointing home. I want to programmatically combine several Google Docs into one file without losing tables or list formatting. // Merges all source docs into destDocId, in order. // Run from the Apps Script editor; no triggers needed. function mergeDocs () { var sourceIds = [ ' DOC_ID_ONE ' , ' DOC_ID_TWO ' , ' DOC_ID_THREE ' ]; var dest = DocumentApp . openById ( ' DEST_DOC_ID ' ). getBody (); for ( var i = 0 ; i < sourceIds . length ; i ++ ) { var srcBody = DocumentApp . openById ( sourceIds [ i ]). getBody (); var total = srcBody . getNumChildren (); for ( var j = 0 ; j < total ; j ++ ) { var el = srcBody . getChild ( j ); var type = el . getType (); if ( type === DocumentApp . ElementType . PARAGRAPH ) { dest . appendParagraph ( el . asParagraph (). copy ()); } else if ( type === DocumentApp . ElementType . TABLE ) { dest . appendTable ( el . asTable (). copy ()); } else if ( type === DocumentApp . ElementType . LIST_ITEM ) { dest . appendListItem ( el . asListItem (). copy ()); } } } } Why there is no single appendElement call The Document service in Apps Script does not expose a generic appendElement method on Body . Every element type has its own typed append method: appendParagraph , appendTable , appendListItem , and so on. That means a merge loop that ignores element types will throw TypeError: el.copy is not a function the moment it hits a table, because you would be passing an Element where the API expects a Table . The fix is to call getType() on each child element and switch on DocumentApp.ElementType . The type enum values are strings like PARAGRAPH , TABLE , LIST_ITEM , INLINE_IMAGE , and HORIZONTAL_RULE . In practice the first three account for almost all real document content. The code above handles those three and silently skips anything else (images, rules) rather than crashing the entire merge. Getting the doc IDs and running the script The ID for any Google Doc is the lo

2026-06-13 原文 →
AI 资讯

Import JSON from an API in Google Sheets

Originally written for bulldo.gs — republished here with the canonical link pointing home. I want to pull live JSON data from an API endpoint directly into a Google Sheet without installing an add-on. // Fetch JSON from an API and write it to the active sheet // Adjust API_URL and the field list to match your endpoint function importJsonFromApi () { var API_URL = ' https://jsonplaceholder.typicode.com/users ' ; var sheet = SpreadsheetApp . getActiveSpreadsheet (). getActiveSheet (); var response = UrlFetchApp . fetch ( API_URL ); var raw = response . getContentText (); var data = JSON . parse ( raw ); var headers = [ ' id ' , ' name ' , ' username ' , ' email ' , ' phone ' ]; var rows = data . map ( function ( obj ) { return headers . map ( function ( key ) { return obj [ key ] || '' ; }); }); sheet . clearContents (); sheet . getRange ( 1 , 1 , 1 , headers . length ). setValues ([ headers ]); sheet . getRange ( 2 , 1 , rows . length , headers . length ). setValues ( rows ); } Why getContentText() comes before JSON.parse UrlFetchApp.fetch() returns an HTTPResponse object, not a string. The first time I skipped getContentText() and passed the response object directly to JSON.parse(), it silently parsed to null and the sheet wrote nothing. You need raw = response.getContentText() to get the actual body as a string, then JSON.parse(raw) turns it into a JavaScript object or array. The URL must be publicly accessible or accept an API key via a query parameter or Authorization header. Add headers like this: UrlFetchApp.fetch(url, { headers: { Authorization: 'Bearer ' + token } }). Apps Script's UrlFetchApp quota is 20,000 calls per day on a free Google account, 100,000 on Workspace. The rectangular array constraint — why setValues fails without mapping setValues() is strict: it requires a 2D array where every row has the same number of columns. If you hand it an array of plain JSON objects, it throws 'The number of rows or columns in the range does not match the number of

2026-06-13 原文 →
AI 资讯

Send personalized emails from a sheet in Gmail

Originally written for bulldo.gs — republished here with the canonical link pointing home. I have a spreadsheet of names and email addresses and I want to send each person a personalized message from my Gmail account without copy-pasting or using a paid tool. // Mail merge: Sheet cols A=Name, B=Email, C=Sent // Run from Apps Script; authorize Gmail + Sheets scopes function sendMerge () { var sheet = SpreadsheetApp . getActiveSheet (); var rows = sheet . getDataRange (). getValues (); var quota = MailApp . getRemainingDailyQuota (); var sent = 0 ; for ( var i = 1 ; i < rows . length ; i ++ ) { if ( rows [ i ][ 2 ] === ' Sent ' ) continue ; if ( sent >= quota ) { Logger . log ( ' Quota reached at row ' + ( i + 1 )); break ; } var name = rows [ i ][ 0 ]; var email = rows [ i ][ 1 ]; var subject = ' Hey ' + name + ' , here is your update ' ; var body = ' Hi ' + name + ' , \n\n Your personalized content goes here. \n\n Thanks ' ; MailApp . sendEmail ( email , subject , body ); sheet . getRange ( i + 1 , 3 ). setValue ( ' Sent ' ); sent ++ ; } } Set up your sheet and open the script editor Put names in column A, email addresses in column B, and leave column C blank — the script writes 'Sent' there as it goes. Header row in row 1 is assumed; the loop starts at index 1 (row 2) to skip it. Open the script editor from Extensions > Apps Script, paste the function, and save. The first time you run sendMerge() Google will ask you to authorize two scopes: Sheets (read/write the active spreadsheet) and Gmail (send mail on your behalf). Both are required. If you only see a Sheets prompt, delete the file and re-paste — a cached partial authorization sometimes skips the Gmail scope on older script files. Why the Sent column is the whole point Consumer Google accounts cap at roughly 100 outgoing recipients per 24-hour rolling window via MailApp. If your list has 200 rows and you run the script at 11 pm, it will send 100 and log 'Quota reached at row 101'. Without the Sent check, a sec

2026-06-13 原文 →
开发者

Remove duplicate rows in Google Sheets

Originally written for bulldo.gs — republished here with the canonical link pointing home. I have a Google Sheet with duplicate rows and I want to remove them programmatically, either on demand or on a schedule, without destroying the rest of my data. // removeDuplicates.gs — dedup active sheet, keep first occurrence // Run from Extensions > Apps Script, or bind to a trigger. function removeDuplicateRows () { var sheet = SpreadsheetApp . getActiveSheet (); var data = sheet . getDataRange (). getValues (); var seen = new Set (); var unique = []; for ( var i = 0 ; i < data . length ; i ++ ) { var key = data [ i ]. join ( ' | ' ); if ( ! seen . has ( key )) { seen . add ( key ); unique . push ( data [ i ]); } } sheet . clearContents (); sheet . getRange ( 1 , 1 , unique . length , unique [ 0 ]. length ). setValues ( unique ); } Why rewrite instead of delete The instinct when deduplicating is to loop through the sheet and call deleteRow on each duplicate. That works, but it has a sharp edge: every call to deleteRow shifts all rows below it up by one. If you delete row 3, what was row 4 is now row 3, and your loop index is already pointing at the new row 4. The safe workaround people reach for is iterating bottom-to-top, which works but means holding the full duplicate set in memory anyway, making one API call per deleted row. The approach here sidesteps the problem entirely. Read everything once with getDataRange().getValues() — a single API call that returns a 2D array. Build the deduplicated array in JavaScript using a Set to track which row fingerprints you have already seen. Then clear the sheet and write the result back with one setValues call. Two API calls total, regardless of how many duplicates you had. For a 10,000-row sheet, this is the difference between a script that finishes in two seconds and one that times out at the six-minute Apps Script execution limit. The row key is built with data[i].join('|'). The pipe character works as a separator in practice; i

2026-06-13 原文 →
AI 资讯

Congrats to the Google I/O 2026 Writing Challenge Winners!

We are so excited to announce the winners of the Google I/O 2026 Writing Challenge ! We asked you to explore the announcements from Google I/O 2026 and share your thoughts and firsthand takes. Wow, you delivered. The quality and depth of submissions genuinely impressed our team. From hands-on walkthroughs to bold opinions on what the announcements really mean for developers, the entries were thoughtful, original, and packed with insight. Thank you to everyone who participated. Your writing helps make this community one of the best places on the internet to learn what's actually happening in tech. Now, let's celebrate our five winners! 🎉 🏆 Congratulations To… The Sleeper Announcement from Google I/O 2026 That Will Change How We Think About Apps Google I/O Writing Challenge Submission Vrushali Vrushali Vrushali Follow May 24 The Sleeper Announcement from Google I/O 2026 That Will Change How We Think About Apps # devchallenge # googleiochallenge # android # kotlin 7 reactions 2 comments 7 min read @vrushali_dev_15 wrote a standout deep-dive into AppFunctions — Android's new API for exposing app capabilities directly to AI agents. With 10 years of Android experience behind the lens, this post goes far beyond the surface announcement to map out the full architectural shift this signals and what developers should be thinking about right now, even before shipping a single AppFunction. I gave Gemini 3.5 Flash a CVE-fix PR to review. It found another bug in the same file. Google I/O Writing Challenge Submission Vicente Junior Vicente Junior Vicente Junior Follow May 22 I gave Gemini 3.5 Flash a CVE-fix PR to review. It found another bug in the same file. # googleiochallenge # devchallenge # ai # gemini 9 reactions 1 comment 7 min read @vicente_junior_dev did something rare: actually tested the thing. Running Gemini 3.5 Flash across 3 real production PRs, including a CVE fix, the post documents what the model caught. Grounded, honest, and exactly the kind of first-person expe

2026-06-11 原文 →
AI 资讯

Debugging the Google Maps Duplicate Loading Bug in React

Originally published on clintech.me If you've integrated Google Maps into a React app and seen Autocomplete randomly stop working, Directions silently fail, or the API throw google is not defined on second render — you've hit the duplicate loading bug. Here's exactly what caused it in my case and how I fixed it. The setup that broke things While building delivery address flows at POLOM — a production e-commerce platform — I integrated Google Places Autocomplete across 20+ screens. I had the Maps JavaScript API loading in two places: A provider.tsx for global script loading across the app A useLoadGoogleMaps hook inside a shared component This caused race conditions. The Autocomplete and Directions APIs were initialising before the script fully resolved in some renders, silently failing in others. The failure wasn't consistent, which made it harder to catch. The fix Step 1 — Remove the global load Delete the script tag or next/script call in provider.tsx . There should be exactly one place the Maps API loads. Step 2 — Centralise in a hook Move all loading logic into a single useLoadGoogleMaps hook using dynamic loading. If you're on Next.js, next/script with strategy="afterInteractive" inside the hook is the right approach. Step 3 — Guard before initialising if ( ! window . google ?. maps ) return ; Check that the API is fully available before attempting to attach Autocomplete or Directions . Don't assume the script load event means every namespace is ready. Step 4 — Scope your ref correctly Bind the autocomplete instance to inputRef.current explicitly. If the component remounts, re-initialise the binding — don't assume the previous instance is still attached. The result One load, one source of truth, no race conditions. Autocomplete and Directions worked consistently across all 20+ screens without reinitialising on every render. Security — the step most developers skip Restrict your API key at the Google Cloud Console level: HTTP referrers: whitelist your domain onl

2026-06-11 原文 →