1<!doctype html> 2<html lang="en"> 3 <head> 4 <meta charset="UTF-8" /> 5 <link rel="icon" type="image/png" href="/favicon-96x96.png?v=20260805" sizes="96x96" /> 6 <link rel="icon" type="image/svg+xml" href="/favicon.svg?v=20260805" /> 7 <link rel="shortcut icon" href="/favicon.ico?v=20260805" /> 8 <link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png?v=20260806" /> 9 <meta name="apple-mobile-web-app-title" content="LoopLingua" /> 10 <link rel="manifest" href="/site.webmanifest?v=20260805" /> 11 <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" /> 12 13 <!-- Primary Meta --> 14 <title>LoopLingua â Loop Lifelike Audio for Language Shadowing Practice</title> 15 <meta name="description" content="Type any English sentence and loop lifelike AI audio for shadowing practice. Spanish, Mandarin, German, Japanese, Italian, and French. CEFR, HSK, and JLPT level targeting. Anki and Quizlet export. Free to start. More languages coming soon." /> 16 <meta name="keywords" content="shadowing practice, language shadowing tool, listen and repeat, loop audio practice, AI voice audio, text to speech audio, language audio generator, Spanish shadowing, Spanish listening practice, CEFR Spanish, English to Spanish audio, Spanish A1 A2 B1 C1, Mandarin shadowing, Chinese shadowing practice, pinyin audio generator, HSK 1 to 6 practice, English to Mandarin audio, German shadowing, Deutsch A1 A2 B1, English to German audio, Japanese shadowing, JLPT N5 N4 N3, English to Japanese audio, Italian shadowing, Italian listening practice, CEFR Italian, English to Italian audio, Italian A1 A2 B1, French shadowing, French listening practice, CEFR French, English to French audio, French A1 A2 B1, Anki audio export, Quizlet export, language fluency practice, comprehensible input audio, spaced repetition audio" /> 17 <meta name="author" content="LoopLingua" /> 18 <meta name="robots" content="index, follow" /> 19 <link rel="canonical" href="https://looplingua.com" /> 20 21 <!-- Open Graph (Facebook, iMessage, LinkedIn, Slack) --> 22 <meta property="og:type" content="website" /> 23 <meta property="og:url" content="https://looplingua.com" /> 24 <meta property="og:site_name" content="LoopLingua" /> 25 <meta property="og:title" content="LoopLingua â Loop Lifelike Audio for Language Shadowing Practice" /> 26 <meta property="og:description" content="Type any English sentence and loop lifelike AI audio for shadowing. Spanish, Mandarin, German, Japanese, Italian, and French. CEFR, HSK, JLPT level targeting. Anki + Quizlet export." /> 27 <meta property="og:image" content="https://looplingua.com/og-image.png" /> 28 <meta property="og:image:width" content="1200" /> 29 <meta property="og:image:height" content="630" /> 30 <meta property="og:locale" content="en_US" /> 31 32 <!-- Twitter / X Card --> 33 <meta name="twitter:card" content="summary_large_image" /> 34 <meta name="twitter:site" content="@looplingua" /> 35 <meta name="twitter:title" content="LoopLingua â Loop Lifelike Audio for Language Shadowing Practice" /> 36 <meta name="twitter:description" content="Type any English sentence and loop lifelike AI audio for shadowing. Spanish, Mandarin, German, Japanese, Italian, and French. CEFR, HSK, JLPT level targeting. Anki + Quizlet export." /> 37 <meta name="twitter:image" content="https://looplingua.com/og-image.png" /> 38 39 <!-- Theme color (browser chrome on mobile) â Sky Frequency, matches 40 the landing hero and the in-app accent. --> 41 <!-- Matches the page background (not the accent) so the mobile status/URL bar 42 blends: light ground #f1efe9 / dark #14161b. Kept in sync live by the 43 pre-paint script below + applyMode() in src/theme.js. --> 44 <meta name="theme-color" content="#f1efe9" /> 45 46 <!-- Dark-mode bootstrap: set data-theme before first paint so users who 47 chose dark don't see a light flash. Mirrors resolveDark() in 48 src/theme.js. Default (unset key) is light, so this is a no-op for 49 everyone who hasn't opted in. --> 50
50<script> 51 (function () { 52 try { 53 var m = localStorage.getItem("ll_mode") || "light"; 54 var dark = m === "dark" || (m === "system" && 55 window.matchMedia("(prefers-color-scheme: dark)").matches); 56 if (dark) document.documentElement.setAttribute("data-theme", "dark"); 57 var mc = document.querySelector('meta[name="theme-color"]'); 58 if (mc) mc.setAttribute("content", dark ? "#14161b" : "#f1efe9"); 59 } catch (e) {} 60 })(); 61 </script>
61 62 63 <!-- Pre-paint dark canvas. darkmode.css (which sets the dark background) is 64 bundled via JS and loads late, so the root would flash white around the 65 app on load / sign-in. This critical rule is scoped to [data-theme=dark] 66 so it self-clears when the user switches to light at runtime. --> 67 <style> 68 /* Loading canvas = the theme background, so there's no white flash/border 69 before the app paints (Matt): light cream, dark grey. body margin:0 kills 70 the stray white frame from the browser default 8px margin. */ 71 html { background-color: #f1efe9; } 72 body { margin: 0; } 73 html[data-theme="dark"] { background-color: #14161b; color-scheme: dark; } 74 html[data-theme="dark"] body { background-color: #14161b; } 75 </style> 76 77 <!-- Fonts: Inter (UI everywhere, per DESIGN.md), LXGW WenKai (hanzi). 78 Manrope + Instrument Serif kept temporarily so other surfaces that 79 still reference them don't go bare while this feature branch 80 lands; remove once the system extract pass runs. --> 81 <link rel="preconnect" href="https://fonts.googleapis.com"> 82 <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> 83 <link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin> 84 <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=Manrope:wght@300;400;500;600;700;800&family=Hanken+Grotesk:wght@400;500;600;700;800&family=Schibsted+Grotesk:wght@400;500;600;700;800&family=Instrument+Serif:ital@0;1&display=swap"> 85 <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/style.css"> 86 87 <!-- Structured Data (Google rich results) --> 88
88<script type="application/ld+json"> 89 { 90 "@context": "https://schema.org", 91 "@type": "WebApplication", 92 "name": "LoopLingua", 93 "url": "https://looplingua.com", 94 "description": "Type any English sentence and loop lifelike AI audio for shadowing practice. Spanish, Mandarin, German, Japanese, Italian, and French. CEFR, HSK, and JLPT level targeting. Anki and Quizlet export.", 95 "applicationCategory": "EducationApplication", 96 "operatingSystem": "Web", 97 "inLanguage": ["en", "es", "zh", "de", "ja", "it", "fr"], 98 "offers": { 99 "@type": "Offer", 100 "price": "0", 101 "priceCurrency": "USD" 102 }, 103 "featureList": [ 104 "English to Spanish, Mandarin, German, Japanese, Italian, and French lifelike AI audio", 105 "Configurable shadowing loop with adjustable speed and gap", 106 "CEFR A1-C1 level targeting for Spanish, German, Italian, and French", 107 "HSK 1-6 level targeting and pinyin for Mandarin", 108 "JLPT N5-N1 level targeting and furigana for Japanese", 109 "Personal Looplist phrasebooks", 110 "Anki and Quizlet deck export", 111 "Shareable phrase links" 112 ] 113 } 114 </script>
114 115 116 <!-- Analytics (Google Analytics) + PostHog load only after cookie consent; 117 see src/lib/consent.js + src/ConsentBanner.jsx. Nothing tracker-related 118 is hardcoded here anymore. --> 119 120 <!-- Force Clerk avatar to Sky Frequency on the placeholder state. 121 The "purple" most users see is Clerk's default placeholder <img> 122 served from img.clerk.com (a purple-silhouette PNG). CSS backgrounds 123 can't override an image element â we hide the default image and let 124 the parent span's Sky background show through. Real profile photos 125 (Google OAuth) come from other CDNs and stay visible. --> 126 <style> 127 [class*="cl-"][class*="vatar"], 128 [class*="cl-avatarBox"], 129 [class*="cl-userButtonAvatar"], 130 [class*="cl-userPreviewAvatar"] { 131 background: #1cb0f6 !important; 132 background-color: #1cb0f6 !important; 133 background-image: none !important; 134 color: #ffffff !important; 135 border: 2px solid #ffffff !important; 136 font-weight: 700 !important; 137 display: inline-flex !important; 138 align-items: center !important; 139 justify-content: center !important; 140 text-transform: uppercase !important; 141 } 142 img[src*="img.clerk.com"], 143 img[srcset*="img.clerk.com"] { 144 display: none !important; 145 } 146 </style> 147
147<script type="module" crossorigin src="/assets/ConsentBanner-BdLO7qsc.js"></script>
147 148
148<script type="module" crossorigin src="/assets/main-BIH7H06y.js"></script>
148 149 <link rel="stylesheet" crossorigin href="/assets/ConsentBanner-C-YNuWDq.css"> 150 <link rel="stylesheet" crossorigin href="/assets/main-3gYDCBU8.css"> 151 </head> 152 <body> 153 <div id="root"></div> 154 </body> 155</html>
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.