SafeShare: Friction-Free Reddit Sharing with Next.js and a One-Click Bookmarklet

SafeShare interface showing Reddit post sharing with bookmarklet
TL;DR: SafeShare is a Next.js 16 web app that creates clean, shareable views of Reddit posts — no login walls, no app install prompts, no ads. It uses Vercel Redis with a 90-day TTL for snapshot storage and a one-click bookmarklet that generates a shareable link without leaving the Reddit tab. The architecture fetches post data client-side to bypass Reddit's datacenter IP restrictions, then stores the snapshot server-side. April 2026 update: improved bookmarklet reliability and gallery post support.

The Problem

We've all been there: you find a great Reddit post and want to share it with a friend or family member. But when they click the link, they're hit with:

  • Login walls — "Sign in to continue"
  • App install prompts — "Open in the Reddit app"
  • Ads and promoted content — Cluttering the reading experience
  • Endless scrolling — Recommended posts, trending content, noise everywhere

For a simple act of sharing, the experience is frustrating — especially for less tech-savvy users who just want to read what you sent them.

Enter SafeShare

SafeShare is my solution to this problem. It's a clean reader view for Reddit posts that strips away everything except what matters: the post content and top comments.

Here's how it works:

  1. Paste a Reddit URL into SafeShare
  2. Get a clean, shareable link
  3. Anyone who visits sees the post content and comments — nothing else

Snapshots are stored for 90 days, giving you plenty of time to share before they expire.

Supported Content

SafeShare handles all the common Reddit post types:

  • Text posts — Full self-post content with formatting
  • Image posts — Single images and galleries
  • Videos — Reddit-hosted videos (note: no audio due to Reddit's streaming format)
  • External links — Link posts with preview images

The Bookmarklet Feature

The real magic happens with the bookmarklet. Instead of copying a Reddit URL, pasting it into SafeShare, and then sharing the generated link — you can do it all in one click.

How to use the bookmarklet:

  1. Drag the "SafeShare" button to your browser's bookmarks bar
  2. Navigate to any Reddit post
  3. Click the bookmarklet
  4. Your clean SafeShare link is automatically copied to clipboard
  5. Paste and share!

The bookmarklet fetches the post data directly from Reddit's API (client-side to avoid CORS issues), sends it to the SafeShare backend, and returns a shareable link — all in under a second.

Tech Stack

SafeShare is built with modern, serverless technologies:

  • Next.js 16 — App Router, React Server Components, optimized performance
  • Vercel — Hosting, edge functions, and automatic deployments
  • Vercel Redis — Fast, ephemeral storage for post snapshots (90-day TTL)
  • Tailwind CSS — Clean, responsive UI
  • TypeScript — Type-safe development

Architecture Notes

One interesting challenge: Reddit's API blocks server-side requests from datacenter IPs (like Vercel's). To work around this, SafeShare fetches Reddit data directly in the browser, then stores it server-side. This means:

  • No Reddit API credentials are required
  • No server-side rate limiting issues
  • The backend only stores data — it never talks to Reddit

This architecture keeps the project simple and free to host, while still providing a reliable sharing experience.

Local Development

Want to run SafeShare locally? Here's how:

# Clone the repository
git clone https://github.com/josefresco/safe-share.git
cd safe-share

# Install dependencies
npm install

# Pull environment variables from Vercel
vercel env pull .env.local

# Start dev server
npm run dev

Open http://localhost:3000 and you're ready to go.

Environment Variables

SafeShare requires just one environment variable:

Variable Description
REDIS_URL Vercel Redis connection URL

Deployment

SafeShare is connected to GitHub — any push to master triggers an automatic Vercel deployment. This means:

  • Zero-config deployments
  • Preview URLs for every branch
  • Automatic SSL certificates
  • Global edge caching

How the App Router Structures the Application

SafeShare is built on Next.js 16 with the App Router — not the older Pages Router. This shapes how routes, data fetching, and server/client components are organized.

The core route structure:

app/
├── layout.tsx          # Root layout (shared head, fonts)
├── page.tsx            # Landing page — paste URL or use bookmarklet
├── [id]/
│   └── page.tsx        # Snapshot viewer — renders a stored post
└── api/
    ├── store/
    │   └── route.ts    # POST endpoint — receives snapshot from bookmarklet
    └── snapshot/
        └── [id]/
            └── route.ts  # GET endpoint — retrieves snapshot for viewer

The landing page (app/page.tsx) is a Client Component — it needs the URL input field and form submission logic to run in the browser. The snapshot viewer (app/[id]/page.tsx) is a Server Component — it fetches the snapshot from Redis at request time and renders the post HTML server-side, so the reader sees fully-rendered content with no client-side hydration required for the post body.

Storing a Snapshot

When the bookmarklet (or the paste form on the landing page) sends a Reddit post to SafeShare, the /api/store route handles it:

// app/api/store/route.ts
import { Redis } from '@upstash/redis';
import { nanoid } from 'nanoid';

const redis = new Redis({ url: process.env.REDIS_URL! });

export async function POST(request: Request) {
  const snapshot = await request.json();

  // Basic validation
  if (!snapshot.title || !snapshot.subreddit) {
    return Response.json({ error: 'Invalid snapshot' }, { status: 400 });
  }

  const id = nanoid(10);
  const ttl = 60 * 60 * 24 * 90; // 90 days in seconds

  await redis.set(`post:${id}`, JSON.stringify(snapshot), { ex: ttl });

  return Response.json({ id, url: `https://safe-share.vercel.app/${id}` });
}

nanoid generates a short, URL-safe ID. The snapshot is stored in Redis with a 90-day TTL — after that, the key expires automatically and the shareable link returns a 404. No cleanup job needed.

Rendering a Snapshot

The viewer route fetches from Redis on the server and renders synchronously:

// app/[id]/page.tsx
import { Redis } from '@upstash/redis';
import { notFound } from 'next/navigation';

const redis = new Redis({ url: process.env.REDIS_URL! });

export default async function SnapshotPage({ params }: { params: { id: string } }) {
  const raw = await redis.get(`post:${params.id}`);

  if (!raw) notFound();

  const post = typeof raw === 'string' ? JSON.parse(raw) : raw;

  return (
    <article>
      <h1>{post.title}</h1>
      <p>r/{post.subreddit} · {post.score} points</p>
      <div dangerouslySetInnerHTML={{ __html: post.bodyHtml }} />
      {/* Top comments rendered here */}
    </article>
  );
}

Because this is a Server Component, the Redis fetch happens at request time without any client-side JavaScript. The rendered HTML reaches the browser ready to display. For a read-only view of a stored post, that's exactly the right trade-off — fast first paint, no loading spinner, no layout shift.

What's Next

SafeShare is already useful in its current form, but there are plenty of ideas for future improvements:

  • Custom themes — Dark mode (already there!), light mode, or fun color schemes
  • Comment depth options — Choose how many levels of nested comments to display
  • Export options — Download posts as PDF or Markdown
  • Analytics — Track how many times your shared links are viewed (privacy-respecting, of course)

April 2026 Update

A few improvements landed in April 2026 based on real-world usage and user reports:

  • Bookmarklet reliability — The bookmarklet now handles Reddit's occasional API shape changes more gracefully, falling back to the URL-paste flow instead of silently failing.
  • Gallery post support — Multi-image gallery posts previously only showed the first image. The snapshot now captures all gallery images and renders them in a scrollable grid in the clean view.
  • Snapshot preview — Before the bookmarklet copies the SafeShare link to your clipboard, it briefly shows a toast with the post title so you can confirm you're sharing the right thing.
  • Error page improvements — Expired snapshots (past the 90-day TTL) now show a helpful page with the original Reddit URL rather than a generic 404.

The core architecture is unchanged — client-side Reddit fetch, server-side Redis storage, 90-day TTL. These are surface-level improvements that make the existing flow more reliable.

Conclusion

SafeShare solves a real problem I encountered daily: sharing Reddit content without the friction. Whether you're sharing a funny post with family, a technical discussion with colleagues, or news with friends, SafeShare makes it clean and simple.

The one-click bookmarklet is the killer feature — it turns a multi-step process into a single click. Once you start using it, you'll wonder how you ever shared Reddit links any other way.

Want a Cleaner Web Experience?

From browser bookmarklets to full web apps, I build tools that cut through the noise and make sharing content simple and friction-free.