|
| 1 | +# Shift |
| 2 | + |
| 3 | +Read any article on the internet in your preferred language. |
| 4 | +Shift extracts article content from web pages and translates it while preserving formatting, images, and typography. |
| 5 | + |
| 6 | +- [Checkout Live Here](https://shift-read.vercel.app/) |
| 7 | +- [View Demo Here](https://5kas5z928t.ufs.sh/f/wBHVA4PQTleAKsb2NVrIL2VE9DjCy53AWlsMSoTNfqhc0U8J) |
| 8 | + |
| 9 | + |
| 10 | +## Features |
| 11 | + |
| 12 | +- **Web Scraping**: Extract clean article content from any URL |
| 13 | +- **Translation**: Translate articles to 12+ languages while preserving Markdown formatting |
| 14 | +- **Beautiful Reading**: Clean, minimal reader mode with typography optimized for long-form content |
| 15 | +- **Language Toggle**: Seamlessly switch between original and translated content |
| 16 | +- **Dark Mode**: Toggle between light and dark themes |
| 17 | +- **Smart Caching**: Articles and translations are cached locally for instant re-access |
| 18 | + |
| 19 | +## Tech Stack |
| 20 | + |
| 21 | +- **Framework**: Next.js 16.1.4 (App Router) |
| 22 | +- **Language**: TypeScript |
| 23 | +- **Styling**: Tailwind CSS 4 |
| 24 | +- **UI Components**: shadcn/ui |
| 25 | +- **Web Scraping**: @mendable/firecrawl-js |
| 26 | +- **Translation**: lingo.dev SDK |
| 27 | +- **Markdown Rendering**: react-markdown with remark-gfm and rehype-highlight |
| 28 | +- **Syntax Highlighting**: react-syntax-highlighter |
| 29 | +- **Caching**: localStorage with timestamp-based cache management |
| 30 | + |
| 31 | +## What lingo.dev Feature It Highlights |
| 32 | + |
| 33 | +Shift showcases **lingo.dev's Markdown translation capabilities**. The app demonstrates how lingo.dev can: |
| 34 | + |
| 35 | +- Translate complex Markdown content while preserving formatting |
| 36 | +- Maintain document structure during translation |
| 37 | +- Provide seamless language switching for content-heavy applications |
| 38 | + |
| 39 | +The translation preserves: |
| 40 | +- Headers and text hierarchy |
| 41 | +- Links and their targets |
| 42 | +- Lists, quotes, and other Markdown elements |
| 43 | + |
| 44 | +## Installation |
| 45 | + |
| 46 | +### Prerequisites |
| 47 | + |
| 48 | +- Node.js 18+ |
| 49 | +- pnpm (recommended) or npm/yarn |
| 50 | + |
| 51 | +### Setup |
| 52 | + |
| 53 | +1. **Clone the repository** |
| 54 | + ```bash |
| 55 | + git clone <repository-url> |
| 56 | + cd shift-read |
| 57 | + ``` |
| 58 | + |
| 59 | +2. **Install dependencies** |
| 60 | + ```bash |
| 61 | + pnpm install |
| 62 | + ``` |
| 63 | + |
| 64 | +3. **Set up environment variables** |
| 65 | + |
| 66 | + Create a `.env` file in the project root and see .env.example for variables to add: |
| 67 | + ```env |
| 68 | + FIRECRAWL_API_KEY=your_firecrawl_api_key_here |
| 69 | + LINGODOTDEV_API_KEY=your_lingodotdev_api_key_here |
| 70 | + GROQ_API_KEY=groq_api_key_here |
| 71 | + ``` |
| 72 | + |
| 73 | +4. **Get API Keys** |
| 74 | + - **Firecrawl**: Sign up at [firecrawl.dev](https://firecrawl.dev) to get your API key |
| 75 | + - **Groq**: Sign up at [groq.com](https://groq.com) to get your API key |
| 76 | + - **lingo.dev**: Sign up at [lingo.dev](https://lingo.dev) to get your API key |
| 77 | + |
| 78 | +5. **Run the development server** |
| 79 | + ```bash |
| 80 | + pnpm dev |
| 81 | + ``` |
| 82 | + |
| 83 | +6. **Open your browser** |
| 84 | + Navigate to [http://localhost:3000](http://localhost:3000) |
| 85 | + |
| 86 | +## Running Locally |
| 87 | + |
| 88 | +### Development Mode |
| 89 | +```bash |
| 90 | +pnpm dev |
| 91 | +``` |
| 92 | +Starts the development server with hot reload at `http://localhost:3000` |
| 93 | + |
| 94 | +### Build for Production |
| 95 | +```bash |
| 96 | +pnpm build |
| 97 | +``` |
| 98 | +Creates an optimized production build |
| 99 | + |
| 100 | +### Start Production Server |
| 101 | +```bash |
| 102 | +pnpm start |
| 103 | +``` |
| 104 | +Runs the production build at `http://localhost:3000` |
| 105 | + |
| 106 | +### Linting |
| 107 | +```bash |
| 108 | +pnpm lint |
| 109 | +``` |
| 110 | +Runs ESLint to check for code issues |
| 111 | + |
| 112 | +## Supported Languages |
| 113 | + |
| 114 | +Shift supports translation to these languages: |
| 115 | + |
| 116 | +- 🇪🇸 Spanish (es) |
| 117 | +- 🇫🇷 French (fr) |
| 118 | +- 🇩🇪 German (de) |
| 119 | +- 🇯🇵 Japanese (ja) |
| 120 | +- 🇨🇳 Chinese (zh) |
| 121 | +- 🇸🇦 Arabic (ar) |
| 122 | +- 🇮🇳 Hindi (hi) |
| 123 | +- 🇵🇹 Portuguese (pt) |
| 124 | +- 🇷🇺 Russian (ru) |
| 125 | +- 🇰🇷 Korean (ko) |
| 126 | +- 🇮🇹 Italian (it) |
| 127 | +- 🇳🇱 Dutch (nl) |
| 128 | + |
| 129 | +The source language is automatically detected and filtered from the translation options. |
| 130 | + |
| 131 | +## Project Structure |
| 132 | + |
| 133 | +```text |
| 134 | +shift-read/ |
| 135 | +├── app/ |
| 136 | +│ ├── page.tsx # Homepage with URL input |
| 137 | +│ ├── layout.tsx # Root layout with providers |
| 138 | +│ ├── globals.css # Global styles (Tailwind v4) |
| 139 | +│ ├── read/[...url]/ |
| 140 | +│ │ └── page.tsx # Reading page with article display |
| 141 | +│ └── actions/ |
| 142 | +│ ├── fetchContent.ts # Firecrawl server action |
| 143 | +│ ├── translate.ts # lingo.dev server action |
| 144 | +│ └── cleanMarkdown.ts # Markdown cleanup utilities |
| 145 | +├── components/ |
| 146 | +│ ├── ArticleHeader.tsx # Title, author, date, image display |
| 147 | +│ ├── LanguageSelector.tsx # Language dropdown |
| 148 | +│ ├── MDXRender.tsx # Markdown renderer with custom components |
| 149 | +│ └── ThemeToggle.tsx # Dark/light mode toggle |
| 150 | +├── lib/ |
| 151 | +│ ├── utils.ts # Utility functions |
| 152 | +│ └── storage.ts # localStorage helpers |
| 153 | +├── README.md |
| 154 | +├── package.json |
| 155 | +├── next.config.ts |
| 156 | +└── tsconfig.json |
| 157 | +``` |
| 158 | + |
| 159 | +## How It Works |
| 160 | + |
| 161 | +1. **URL Input**: User enters an article URL on the homepage |
| 162 | +2. **Content Extraction**: Firecrawl scrapes the URL and extracts clean Markdown content |
| 163 | +3. **Caching**: Article is cached in localStorage for instant future access |
| 164 | +4. **Translation**: User can select a target language and lingo.dev translates the content |
| 165 | +5. **Display**: Article is rendered with beautiful typography and preserved formatting |
| 166 | +6. **Toggle**: Users can switch between original and translated content seamlessly |
| 167 | + |
| 168 | +--- |
| 169 | + |
| 170 | +- built by [mayank](https://mayankbansal.xyz) |
0 commit comments