<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Admin Supafast</title>
    <description>The latest articles on DEV Community by Admin Supafast (@supafast-tech).</description>
    <link>https://dev.to/supafast-tech</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4070835%2F7bb80f27-3cd6-4956-b120-81fb8db32588.png</url>
      <title>DEV Community: Admin Supafast</title>
      <link>https://dev.to/supafast-tech</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/supafast-tech"/>
    <language>en</language>
    <item>
      <title>Controlling a treadmill from an iPhone over Bluetooth LE</title>
      <dc:creator>Admin Supafast</dc:creator>
      <pubDate>Mon, 10 Aug 2026 16:06:32 +0000</pubDate>
      <link>https://dev.to/supafast-tech/controlling-a-treadmill-from-an-iphone-over-bluetooth-le-101k</link>
      <guid>https://dev.to/supafast-tech/controlling-a-treadmill-from-an-iphone-over-bluetooth-le-101k</guid>
      <description>&lt;p&gt;Most treadmills have a Bluetooth chip and a companion app nobody enjoys using. I wanted to drive the treadmill - speed, incline, live stats - from a clean SwiftUI app instead. That became &lt;a href="https://treadmillpro.app" rel="noopener noreferrer"&gt;Treadmill Pro&lt;/a&gt;, an iOS app that talks to the treadmill directly over Bluetooth Low Energy with CoreBluetooth. Here's what building a BLE hardware controller actually involves.&lt;/p&gt;

&lt;h2&gt;
  
  
  BLE in one paragraph
&lt;/h2&gt;

&lt;p&gt;A BLE device exposes &lt;em&gt;services&lt;/em&gt;, each containing &lt;em&gt;characteristics&lt;/em&gt; you can read, write, or subscribe to. Fitness equipment often speaks FTMS (the Fitness Machine Service), a standard set of characteristics for treadmills, bikes and rowers. In practice, support is uneven - some machines follow the spec, some ship their own quirks - so you discover services at runtime and adapt.&lt;/p&gt;

&lt;h2&gt;
  
  
  The connection lifecycle
&lt;/h2&gt;

&lt;p&gt;The unglamorous truth of BLE is that most of the work is state management:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Scan&lt;/strong&gt; for peripherals advertising the right service.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Connect&lt;/strong&gt; and &lt;strong&gt;discover&lt;/strong&gt; services and characteristics.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Subscribe&lt;/strong&gt; to the ones that stream data (speed, distance, time).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Write&lt;/strong&gt; to the control characteristic to change speed or incline.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Handle disconnects&lt;/strong&gt; - devices drop, users walk out of range, sessions end.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Every one of these steps can fail or stall, so the app is really a state machine with a treadmill on the other end.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reading stats vs sending commands
&lt;/h2&gt;

&lt;p&gt;Two directions, two different concerns:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Reading&lt;/strong&gt; is a subscription: the treadmill pushes notifications and you decode the bytes into speed, distance, time, calories. The decoding has to match the characteristic's data layout exactly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Writing&lt;/strong&gt; is a control request: you send a command to set speed or incline. Many machines require a "take control" handshake before they accept commands, and you have to respect their allowed ranges.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Lessons from talking to hardware
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Assume the spec is a suggestion.&lt;/strong&gt; Real devices deviate. Log raw packets and be defensive when decoding.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Make the state machine explicit.&lt;/strong&gt; Scanning, connecting, connected, reconnecting - model them directly instead of juggling booleans.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Never trust the connection.&lt;/strong&gt; Design for the treadmill vanishing mid-run; recover gracefully instead of hanging.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep the UI responsive during BLE work.&lt;/strong&gt; Connection and discovery are async; the interface should always show what's happening.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Takeaways
&lt;/h2&gt;

&lt;p&gt;BLE hardware apps are less about the flashy UI and more about robust connection handling and correct byte decoding. Get the state machine and the parsing right and the rest is easy.&lt;/p&gt;

&lt;p&gt;The app is at &lt;a href="https://treadmillpro.app" rel="noopener noreferrer"&gt;https://treadmillpro.app&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you've worked with CoreBluetooth or FTMS, I'm curious how you handle devices that ignore the standard - do you maintain per-device quirks, or try to stay generic?&lt;/p&gt;

</description>
      <category>ios</category>
      <category>swift</category>
      <category>bluetooth</category>
      <category>mobile</category>
    </item>
    <item>
      <title>Rendering a live 3D earthquake globe on iOS from the USGS feed</title>
      <dc:creator>Admin Supafast</dc:creator>
      <pubDate>Mon, 10 Aug 2026 15:53:44 +0000</pubDate>
      <link>https://dev.to/supafast-tech/rendering-a-live-3d-earthquake-globe-on-ios-from-the-usgs-feed-55ch</link>
      <guid>https://dev.to/supafast-tech/rendering-a-live-3d-earthquake-globe-on-ios-from-the-usgs-feed-55ch</guid>
      <description>&lt;p&gt;I wanted to see earthquakes the way they actually happen: as points lighting up on a spinning planet, in near real time. That became &lt;a href="https://earthquakes.site" rel="noopener noreferrer"&gt;Earthquake: Live Seismic Monitor&lt;/a&gt;, an iOS app that renders a 3D globe of recent quakes straight from the USGS feed. No backend of my own - just the public data and the device. Here's how it comes together.&lt;/p&gt;

&lt;h2&gt;
  
  
  The data source
&lt;/h2&gt;

&lt;p&gt;The USGS publishes earthquake data as GeoJSON feeds, updated continuously, at several time/magnitude cutoffs (past hour, past day, 2.5+, 4.5+, etc). Each feature has coordinates, magnitude, depth and time. That's everything you need to place a quake on a globe - no custom API required.&lt;/p&gt;

&lt;p&gt;The app polls the appropriate feed, diffs against what it already has, and updates the scene. Because USGS does the heavy lifting, the whole thing is effectively serverless from my side.&lt;/p&gt;

&lt;h2&gt;
  
  
  Putting quakes on a globe
&lt;/h2&gt;

&lt;p&gt;The core mapping problem is turning (latitude, longitude) into a point on a sphere. Once you have that, each earthquake becomes a marker whose size and color encode magnitude and depth, so a glance tells you "big and shallow" vs "small and deep".&lt;/p&gt;

&lt;p&gt;Design decisions that mattered:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Encode magnitude visually.&lt;/strong&gt; Radius and color do more than any label. A magnitude 6 should &lt;em&gt;look&lt;/em&gt; like a magnitude 6.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cluster sensibly.&lt;/strong&gt; Active regions produce swarms; markers need to stay readable when dozens land in one area.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep the globe interactive.&lt;/strong&gt; Rotate, zoom, tap a quake for details. It should feel like an object, not a chart.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Real-time without a server
&lt;/h2&gt;

&lt;p&gt;Every network-dependent app has to answer: what happens offline, and how fresh is "live"? My rules:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cache the last good feed so the globe still renders with no connection.&lt;/li&gt;
&lt;li&gt;Refresh on foreground and on an interval, and show the data's own timestamp so "live" is honest.&lt;/li&gt;
&lt;li&gt;Never block the UI on the network - render what you have, then update.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why no backend
&lt;/h2&gt;

&lt;p&gt;It's tempting to proxy the feed through your own server "for control". But USGS is reliable, public, and built for exactly this. Skipping a backend meant no servers to run, no scaling to worry about, and no place for me to introduce staleness. The device talks to the source directly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Great public datasets (USGS here) can carry an entire app - look for them before building infrastructure.&lt;/li&gt;
&lt;li&gt;Encode the important variable (magnitude) into shape and color, not text.&lt;/li&gt;
&lt;li&gt;Be honest about "real time": show the source timestamp instead of implying instant.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The app is at &lt;a href="https://earthquakes.site" rel="noopener noreferrer"&gt;https://earthquakes.site&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you've built globe or map visualizations, I'd love to hear how you handle dense clusters of points without the map turning to mush.&lt;/p&gt;

</description>
      <category>ios</category>
      <category>swift</category>
      <category>dataviz</category>
      <category>mobile</category>
    </item>
    <item>
      <title>Generating daily horoscopes and zodiac videos with an automated AI pipeline</title>
      <dc:creator>Admin Supafast</dc:creator>
      <pubDate>Mon, 10 Aug 2026 15:47:33 +0000</pubDate>
      <link>https://dev.to/supafast-tech/generating-daily-horoscopes-and-zodiac-videos-with-an-automated-ai-pipeline-1b83</link>
      <guid>https://dev.to/supafast-tech/generating-daily-horoscopes-and-zodiac-videos-with-an-automated-ai-pipeline-1b83</guid>
      <description>&lt;p&gt;Astrology content has a brutal property: it has to be fresh &lt;em&gt;every single day&lt;/em&gt;, for every sign, ideally in a few languages, forever. Writing that by hand doesn't scale. For &lt;a href="https://astrozodify.com" rel="noopener noreferrer"&gt;AstroZodify&lt;/a&gt; I built a pipeline that generates daily horoscopes and short zodiac videos on a schedule, with humans reviewing rather than writing. Here's the shape of it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The content problem
&lt;/h2&gt;

&lt;p&gt;Per day you need: 12 signs x N content types (daily horoscope, love, career) x M languages. That's hundreds of pieces of copy a day that all have to feel written, not templated, and stay consistent with each sign's "voice".&lt;/p&gt;

&lt;p&gt;Templating alone reads robotic. Free-form generation drifts. The trick is constraining an LLM enough to stay on-brand while still sounding human.&lt;/p&gt;

&lt;h2&gt;
  
  
  The generation pipeline
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Structured prompts per sign.&lt;/strong&gt; Each sign has a persona and constraints (tone, themes, length). The model fills the daily specifics, not the whole thing from scratch.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scheduled batch runs.&lt;/strong&gt; A cron job kicks off generation ahead of time so content is ready before it's needed, never on the critical path of a page request.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Validation.&lt;/strong&gt; Output is checked for length, banned phrasing, and structure before it's allowed near the site.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Store, then serve.&lt;/strong&gt; Everything lands in Postgres. Pages are SSR and just read pre-generated rows, so the LLM is never in the user's request path.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Keeping generation &lt;em&gt;offline&lt;/em&gt; from serving is the single most important decision - it keeps pages fast and costs predictable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding video
&lt;/h2&gt;

&lt;p&gt;Text was step one. Short vertical zodiac videos (for social) are step two, and that's a heavier pipeline: script -&amp;gt; imagery -&amp;gt; voiceover -&amp;gt; render. That part runs on Cloud Run as a separate job so a slow render never touches the web app, and we pilot one item before any batch.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cost and safety rails
&lt;/h2&gt;

&lt;p&gt;Anything that calls a paid API in a loop is a footgun. The rules I follow:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Always pilot on 1-10 items before a full batch.&lt;/li&gt;
&lt;li&gt;Never an unbounded loop against a paid API.&lt;/li&gt;
&lt;li&gt;Cache and pre-generate so serving is basically free.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Separate &lt;em&gt;generation&lt;/em&gt; from &lt;em&gt;serving&lt;/em&gt;. Pre-generate on a schedule, serve static rows.&lt;/li&gt;
&lt;li&gt;Constrain the model with per-entity personas instead of free-form prompts.&lt;/li&gt;
&lt;li&gt;Treat video as its own isolated pipeline, not an extension of the text one.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can see the output at &lt;a href="https://astrozodify.com" rel="noopener noreferrer"&gt;https://astrozodify.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you're generating large volumes of scheduled content, I'd love to compare notes on validation - how do you catch a bad generation before it ships?&lt;/p&gt;

</description>
      <category>ai</category>
      <category>python</category>
      <category>automation</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Building an AI translator that lives everywhere on macOS, iOS and Chrome</title>
      <dc:creator>Admin Supafast</dc:creator>
      <pubDate>Mon, 10 Aug 2026 15:43:24 +0000</pubDate>
      <link>https://dev.to/supafast-tech/building-an-ai-translator-that-lives-everywhere-on-macos-ios-and-chrome-36jf</link>
      <guid>https://dev.to/supafast-tech/building-an-ai-translator-that-lives-everywhere-on-macos-ios-and-chrome-36jf</guid>
      <description>&lt;p&gt;Most translation tools make you leave what you're doing: copy text, switch to a tab or app, paste, read, copy back. I wanted translation to sit &lt;em&gt;inside&lt;/em&gt; whatever I was already using. That turned into &lt;a href="https://linguin.app" rel="noopener noreferrer"&gt;Linguin&lt;/a&gt;, an AI translator with a native Mac app, an iPhone app, and a Chrome extension. Here's how I think about building the "same" product across three very different surfaces.&lt;/p&gt;

&lt;h2&gt;
  
  
  One idea, three surfaces
&lt;/h2&gt;

&lt;p&gt;The product promise is identical everywhere: select text, get a fast, context-aware translation in 100+ languages. But the &lt;em&gt;interaction&lt;/em&gt; has to be native to each platform, or it feels wrong:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;macOS&lt;/strong&gt;: a menu-bar app plus a global hotkey. Select text anywhere, hit the shortcut, get an overlay. The whole point is that you never switch apps.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;iOS&lt;/strong&gt;: a share-sheet extension and keyboard, so translation is one tap from any app instead of a context switch to a separate screen.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Chrome&lt;/strong&gt;: an extension that translates selections and full pages in place, keeping layout intact.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Same core, three genuinely different UX shells.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keeping the core in one place
&lt;/h2&gt;

&lt;p&gt;The translation logic - language detection, prompt construction, tone handling, caching - is the part you never want to fork. If Mac and iOS drift, you get subtly different translations for the same input, which erodes trust fast.&lt;/p&gt;

&lt;p&gt;So the model-facing logic lives behind one small service contract, and each client is a thin shell that owns only its platform UX. A translation request looks the same whether it comes from the menu bar, the share sheet, or a browser selection.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why "AI" translation instead of a classic API
&lt;/h2&gt;

&lt;p&gt;Classic MT is great at literal accuracy but blind to context. "Book" in a travel app and "book" in a library app should not translate the same way. Passing the surrounding context and a tone hint (formal, casual, technical) to an LLM produces translations that read like a human wrote them, not a dictionary.&lt;/p&gt;

&lt;p&gt;The tradeoffs I had to design around:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Latency&lt;/strong&gt;: users expect near-instant results, so caching and streaming matter a lot.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consistency&lt;/strong&gt;: same input should give the same output, so requests are normalized and cached aggressively.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cost&lt;/strong&gt;: batching and caching keep per-translation cost sane.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Lessons so far
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Ship the platform-native interaction first. A technically perfect translation behind a clunky flow loses to a decent translation that's one keystroke away.&lt;/li&gt;
&lt;li&gt;Centralize the model logic early, before the clients diverge.&lt;/li&gt;
&lt;li&gt;Context and tone are where AI translation actually beats the old tools - lean into that, not raw language count.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you want to try it, the Mac app, iOS app and Chrome extension are all at &lt;a href="https://linguin.app" rel="noopener noreferrer"&gt;https://linguin.app&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Curious how others structure a shared core across native + web clients - do you go with a shared service, a shared package, or just accept some duplication?&lt;/p&gt;

</description>
      <category>ai</category>
      <category>macos</category>
      <category>swift</category>
      <category>productivity</category>
    </item>
    <item>
      <title>How I track whether ChatGPT, Claude and Perplexity recommend my product</title>
      <dc:creator>Admin Supafast</dc:creator>
      <pubDate>Mon, 10 Aug 2026 15:41:37 +0000</pubDate>
      <link>https://dev.to/supafast-tech/how-i-track-whether-chatgpt-claude-and-perplexity-recommend-my-product-4969</link>
      <guid>https://dev.to/supafast-tech/how-i-track-whether-chatgpt-claude-and-perplexity-recommend-my-product-4969</guid>
      <description>&lt;p&gt;When people look for software today, a growing share of them never touch Google. They ask ChatGPT, Claude, Perplexity or Gemini "what's the best tool for X?" and take the answer at face value. If your product isn't in that answer, you're invisible to those users, and you have no idea it's happening.&lt;/p&gt;

&lt;p&gt;I kept running into this with our own products, so I built &lt;a href="https://askairank.com" rel="noopener noreferrer"&gt;AskAiRank&lt;/a&gt; to measure it. This post is about the problem and how the tracking actually works under the hood.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem: AI answers are a black box
&lt;/h2&gt;

&lt;p&gt;Classic SEO gives you rank trackers, Search Console, backlinks. For AI assistants there's almost nothing. You can't see:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Whether a model mentions your brand when asked about your category&lt;/li&gt;
&lt;li&gt;Where you land relative to competitors in that answer&lt;/li&gt;
&lt;li&gt;Which sources the model cites to justify its recommendation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And the answers aren't deterministic. Ask the same question twice and you can get different tools, different ordering, different citations. So a single manual check tells you nothing, you need to sample over time.&lt;/p&gt;

&lt;h2&gt;
  
  
  How the tracking works
&lt;/h2&gt;

&lt;p&gt;The core loop is simple:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Prompts.&lt;/strong&gt; You define a set of buyer-intent prompts for your category, e.g. "best AI translation app for Mac" or "tools to monitor earthquakes".&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Run across models.&lt;/strong&gt; Each prompt is sent to ChatGPT, Claude, Perplexity and Gemini on a schedule, so we sample the distribution rather than a single roll.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Parse the response.&lt;/strong&gt; For each answer we extract brand mentions, their position in the list, sentiment, and any cited source URLs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Score and compare.&lt;/strong&gt; Mentions and positions roll up into a visibility score per model, and you can add competitors to see share of voice.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Alert on drift.&lt;/strong&gt; When your visibility drops or a competitor overtakes you, you get notified.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The parsing is the hard part. Model output is prose, not JSON, so mention detection has to handle aliases, partial names, "also worth checking out X" asides, and citations that live in footnotes or inline links. It's the piece I'm still iterating on the most.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stack
&lt;/h2&gt;

&lt;p&gt;Nothing exotic:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Next.js&lt;/strong&gt; frontend&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Self-hosted Postgres + PostgREST&lt;/strong&gt; for data and API&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Python workers&lt;/strong&gt; that call the four model APIs and do the parsing/scoring&lt;/li&gt;
&lt;li&gt;Scheduled runs so the sampling happens without anyone clicking a button&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why this matters (AEO / GEO)
&lt;/h2&gt;

&lt;p&gt;People are starting to call this AEO (Answer Engine Optimization) or GEO (Generative Engine Optimization). The name matters less than the shift: recommendation is moving from ranked blue links to a single synthesized answer. If you ship a product, it's worth knowing where you stand in that answer, the same way you'd check your Google rank.&lt;/p&gt;

&lt;p&gt;If you want to try it on your own product, there's a free plan (no credit card): &lt;a href="https://askairank.com" rel="noopener noreferrer"&gt;https://askairank.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'd genuinely love feedback, especially from anyone who has tackled mention-detection in free-form LLM output. Where does your approach break?&lt;/p&gt;

</description>
      <category>ai</category>
      <category>seo</category>
      <category>saas</category>
      <category>startup</category>
    </item>
  </channel>
</rss>
