diff --git a/apps/api/src/sources/750g.ts b/apps/api/src/sources/750g.ts
new file mode 100644
index 0000000..1b46497
--- /dev/null
+++ b/apps/api/src/sources/750g.ts
@@ -0,0 +1,389 @@
+import type {
+ ParsedRecipe,
+ RecipeSourceAdapter,
+ RecipeSourceListItem,
+ RecipeSourceListParams,
+ RecipeSourceListResult,
+} from "../lib/recipe-sources/recipe-source-adapter.js";
+import {
+ RecipeSourceFetchError,
+ RecipeSourceParseError,
+} from "../lib/recipe-sources/recipe-source-errors.js";
+import { jsonLdRecipeAdapter } from "./json-ld-recipe.js";
+
+const SOURCE_KEY = "750g";
+
+// 750g.com's own site search is a client-side widget (results are fetched
+// by the page's own JS after load, nothing server-rendered to scrape) — but
+// that JS itself calls this plain GET endpoint, an "AI answer engine" that
+// returns an HTML fragment of recipe cards for a free-text query. Verified
+// live: works with a bare `fetch`, no special headers/cookies/session
+// needed, same as every other adapter in this family.
+const SEARCH_URL = "https://www.750g.com/genius/query/";
+
+/**
+ * Matches every `` block —
+ * same shape as `JSON_LD_SCRIPT_PATTERN` in json-ld-recipe.ts, kept as its
+ * own private copy here rather than sharing that module's export: this one
+ * does textual surgery on the *raw HTML* before `jsonLdRecipeAdapter` ever
+ * sees it (see {@link sanitizeJsonLdBlocks} below), a different concern
+ * from extracting-and-parsing blocks into objects.
+ */
+const JSON_LD_SCRIPT_PATTERN =
+ /(