diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000..c1df76e --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,3 @@ +{ + "extends": ["next/core-web-vitals"] +} \ No newline at end of file diff --git a/.gitignore b/.gitignore index 79a2c83..5bbb991 100644 --- a/.gitignore +++ b/.gitignore @@ -1,15 +1,35 @@ -node_modules +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. -.cache -.env -.vercel -.output +# dependencies +/node_modules +/.pnp +.pnp.js + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build -/build/ -/public/build -/api/index.js -api/index.js.map +# misc .DS_Store -app/styles/app.css +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# local env files +.env*.local + +# vercel +.vercel -.DS_Store \ No newline at end of file +# typescript +*.tsbuildinfo +next-env.d.ts \ No newline at end of file diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index da39e3c..0000000 --- a/Dockerfile +++ /dev/null @@ -1,60 +0,0 @@ -# base node image -FROM node:16-bullseye-slim as base - -# Install openssl for Prisma -RUN apt-get update && apt-get install -y openssl - -# Install all node_modules, including dev dependencies -FROM base as deps - -RUN mkdir /app -WORKDIR /app - -ADD package.json package-lock.json ./ -RUN npm install --production=false - -# Setup production node_modules -FROM base as production-deps - -RUN mkdir /app -WORKDIR /app - -COPY --from=deps /app/node_modules /app/node_modules -ADD package.json package-lock.json ./ -RUN npm prune --production - -# Build the app -FROM base as build - -ENV NODE_ENV=production - -RUN mkdir /app -WORKDIR /app - -COPY --from=deps /app/node_modules /app/node_modules - -# If we're using Prisma, uncomment to cache the prisma schema -# ADD prisma . -# RUN npx prisma generate - -ADD . . -RUN npm run build - -# Finally, build the production image with minimal footprint -FROM base - -ENV NODE_ENV=production - -RUN mkdir /app -WORKDIR /app - -COPY --from=production-deps /app/node_modules /app/node_modules - -# Uncomment if using Prisma -# COPY --from=build /app/node_modules/.prisma /app/node_modules/.prisma - -COPY --from=build /app/build /app/build -COPY --from=build /app/public /app/public -ADD . . - -CMD ["npm", "run", "start"] diff --git a/README.md b/README.md index 62070d9..bca9fbb 100644 --- a/README.md +++ b/README.md @@ -1,44 +1,60 @@ -# Welcome to Remix! +# Modern Landing Page -- [Remix Docs](https://remix.run/docs) +A minimal, modern landing page built with **Next.js 15** and **Tailwind CSS**. -## Fly Setup +## Features -1. [Install `flyctl`](https://fly.io/docs/getting-started/installing-flyctl/) +- ⚡ **Next.js 15** with App Router +- 🎨 **Tailwind CSS** for styling +- 📱 **Fully Responsive** design +- 🌙 **Dark mode** support +- ⚡ **Lightning fast** performance +- 🔧 **TypeScript** support -2. Sign up and log in to Fly +## Getting Started -```sh -flyctl auth signup -``` +### Prerequisites + +- Node.js 18.17 or later +- npm or yarn -3. Setup Fly. It might ask if you want to deploy, say no since you haven't built the app yet. +### Installation + +1. Install dependencies: +```bash +npm install +``` -```sh -flyctl launch +2. Run the development server: +```bash +npm run dev ``` -## Development +3. Open [http://localhost:3000](http://localhost:3000) in your browser to see the result. -From your terminal: +### Build for Production -```sh -npm run dev +```bash +npm run build +npm start ``` -This starts your app in development mode, rebuilding assets on file changes. +## Customization -## Deployment +The landing page is fully customizable: -If you've followed the setup instructions already, all you need to do is run this: +- Edit `app/page.tsx` to modify the content +- Update `app/globals.css` for global styles +- Modify `tailwind.config.js` for custom Tailwind configuration +- Update metadata in `app/layout.tsx` -```sh -npm run deploy -``` +## Tech Stack + +- **Framework**: Next.js 15 +- **Styling**: Tailwind CSS +- **Language**: TypeScript +- **Icons**: Heroicons (inline SVG) -You can run `flyctl info` to get the url and ip address of your server. +## License -Check out the [fly docs](https://fly.io/docs/getting-started/node/) for more information. -Todo: -bottom right commit hash -3D orientation \ No newline at end of file +MIT License - feel free to use this template for your projects! \ No newline at end of file diff --git a/app/components/Contributions.tsx b/app/components/Contributions.tsx deleted file mode 100644 index ff810ef..0000000 --- a/app/components/Contributions.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import ActivityCalendar from 'react-activity-calendar'; -import type { CalendarData } from 'react-activity-calendar'; - -export type ActivityType = { - data: CalendarData; -}; - -const ContributionGraph = ({ data }: ActivityType): JSX.Element => { - return ( - - - ); -}; - -export default ContributionGraph; diff --git a/app/components/Link.tsx b/app/components/Link.tsx deleted file mode 100644 index 6711c0d..0000000 --- a/app/components/Link.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import { Link as RemixLink } from '@remix-run/react'; - -export type LinkProps = { - href: string; - label?: string; - style?: boolean; - fontMono?: boolean; - onClick?: (e: any) => void; -}; - -const Link = ({ href, style, fontMono, label, onClick }: LinkProps): JSX.Element => { - const isExternal = href.startsWith('http'); - - return isExternal ? ( - - {label ?? href?.split('://')?.[1] ?? href} - - ) : ( - - {label} - - ); -}; - -export default Link; diff --git a/app/components/Model.client.tsx b/app/components/Model.client.tsx deleted file mode 100644 index 5a5f985..0000000 --- a/app/components/Model.client.tsx +++ /dev/null @@ -1,65 +0,0 @@ -import '@google/model-viewer'; -import { useState } from 'react'; -import Link from './Link'; - -interface ModelViewerJSX { - src: string; - poster?: string; - alt?: string; - ar?: boolean; - 'ar-modes'?: string; - orientation?: string; -} - -declare global { - namespace JSX { - interface IntrinsicElements { - 'model-viewer': ModelViewerJSX & - React.DetailedHTMLProps, HTMLElement>; - } - } -} - -const Model = () => { - const [year, setYear] = useState(2022); - return ( -
-
- - -
-
- -
-

- 3D model courtesy-{' '} - {' '} -

-
- ); -}; - -export default Model; diff --git a/app/components/Spotify.tsx b/app/components/Spotify.tsx deleted file mode 100644 index 028dc28..0000000 --- a/app/components/Spotify.tsx +++ /dev/null @@ -1,77 +0,0 @@ -import { Link } from '@remix-run/react'; - -export const NowPlaying = ({ - music, - showRedirect, -}: { - music: any; - showRedirect?: boolean; -}) => { - return ( - <> -
- - - - {/* Add music's now playing icon later*/} -
-

- {music?.status === true ? ( - `${music.data.name} - ${music.data.artist}` - ) : music?.status === false ? ( -

- Psst. Nothing is playing right now - {showRedirect && ( - <> - , but maybe checkout{' '} - - /music - - ? - - )} -

- ) : ( - 'Loading...' - )} -

- {music?.status !== false && ( - <> - -

Spotify

- - )} -
-
- - ); -}; - -export const RecentTracks = ({ recentTracks }: { recentTracks?: any }) => { - if (!recentTracks || recentTracks?.status === false) return <>Loading...; - - return ( -
- -
- ); -}; diff --git a/app/entry.client.tsx b/app/entry.client.tsx deleted file mode 100644 index 3eec1fd..0000000 --- a/app/entry.client.tsx +++ /dev/null @@ -1,4 +0,0 @@ -import { RemixBrowser } from "@remix-run/react"; -import { hydrate } from "react-dom"; - -hydrate(, document); diff --git a/app/entry.server.tsx b/app/entry.server.tsx deleted file mode 100644 index aa0aa09..0000000 --- a/app/entry.server.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import type { EntryContext } from "@remix-run/node"; -import { RemixServer } from "@remix-run/react"; -import { renderToString } from "react-dom/server"; - -export default function handleRequest( - request: Request, - responseStatusCode: number, - responseHeaders: Headers, - remixContext: EntryContext -) { - let markup = renderToString( - - ); - - responseHeaders.set("Content-Type", "text/html"); - - return new Response("" + markup, { - status: responseStatusCode, - headers: responseHeaders, - }); -} diff --git a/app/globals.css b/app/globals.css new file mode 100644 index 0000000..6e5f93b --- /dev/null +++ b/app/globals.css @@ -0,0 +1,27 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +:root { + --foreground-rgb: 0, 0, 0; + --background-start-rgb: 214, 219, 220; + --background-end-rgb: 255, 255, 255; +} + +@media (prefers-color-scheme: dark) { + :root { + --foreground-rgb: 255, 255, 255; + --background-start-rgb: 0, 0, 0; + --background-end-rgb: 0, 0, 0; + } +} + +body { + color: rgb(var(--foreground-rgb)); + background: linear-gradient( + to bottom, + transparent, + rgb(var(--background-end-rgb)) + ) + rgb(var(--background-start-rgb)); +} \ No newline at end of file diff --git a/app/layout.tsx b/app/layout.tsx new file mode 100644 index 0000000..621cf32 --- /dev/null +++ b/app/layout.tsx @@ -0,0 +1,22 @@ +import type { Metadata } from 'next' +import { Inter } from 'next/font/google' +import './globals.css' + +const inter = Inter({ subsets: ['latin'] }) + +export const metadata: Metadata = { + title: 'Modern Landing Page', + description: 'A minimal, modern landing page built with Next.js 15', +} + +export default function RootLayout({ + children, +}: { + children: React.ReactNode +}) { + return ( + + {children} + + ) +} \ No newline at end of file diff --git a/app/page.tsx b/app/page.tsx new file mode 100644 index 0000000..b60de08 --- /dev/null +++ b/app/page.tsx @@ -0,0 +1,100 @@ +export default function Home() { + return ( +
+ {/* Hero Section */} +
+
+

+ Welcome to the Future +

+

+ Experience the next generation of web development with our minimal, + modern, and lightning-fast landing page built with Next.js 15. +

+
+ + +
+
+
+ + {/* Features Section */} +
+
+

+ Why Choose Us? +

+
+
+
+ + + +
+

+ Lightning Fast +

+

+ Built with Next.js 15 and optimized for performance. Experience blazing fast load times and smooth interactions. +

+
+ +
+
+ + + +
+

+ Modern Design +

+

+ Clean, minimal, and responsive design that looks great on all devices. Built with Tailwind CSS for maximum flexibility. +

+
+ +
+
+ + + +
+

+ Developer Friendly +

+

+ Built with TypeScript and modern development practices. Easy to customize and extend for your needs. +

+
+
+
+
+ + {/* CTA Section */} +
+
+

+ Ready to Get Started? +

+

+ Join thousands of developers who have already made the switch to modern web development. +

+ +
+
+ + {/* Footer */} +
+
+

© 2024 Modern Landing Page. Built with Next.js 15 & Tailwind CSS.

+
+
+
+ ) +} \ No newline at end of file diff --git a/app/root.tsx b/app/root.tsx deleted file mode 100644 index 2f79c61..0000000 --- a/app/root.tsx +++ /dev/null @@ -1,77 +0,0 @@ -import type { MetaFunction } from '@remix-run/node'; -import { - Links, - LiveReload, - Meta, - Outlet, - Scripts, - ScrollRestoration, -} from '@remix-run/react'; -import { H } from 'highlight.run'; -import styles from './styles/app.css'; -import gloablStyles from './styles/global.css'; - -export function links() { - return [ - { rel: 'stylesheet', href: styles }, - { rel: 'stylesheet', href: gloablStyles }, - ]; -} - -export const meta: MetaFunction = () => ({ - charset: 'utf-8', - title: 'Ayush Goyal', - viewport: 'width=device-width,initial-scale=1', -}); - -if (process.env.NODE_ENV !== 'development') { - H.init('2d10jqgr', { - environment: 'production', - enableStrictPrivacy: false, - }); -} - -export default function App() { - return ( - - - - - - - - - {/*
*/} - {/*
*/} - {/*
*/} - {/*
*/} - {/*
*/} - - - - - - - - - - ); -} diff --git a/app/routes/index.tsx b/app/routes/index.tsx deleted file mode 100644 index 4cec8ae..0000000 --- a/app/routes/index.tsx +++ /dev/null @@ -1,220 +0,0 @@ -import Model from '~/components/Model.client'; -import { ClientOnly, getClientIPAddress } from 'remix-utils'; -import Link from '~/components/Link'; -import type { LoaderFunction } from '@remix-run/node'; -import { json } from '@remix-run/node'; -import { useLoaderData } from '@remix-run/react'; -import ContributionGraph from '~/components/Contributions'; -import { useEffect, useState } from 'react'; -import { get } from '~/utils/cache.server'; -import { NowPlaying } from '~/components/Spotify'; - -declare global { - interface Window { - Calendly: { - initPopupWidget: (options: { url: string }) => void; - }; - } -} - -export default function Index() { - const { githubContributions } = useLoaderData<{ - githubContributions: { contributions: any }; - music: any; - }>(); - - const [music, setMusic] = useState(); - - const [showModel, setShowModel] = useState(false); - useEffect(() => { - fetch('https://lastfm.ayushgoyal.dev/live') - .then((r) => r.json()) - .then((d) => setMusic(d)); - }, []); - - return ( -
-
-

- hi -

-

- I am Ayush Goyal. I am a software engineer working at{' '} - - Nimbus (YC W22) - - . I'm a senior at DTU (formerly DCE), New Delhi, India. I enjoy - playing with the web and help build and improve developer tooling. You - might find me working on some side projects 🚀 -

-

- Checkout my{' '} - - - ,{' '} - - - {' '} - and{' '} - - . - -

-

- You can contact me at{' '} - ayush@ayushgoyal.dev or - schedule a meeting using my{' '} - - { - e.preventDefault(); - window.Calendly.initPopupWidget({ - url: 'https://calendly.com/ayushg1214/30min?hide_gdpr_banner=1', - }); - return false; - }} - label="Calendly" - style - fontMono - /> - - . -

-
-
-

- experience -

-
    -
  • -
    - - * -

    July 2022 - present

    -
    -
  • -
  • -
    - -

    May 2022 - July 2022

    -
    -
  • -
  • -
    - -

    Apr 2021 - Apr 2022

    -
    -
  • -
- * Ongoing -
-
-

- etc -

-
- {showModel === false ? ( - githubContributions && ( - - ) - ) : ( - <> - Loading...
}> - {() => } - - - )} - -
- -
-

- listening to -

- -
-
- ); -} - -export let loader: LoaderFunction = async ({ request }) => { - let ipAddress = getClientIPAddress(request.headers); - - if (ipAddress !== null) - fetch('https://tg.ayushgoyal.dev/message', { - method: 'POST', - body: JSON.stringify({ - secret: process.env.TG_KEY, - ip: ipAddress, - type: 'analytics', - }), - headers: { - 'Content-Type': 'application/json', - }, - }); - - return json({ - githubContributions: await get( - 'https://github-contributions-api.jogruber.de/v4/ayush6624?y=last' - ), - }); -}; diff --git a/app/routes/music.tsx b/app/routes/music.tsx deleted file mode 100644 index a651638..0000000 --- a/app/routes/music.tsx +++ /dev/null @@ -1,66 +0,0 @@ -import { useEffect, useState } from 'react'; -import Link from '~/components/Link'; -import { NowPlaying, RecentTracks } from '~/components/Spotify'; - -const MusicPage = () => { - const [recentTracks, setRecentTracks] = useState(); - const [music, setMusic] = useState(); - - useEffect(() => { - fetch('https://lastfm.ayushgoyal.dev/recent-tracks') - .then((r) => r.json()) - .then((d) => setRecentTracks(d)); - - fetch('https://lastfm.ayushgoyal.dev/live') - .then((r) => r.json()) - .then((d) => setMusic(d)); - }, []); - - return ( -
-
-

- my music taste -

- -
-
-

- I use{' '} - - {' '} - - to keep a record of my listening history and get some cool insights! -

-
- -
-

recent tracks

- -
- -
-

- My Spotify playlist 👇 -

-