From 9da5cee25c2faa1bb0d94a10fa2099b8fd52b1b5 Mon Sep 17 00:00:00 2001
From: Andres Estrada <105224908+andesvel@users.noreply.github.com>
Date: Tue, 22 Sep 2026 23:15:36 -0500
Subject: [PATCH 1/5] Replace vague marketing verbs with specific behavior
"Seamlessly" and "intelligently" describe a feeling instead of what
the product does. State the actual behavior: links open in native
apps instead of the in-app browser; expiry stops redirecting after
the date passes; click counts update as visitors arrive.
---
README.md | 2 +-
app/routes/home.tsx | 4 ++--
components/features.tsx | 8 ++++----
3 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/README.md b/README.md
index ef53a6a..bcd301d 100644
--- a/README.md
+++ b/README.md
@@ -39,7 +39,7 @@ The name "Nuto" comes from the Spanish word "diminuto" (tiny), reflecting its pu
## ✨ Key Features
- **In-App Browser Escape**: Detects when a link is opened inside an in-app browser (like Instagram) and redirects to the native system browser.
-- **Deep Linking**: Intelligently routes URLs to native applications like YouTube and Spotify for a seamless user experience.
+- **Deep Linking**: Opens YouTube, Spotify, and other supported links in their native apps instead of the in-app browser.
- **Password Protection**: Secure your links with a password.
- **Link Expiration**: Set an expiration date for temporary links.
- **Custom Short Codes**: Users can customize the short code for their links.
diff --git a/app/routes/home.tsx b/app/routes/home.tsx
index 9b3ca35..3c82eb3 100644
--- a/app/routes/home.tsx
+++ b/app/routes/home.tsx
@@ -15,7 +15,7 @@ export function meta({}: Route.MetaArgs) {
{
name: "description",
content:
- "Give your audience the seamless experience they deserve. Nuto's smart links bypass frustrating in-app browsers and open directly in native apps like YouTube and Spotify.",
+ "Nuto short links open directly in native apps like YouTube and Spotify instead of an in-app browser.",
},
{
property: "og:title",
@@ -24,7 +24,7 @@ export function meta({}: Route.MetaArgs) {
{
property: "og:description",
content:
- "We fix the broken mobile link experience. Nuto seamlessly routes your visitors to their favorite native apps instead of trapping them in an in-app browser.",
+ "Nuto routes your links to the native app — YouTube, Spotify, Apple Music — instead of the in-app browser.",
},
{ name: "twitter:card", content: "summary" },
];
diff --git a/components/features.tsx b/components/features.tsx
index da4209c..231e7a0 100644
--- a/components/features.tsx
+++ b/components/features.tsx
@@ -34,8 +34,8 @@ export function Features() {
Launch native apps
- Seamlessly deep-link your visitors straight into the apps they already
- have installed, like YouTube, Spotify, or Apple Music.
+ Your links open YouTube, Spotify, or Apple Music in their native
+ apps, not in a web view.
@@ -54,8 +54,8 @@ export function Features() {
Auto-expiring links
- Create temporary links that self-destruct after a set time, and seamlessly track
- how many clicks you're getting.
+ Set an expiry date and the link stops redirecting after it passes.
+ Click counts update as visitors arrive.
From 6eba8bed1883fdf05f5bd807aed43c6ea697f9ad Mon Sep 17 00:00:00 2001
From: Andres Estrada <105224908+andesvel@users.noreply.github.com>
Date: Tue, 22 Sep 2026 23:16:02 -0500
Subject: [PATCH 2/5] Remove infinite bounce and animate only colors
The scroll cue bouncing forever competes with the CTA for attention;
a static icon still signals where to scroll. Button now transitions
colors only instead of all properties, so hover never animates
layout changes.
---
components/hero.tsx | 2 +-
components/ui/button.tsx | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/components/hero.tsx b/components/hero.tsx
index b0acb1b..3e08ff7 100644
--- a/components/hero.tsx
+++ b/components/hero.tsx
@@ -74,7 +74,7 @@ export default function Hero() {
);
diff --git a/components/ui/button.tsx b/components/ui/button.tsx
index 5765a5a..a013c69 100644
--- a/components/ui/button.tsx
+++ b/components/ui/button.tsx
@@ -5,7 +5,7 @@ import { cva, type VariantProps } from "class-variance-authority";
import { cn } from "lib/utils";
const buttonVariants = cva(
- "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
+ "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
{
variants: {
variant: {
From 3e76e65e39ba7312349531ec3a3247e2660dbbd7 Mon Sep 17 00:00:00 2001
From: Andres Estrada <105224908+andesvel@users.noreply.github.com>
Date: Tue, 22 Sep 2026 23:16:22 -0500
Subject: [PATCH 3/5] Drop the hero kicker pill
The h1 already makes the point; a kicker chip repeating it above the
headline adds noise to the first thing visitors read.
---
components/hero.tsx | 3 ---
1 file changed, 3 deletions(-)
diff --git a/components/hero.tsx b/components/hero.tsx
index 3e08ff7..9b98503 100644
--- a/components/hero.tsx
+++ b/components/hero.tsx
@@ -12,9 +12,6 @@ export default function Hero() {
return (
-
- Give your users a better experience
-
Stop losing visitors to clunky in-app browsers
From 8de9cf90f6d853d583b6142b22e6075327dd2733 Mon Sep 17 00:00:00 2001
From: Andres Estrada <105224908+andesvel@users.noreply.github.com>
Date: Tue, 22 Sep 2026 23:16:42 -0500
Subject: [PATCH 4/5] Use the same corner radius in light and dark themes
Dark overrode --radius to 1rem while light uses 0.6rem, so the same
components rounded differently per theme. One radius keeps the
system uniform.
---
app/app.css | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/app.css b/app/app.css
index 6affd44..e6b8c0e 100644
--- a/app/app.css
+++ b/app/app.css
@@ -89,7 +89,7 @@
--font-sans: Inter;
--font-serif: serif;
--font-mono: monospace;
- --radius: 1rem;
+ --radius: 0.6rem;
--shadow-2xs: 0px 2px 4px 0px hsl(0 0% 0% / 0.05);
--shadow-xs: 0px 2px 4px 0px hsl(0 0% 0% / 0.05);
--shadow-sm: 0px 2px 4px 0px hsl(0 0% 0% / 0.10), 0px 1px 2px -1px hsl(0 0% 0% / 0.10);
From 506b50d5e43686b0cf39fdb8e05b8e8de0f394e6 Mon Sep 17 00:00:00 2001
From: Andres Estrada <105224908+andesvel@users.noreply.github.com>
Date: Tue, 22 Sep 2026 23:19:51 -0500
Subject: [PATCH 5/5] Make form controls solid
Inputs and outline buttons sit inside dialogs over a flat dimmed
overlay, where a backdrop-blur renders nothing visible while still
compositing on every keystroke. Glass stays on the page-level
surfaces it was designed for (header bar, count pill).
---
components/ui/button.tsx | 2 +-
components/ui/input.tsx | 3 +--
2 files changed, 2 insertions(+), 3 deletions(-)
diff --git a/components/ui/button.tsx b/components/ui/button.tsx
index a013c69..2062832 100644
--- a/components/ui/button.tsx
+++ b/components/ui/button.tsx
@@ -14,7 +14,7 @@ const buttonVariants = cva(
destructive:
"bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 hover:cursor-pointer",
outline:
- "backdrop-blur-md backdrop-saturate-150 border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50 hover:cursor-pointer",
+ "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50 hover:cursor-pointer",
secondary:
"bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80 hover:cursor-pointer",
ghost:
diff --git a/components/ui/input.tsx b/components/ui/input.tsx
index c450d38..d868ddb 100644
--- a/components/ui/input.tsx
+++ b/components/ui/input.tsx
@@ -8,8 +8,7 @@ function Input({ className, type, ...props }: React.ComponentProps<"input">) {
type={type}
data-slot="input"
className={cn(
- "backdrop-blur-xl backdrop-saturate-150",
- "file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground border-input flex h-9 w-full min-w-0 rounded-md border bg-background/30 px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
+ "file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground border-input flex h-9 w-full min-w-0 rounded-md border bg-background px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
"focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
"aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
className