Skip to content

Commit

Permalink
Added url shortener in next js (#766)
Browse files Browse the repository at this point in the history
* Added url shortener in next js

* Updated README.md

---------

Co-authored-by: Avdhesh <[email protected]>
  • Loading branch information
Aditijainnn and Avdhesh-Varshney authored Aug 10, 2024
1 parent dbd5596 commit 844314d
Show file tree
Hide file tree
Showing 24 changed files with 4,379 additions and 0 deletions.
63 changes: 63 additions & 0 deletions Next-JS-Projects/Intermediate/Url-Shortener/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<h1 align='center'><b>💥 Url Shortener 💥</b></h1>

<!-- -------------------------------------------------------------------------------------------------------------- -->

<h3 align='center'>Tech Stack Used 🎮</h3>
<!-- enlist all the technologies used to create this project from them (Remove comment using 'ctrl+z' or 'command+z') -->

<div align='center'>

![CSS3](https://img.shields.io/badge/css3-%231572B6.svg?style=for-the-badge&logo=css3&logoColor=white)
![JavaScript](https://img.shields.io/badge/javascript-%23323330.svg?style=for-the-badge&logo=javascript&logoColor=%23F7DF1E)
![Next JS](https://img.shields.io/badge/Next-black?style=for-the-badge&logo=next.js&logoColor=white)
</div>


![Line](https://github.com/Avdhesh-Varshney/WebMasterLog/assets/114330097/4b78510f-a941-45f8-a9d5-80ed0705e847)

<!-- -------------------------------------------------------------------------------------------------------------- -->

## :zap: Description 📃

<div>
<p>A Url shortener website that shortens the url</p>
</div>




## :zap: How to run it? 🕹️
First, run the development server:

```bash
npm run dev
# or
yarn dev
# or
pnpm dev
```

Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.



## :zap: Screenshots 📸
<img src="./screenshot.webp"/>




![Line](https://github.com/Avdhesh-Varshney/WebMasterLog/assets/114330097/4b78510f-a941-45f8-a9d5-80ed0705e847)

<!-- -------------------------------------------------------------------------------------------------------------- -->

<h4 align='center'>Developed By <b><i>Aditi Jain</i></b> 👦</h4>
<p align='center'>
<a href='https://github.com/Aditijainnn'>
<img src='https://img.shields.io/badge/github-%23121011.svg?style=for-the-badge&logo=github&logoColor=white' />
</a>
</p>

<h4 align='center'>Happy Coding 🧑‍💻</h4>

<h3 align="center">Show some &nbsp;❤️&nbsp; by &nbsp;🌟&nbsp; this repository!</h3>
3 changes: 3 additions & 0 deletions Next-JS-Projects/Intermediate/Url-Shortener/app/globals.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
13 changes: 13 additions & 0 deletions Next-JS-Projects/Intermediate/Url-Shortener/app/head.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
export default function Head() {
return (
<>
<title>{"Rustam's URL Shortener"}</title>
<meta content='width=device-width, initial-scale=1' name='viewport' />
<meta
name='description'
content="The most beautiful Rustam's URL shortener"
/>
<link rel='icon' href='/favicon.ico' />
</>
)
}
23 changes: 23 additions & 0 deletions Next-JS-Projects/Intermediate/Url-Shortener/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// noinspection HtmlRequiredTitleElement

import './globals.css'
import React from 'react'

export default function RootLayout({
children
}: {
children: React.ReactNode
}) {
return (
<html lang='en'>
{/*
<head /> will contain the components returned by the nearest parent
head.tsx. Find out more at https://beta.nextjs.org/docs/api-reference/file-conventions/head
*/}
<head />
<body className='grid h-screen w-screen place-items-center bg-gradient-to-r from-purple-400 to-yellow-400'>
{children}
</body>
</html>
)
}
11 changes: 11 additions & 0 deletions Next-JS-Projects/Intermediate/Url-Shortener/app/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import MovingPart from '@/components/MovingPart'
import FixedPart from '@/components/FixedPart'

export default function Page() {
return (
<div className='flex w-full max-w-sm flex-col items-center space-y-5 rounded-xl bg-white bg-opacity-20 p-5'>
<FixedPart />
<MovingPart />
</div>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { LinkIcon } from '@heroicons/react/24/solid'

export default function FixedPart() {
return (
<div className='flex flex-col items-center'>
<div className='my-6 cursor-pointer rounded-3xl bg-gradient-to-br from-[#5885e0] via-[#CF4D9E] to-[#EC7951] p-3'>
<LinkIcon className='h-14 w-14 text-white' />
</div>
<h1 className='text-xl font-semibold'>Make a Short Link</h1>
</div>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
'use client'

import { usePostUrlMutation } from '@/utils/use-swr'
import { FormEventHandler, useEffect, useState } from 'react'

export default function MovingPart() {
const postUrl = usePostUrlMutation()

const urlToRedirect =
postUrl.id != null
? new URL(postUrl.id, window.location.origin).toString()
: null

const handleSubmit: FormEventHandler<HTMLFormElement> = async event => {
event.preventDefault()
postUrl.reset()
// @ts-ignore
const url = event.target.url.value
const newId = await postUrl.trigger({ url })
console.log(`The new id is`, newId)
}

const [copied, setCopied] = useState(false)
useEffect(() => {
if (copied) {
const id = setTimeout(() => setCopied(false), 2000)
return () => clearTimeout(id)
}
}, [copied])
const handleCopy = async () => {
if (typeof urlToRedirect === 'string') {
await navigator.clipboard.writeText(urlToRedirect)
setCopied(true)
}
}

return (
<div className='flex w-full flex-col items-center space-y-5'>
<form onSubmit={handleSubmit} className='flex w-full flex-col space-y-4'>
<input
type='url'
name='url'
required
className='rounded-lg border border-gray-200 indent-4 leading-[2.75rem] bg-transparent border-opacity-40'
onClick={e => e.currentTarget.select()}
defaultValue='https://the-link-you-want-to-shorten.long'
/>

<button
type='submit'
className='h-12 rounded-lg bg-gradient-to-r from-blue-500 to-fuchsia-500 font-bold text-white hover:text-opacity-70'
>
Shorten it
</button>
</form>
<div
onClick={handleCopy}
className='group flex h-36 w-full cursor-pointer flex-col items-center justify-center rounded-lg border border-dashed bg-green-200 bg-opacity-10 text-xl hover:border-2 hover:bg-opacity-20'
>
{copied ? (
<p className='text-4xl font-semibold'>Copied!</p>
) : (
<>
<p>
{copied
? 'Copied!'
: urlToRedirect ??
(postUrl.isMutating ? '...' : 'Shortened link will be here')}
</p>
{urlToRedirect && (
<p className='mt-8 text-sm text-gray-500 group-hover:underline'>
Click to copy
</p>
)}
</>
)}
</div>
</div>
)
}
11 changes: 11 additions & 0 deletions Next-JS-Projects/Intermediate/Url-Shortener/middleware.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import type { NextRequest } from 'next/server'
import { NextResponse } from 'next/server'
import { fetchUrl } from '@/utils/urlsFetcher'

export async function middleware(request: NextRequest) {
if (request.nextUrl.pathname.match(/\/\d+/)) {
const id = Number(request.nextUrl.pathname.substring(1))
const url = await fetchUrl(id)
if (url) return NextResponse.redirect(new URL(url!))
}
}
8 changes: 8 additions & 0 deletions Next-JS-Projects/Intermediate/Url-Shortener/next.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
experimental: {
appDir: true
}
}

module.exports = nextConfig
Loading

0 comments on commit 844314d

Please sign in to comment.