Initial commit: Meme Coin Website

This commit is contained in:
boilerrat 2025-03-08 23:20:02 -05:00
commit 472396055f
23 changed files with 6769 additions and 0 deletions

72
.cursor/rules/dev.mdc Normal file
View File

@ -0,0 +1,72 @@
---
description: *sl,,
globs: *tsx, src/**/*.ts, src/**/*.tsx, src/**/*.json, public/**/,*sol
alwaysApply: true
---
You are an expert in Solidity, TypeScript, Node.js, Next.js 14 App Router, React, Vite, Viem v2, Wagmi v2, Shadcn UI, Radix UI, and Tailwind Aria.
Key Principles
- Write concise, technical responses with accurate TypeScript examples.
- Use functional, declarative programming. Avoid classes.
- Prefer iteration and modularization over duplication.
- Use descriptive variable names with auxiliary verbs (e.g., isLoading).
- Use lowercase with dashes for directories (e.g., components/auth-wizard).
- Favor named exports for components.
- Use the Receive an Object, Return an Object (RORO) pattern.
JavaScript/TypeScript
- Use "function" keyword for pure functions. Omit semicolons.
- Use TypeScript for all code. Prefer interfaces over types. Avoid enums, use maps.
- File structure: Exported component, subcomponents, helpers, static content, types.
- Avoid unnecessary curly braces in conditional statements.
- For single-line statements in conditionals, omit curly braces.
- Use concise, one-line syntax for simple conditional statements (e.g., if (condition) doSomething()).
Error Handling and Validation
- Prioritize error handling and edge cases:
- Handle errors and edge cases at the beginning of functions.
- Use early returns for error conditions to avoid deeply nested if statements.
- Place the happy path last in the function for improved readability.
- Avoid unnecessary else statements; use if-return pattern instead.
- Use guard clauses to handle preconditions and invalid states early.
- Implement proper error logging and user-friendly error messages.
- Consider using custom error types or error factories for consistent error handling.
React/Next.js
- Use functional components and TypeScript interfaces.
- Use declarative JSX.
- Use function, not const, for components.
- Use Shadcn UI, Radix, and Tailwind Aria for components and styling.
- Implement responsive design with Tailwind CSS.
- Use mobile-first approach for responsive design.
- Place static content and interfaces at file end.
- Use content variables for static content outside render functions.
- Minimize 'use client', 'useEffect', and 'setState'. Favor RSC.
- Use Zod for form validation.
- Wrap client components in Suspense with fallback.
- Use dynamic loading for non-critical components.
- Optimize images: WebP format, size data, lazy loading.
- Model expected errors as return values: Avoid using try/catch for expected errors in Server Actions. Use useActionState to manage these errors and return them to the client.
- Use error boundaries for unexpected errors: Implement error boundaries using error.tsx and global-error.tsx files to handle unexpected errors and provide a fallback UI.
- Use useActionState with react-hook-form for form validation.
- Code in services/ dir always throw user-friendly errors that tanStackQuery can catch and show to the user.
- Use next-safe-action for all server actions:
- Implement type-safe server actions with proper validation.
- Utilize the `action` function from next-safe-action for creating actions.
- Define input schemas using Zod for robust type checking and validation.
- Handle errors gracefully and return appropriate responses.
- Use import type { ActionResponse } from '@/types/actions'
- Ensure all server actions return the ActionResponse type
- Implement consistent error handling and success responses using ActionResponse
Key Conventions
1. Rely on Next.js App Router for state changes.
2. Prioritize Web Vitals (LCP, CLS, FID).
3. Minimize 'use client' usage:
- Prefer server components and Next.js SSR features.
- Use 'use client' only for Web API access in small components.
- Avoid using 'use client' for data fetching or state management.
Refer to Next.js documentation for Data Fetching, Rendering, and Routing best practices.

4
.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
/node_modules
/.next
.env
.DS_Store

74
GITEA-INSTRUCTIONS.md Normal file
View File

@ -0,0 +1,74 @@
# Pushing to Gitea Server
This document provides instructions on how to push this repository to your private Gitea server.
## Prerequisites
- A Gitea server (e.g., https://git.boilerhaus.org)
- Git installed on your local machine
- SSH key set up for authentication (recommended)
## Steps
### 1. Create a New Repository on Gitea
1. Log in to your Gitea server (e.g., https://git.boilerhaus.org)
2. Click the "+" button in the top right corner and select "New Repository"
3. Enter a name for your repository (e.g., "meme")
4. Add a description (optional): "A modern, responsive website for a meme cryptocurrency"
5. Choose whether to make it private or public
6. Do NOT initialize the repository with a README, .gitignore, or license
7. Click "Create Repository"
### 2. Add the Remote Repository
```bash
# Using SSH (recommended)
git remote add origin git@git.boilerhaus.org:boilerrat/meme.git
# OR using HTTPS
git remote add origin https://git.boilerhaus.org/boilerrat/meme.git
```
### 3. Push the Code
```bash
git push -u origin main
```
### 4. Verify the Push
1. Go to your Gitea server and navigate to the repository
2. You should see all the files and commit history
## Troubleshooting
### Authentication Issues
If you encounter authentication issues:
- For SSH: Make sure your SSH key is added to your Gitea account
- For HTTPS: You'll be prompted for your username and password
### Repository Not Found
If you get a "repository not found" error:
- Double-check the repository name and path
- Make sure the repository exists on your Gitea server
- Verify that you have the correct permissions
### Other Issues
If you encounter other issues, try:
```bash
# Check your Git configuration
git config --list
# Check your remotes
git remote -v
# Check your branch
git branch
```

92
README.md Normal file
View File

@ -0,0 +1,92 @@
# Meme Coin Website
A modern, responsive website for a meme cryptocurrency, built with Next.js, TypeScript, Tailwind CSS, and Framer Motion.
![Meme Coin Website](https://placekitten.com/800/400)
## Features
- Responsive design that works on all devices
- Modern UI with smooth animations using Framer Motion
- Built with Next.js App Router and TypeScript
- Styled with Tailwind CSS and shadcn/ui components
- SEO optimized
## Sections
- **Hero section**: Eye-catching introduction with call-to-action buttons
- **About section**: Highlighting key features and benefits
- **Tokenomics**: Detailed token distribution and transaction fees
- **Interactive roadmap**: Timeline showing project milestones
- **Community section**: Social links and newsletter signup
- **Footer**: Links to important pages and legal information
## Getting Started
### Prerequisites
- Node.js 18.17 or later
### Installation
1. Clone the repository:
```bash
git clone <repository-url>
cd meme-coin
```
2. Install dependencies:
```bash
npm install
```
3. Run the development server:
```bash
npm run dev
```
4. Open [http://localhost:3000](http://localhost:3000) in your browser to see the result.
## Building for Production
```bash
npm run build
```
Then, you can start the production server:
```bash
npm start
```
## Pushing to Gitea Server
To push this repository to your Gitea server:
1. Create a new repository on your Gitea server (e.g., https://git.boilerhaus.org)
2. Add the remote repository:
```bash
git remote add origin git@git.boilerhaus.org:boilerrat/meme.git
```
3. Push the code:
```bash
git push -u origin main
```
## Technologies Used
- [Next.js](https://nextjs.org/) - React framework for production
- [TypeScript](https://www.typescriptlang.org/) - Typed JavaScript
- [Tailwind CSS](https://tailwindcss.com/) - Utility-first CSS framework
- [Framer Motion](https://www.framer.com/motion/) - Animation library
- [shadcn/ui](https://ui.shadcn.com/) - UI component library
## License
This project is licensed under the MIT License - see the LICENSE file for details.
## Acknowledgments
- Design inspired by modern cryptocurrency websites
- Icons and emojis used for simplicity
- Placeholder images from [PlaceKitten](https://placekitten.com/)

5
next-env.d.ts vendored Normal file
View File

@ -0,0 +1,5 @@
/// <reference types="next" />
/// <reference types="next/image-types/global" />
// NOTE: This file should not be edited
// see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information.

6
next.config.js Normal file
View File

@ -0,0 +1,6 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
}
module.exports = nextConfig

5433
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

36
package.json Normal file
View File

@ -0,0 +1,36 @@
{
"name": "meme",
"version": "1.0.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
},
"keywords": [],
"author": "",
"license": "ISC",
"description": "",
"dependencies": {
"@radix-ui/react-slot": "^1.0.2",
"@types/node": "^20.11.30",
"@types/react": "^18.2.67",
"@types/react-dom": "^18.2.22",
"autoprefixer": "^10.4.14",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.0",
"eslint": "^8.57.0",
"eslint-config-next": "^14.1.4",
"framer-motion": "^11.1.12",
"lucide-react": "^0.363.0",
"next": "^14.1.4",
"postcss": "^8.4.23",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"tailwind-merge": "^2.2.2",
"tailwindcss": "^3.3.0",
"tailwindcss-animate": "^1.0.7",
"typescript": "^5.4.5"
}
}

6
postcss.config.js Normal file
View File

@ -0,0 +1,6 @@
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}

59
src/app/globals.css Normal file
View File

@ -0,0 +1,59 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer base {
:root {
--background: 0 0% 100%;
--foreground: 240 10% 3.9%;
--card: 0 0% 100%;
--card-foreground: 240 10% 3.9%;
--popover: 0 0% 100%;
--popover-foreground: 240 10% 3.9%;
--primary: 142.1 76.2% 36.3%;
--primary-foreground: 355.7 100% 97.3%;
--secondary: 240 4.8% 95.9%;
--secondary-foreground: 240 5.9% 10%;
--muted: 240 4.8% 95.9%;
--muted-foreground: 240 3.8% 46.1%;
--accent: 240 4.8% 95.9%;
--accent-foreground: 240 5.9% 10%;
--destructive: 0 84.2% 60.2%;
--destructive-foreground: 0 0% 98%;
--border: 240 5.9% 90%;
--input: 240 5.9% 90%;
--ring: 142.1 76.2% 36.3%;
--radius: 0.5rem;
}
.dark {
--background: 20 14.3% 4.1%;
--foreground: 0 0% 95%;
--card: 24 9.8% 10%;
--card-foreground: 0 0% 95%;
--popover: 0 0% 9%;
--popover-foreground: 0 0% 95%;
--primary: 142.1 70.6% 45.3%;
--primary-foreground: 144.9 80.4% 10%;
--secondary: 240 3.7% 15.9%;
--secondary-foreground: 0 0% 98%;
--muted: 0 0% 15%;
--muted-foreground: 240 5% 64.9%;
--accent: 12 6.5% 15.1%;
--accent-foreground: 0 0% 98%;
--destructive: 0 62.8% 30.6%;
--destructive-foreground: 0 85.7% 97.3%;
--border: 240 3.7% 15.9%;
--input: 240 3.7% 15.9%;
--ring: 142.4 71.8% 29.2%;
}
}
@layer base {
* {
@apply border-border;
}
body {
@apply bg-background text-foreground;
}
}

24
src/app/layout.tsx Normal file
View File

@ -0,0 +1,24 @@
import type { Metadata } from 'next'
import { Inter } from 'next/font/google'
import './globals.css'
const inter = Inter({ subsets: ['latin'] })
export const metadata: Metadata = {
title: 'Meme Coin',
description: 'A meme coin website',
}
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en">
<body className={inter.className}>
{children}
</body>
</html>
)
}

21
src/app/page.tsx Normal file
View File

@ -0,0 +1,21 @@
import { Navbar } from "@/components/navbar"
import { Hero } from "@/components/hero"
import { About } from "@/components/about"
import { Tokenomics } from "@/components/tokenomics"
import { Roadmap } from "@/components/roadmap"
import { Community } from "@/components/community"
import { Footer } from "@/components/footer"
export default function Home() {
return (
<main className="min-h-screen">
<Navbar />
<Hero />
<About />
<Tokenomics />
<Roadmap />
<Community />
<Footer />
</main>
)
}

91
src/components/about.tsx Normal file
View File

@ -0,0 +1,91 @@
"use client"
import { motion } from "framer-motion"
function About() {
const features = [
{
icon: "💰",
title: "Community Driven",
description: "Our token is owned and governed by the community, ensuring fair distribution and democratic decision-making."
},
{
icon: "🔒",
title: "Secure & Audited",
description: "Our smart contract has been thoroughly audited by leading security firms to ensure your investment is safe."
},
{
icon: "🚀",
title: "Deflationary Model",
description: "With a burn mechanism on every transaction, our token becomes more scarce over time, potentially increasing value."
},
{
icon: "🌐",
title: "Cross-Chain Support",
description: "Available on multiple blockchains to ensure accessibility and lower transaction fees for all users."
}
]
return (
<section id="about" className="py-24 px-6 md:px-12 lg:px-24 bg-secondary/30">
<div className="container mx-auto">
<motion.div
className="text-center mb-16"
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6 }}
viewport={{ once: true }}
>
<h2 className="text-3xl md:text-5xl font-bold mb-4">About Our Meme Coin</h2>
<p className="text-lg text-muted-foreground max-w-2xl mx-auto">
More than just a meme, we're building a vibrant ecosystem with real utility and community governance.
</p>
</motion.div>
<div className="grid md:grid-cols-2 lg:grid-cols-4 gap-8">
{features.map((feature, index) => (
<motion.div
key={index}
className="bg-card rounded-lg p-6 shadow-lg"
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ duration: 0.5, delay: index * 0.1 }}
viewport={{ once: true }}
>
<div className="text-4xl mb-4">{feature.icon}</div>
<h3 className="text-xl font-semibold mb-2">{feature.title}</h3>
<p className="text-muted-foreground">{feature.description}</p>
</motion.div>
))}
</div>
<motion.div
className="mt-20 bg-card rounded-lg p-8 shadow-lg"
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6, delay: 0.4 }}
viewport={{ once: true }}
>
<div className="grid md:grid-cols-2 gap-8 items-center">
<div>
<h3 className="text-2xl md:text-3xl font-bold mb-4">Our Vision</h3>
<p className="text-muted-foreground mb-6">
We're not just another meme coin. Our vision is to bridge the gap between humor and utility in the cryptocurrency space, creating a token that's both fun to own and valuable to hold.
</p>
<p className="text-muted-foreground">
By combining the viral nature of memes with solid tokenomics and real-world applications, we're building a sustainable ecosystem that rewards our community while pushing the boundaries of what a meme coin can be.
</p>
</div>
<div className="flex justify-center">
<div className="relative w-64 h-64 rounded-full bg-primary/20 flex items-center justify-center">
<span className="text-6xl">🌈</span>
</div>
</div>
</div>
</motion.div>
</div>
</section>
)
}
export { About }

View File

@ -0,0 +1,166 @@
"use client"
import { motion } from "framer-motion"
import { Button } from "@/components/ui/button"
function Community() {
const socialLinks = [
{
name: "Twitter",
icon: "🐦",
color: "bg-blue-500",
url: "#"
},
{
name: "Telegram",
icon: "✈️",
color: "bg-blue-400",
url: "#"
},
{
name: "Discord",
icon: "💬",
color: "bg-indigo-500",
url: "#"
},
{
name: "Reddit",
icon: "🤖",
color: "bg-orange-500",
url: "#"
}
]
return (
<section id="community" className="py-24 px-6 md:px-12 lg:px-24">
<div className="container mx-auto">
<motion.div
className="text-center mb-16"
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6 }}
viewport={{ once: true }}
>
<h2 className="text-3xl md:text-5xl font-bold mb-4">Join Our Community</h2>
<p className="text-lg text-muted-foreground max-w-2xl mx-auto">
Be part of our growing community and stay updated on the latest news and developments.
</p>
</motion.div>
<div className="grid md:grid-cols-2 gap-12 items-center">
<motion.div
initial={{ opacity: 0, x: -20 }}
whileInView={{ opacity: 1, x: 0 }}
transition={{ duration: 0.6 }}
viewport={{ once: true }}
>
<div className="bg-card rounded-lg p-8 shadow-lg">
<h3 className="text-2xl font-bold mb-6">Connect With Us</h3>
<div className="grid grid-cols-2 gap-4">
{socialLinks.map((social, index) => (
<motion.a
key={index}
href={social.url}
className={`${social.color} bg-opacity-10 hover:bg-opacity-20 transition-colors p-4 rounded-lg flex items-center gap-3`}
whileHover={{ scale: 1.05 }}
whileTap={{ scale: 0.95 }}
>
<span className="text-2xl">{social.icon}</span>
<span className="font-medium">{social.name}</span>
</motion.a>
))}
</div>
<div className="mt-8">
<h4 className="font-semibold mb-4">Community Stats</h4>
<div className="grid grid-cols-2 gap-4">
<div className="bg-secondary/50 p-4 rounded-lg text-center">
<p className="text-2xl font-bold text-primary">50K+</p>
<p className="text-sm text-muted-foreground">Twitter Followers</p>
</div>
<div className="bg-secondary/50 p-4 rounded-lg text-center">
<p className="text-2xl font-bold text-primary">25K+</p>
<p className="text-sm text-muted-foreground">Telegram Members</p>
</div>
<div className="bg-secondary/50 p-4 rounded-lg text-center">
<p className="text-2xl font-bold text-primary">15K+</p>
<p className="text-sm text-muted-foreground">Discord Members</p>
</div>
<div className="bg-secondary/50 p-4 rounded-lg text-center">
<p className="text-2xl font-bold text-primary">10K+</p>
<p className="text-sm text-muted-foreground">Reddit Subscribers</p>
</div>
</div>
</div>
</div>
</motion.div>
<motion.div
initial={{ opacity: 0, x: 20 }}
whileInView={{ opacity: 1, x: 0 }}
transition={{ duration: 0.6, delay: 0.2 }}
viewport={{ once: true }}
>
<div className="bg-card rounded-lg p-8 shadow-lg">
<h3 className="text-2xl font-bold mb-6">Stay Updated</h3>
<form className="space-y-4">
<div>
<label htmlFor="email" className="block text-sm font-medium mb-1">
Email Address
</label>
<input
type="email"
id="email"
placeholder="your@email.com"
className="w-full px-4 py-2 rounded-md border border-input bg-background"
/>
</div>
<div className="flex items-start">
<input
type="checkbox"
id="newsletter"
className="mt-1 mr-2"
/>
<label htmlFor="newsletter" className="text-sm text-muted-foreground">
I agree to receive newsletters and updates about the MEME token and related products.
</label>
</div>
<Button className="w-full">
Subscribe to Newsletter
</Button>
</form>
<div className="mt-8 p-4 bg-secondary/50 rounded-lg">
<h4 className="font-semibold mb-2">Community Benefits</h4>
<ul className="space-y-2">
<li className="flex items-start">
<span className="mr-2 text-primary"></span>
<span className="text-muted-foreground">Early access to new features and products</span>
</li>
<li className="flex items-start">
<span className="mr-2 text-primary"></span>
<span className="text-muted-foreground">Exclusive airdrops for active community members</span>
</li>
<li className="flex items-start">
<span className="mr-2 text-primary"></span>
<span className="text-muted-foreground">Voting rights on important project decisions</span>
</li>
<li className="flex items-start">
<span className="mr-2 text-primary"></span>
<span className="text-muted-foreground">Direct communication with the development team</span>
</li>
</ul>
</div>
</div>
</motion.div>
</div>
</div>
</section>
)
}
export { Community }

127
src/components/footer.tsx Normal file
View File

@ -0,0 +1,127 @@
import Link from "next/link"
function Footer() {
const currentYear = new Date().getFullYear()
return (
<footer className="bg-card py-12 px-6 md:px-12 lg:px-24 border-t border-border">
<div className="container mx-auto">
<div className="grid grid-cols-1 md:grid-cols-4 gap-8">
<div className="md:col-span-1">
<Link href="/" className="flex items-center gap-2 mb-4">
<span className="text-2xl font-bold text-primary">MEME</span>
</Link>
<p className="text-muted-foreground mb-4">
The next generation meme coin with real utility and community governance.
</p>
<div className="flex space-x-4">
<a href="#" className="text-muted-foreground hover:text-primary transition-colors">
<span className="sr-only">Twitter</span>
<span className="text-xl">🐦</span>
</a>
<a href="#" className="text-muted-foreground hover:text-primary transition-colors">
<span className="sr-only">Telegram</span>
<span className="text-xl"></span>
</a>
<a href="#" className="text-muted-foreground hover:text-primary transition-colors">
<span className="sr-only">Discord</span>
<span className="text-xl">💬</span>
</a>
<a href="#" className="text-muted-foreground hover:text-primary transition-colors">
<span className="sr-only">Reddit</span>
<span className="text-xl">🤖</span>
</a>
</div>
</div>
<div>
<h3 className="font-semibold mb-4">Quick Links</h3>
<ul className="space-y-2">
<li>
<Link href="#about" className="text-muted-foreground hover:text-primary transition-colors">
About
</Link>
</li>
<li>
<Link href="#tokenomics" className="text-muted-foreground hover:text-primary transition-colors">
Tokenomics
</Link>
</li>
<li>
<Link href="#roadmap" className="text-muted-foreground hover:text-primary transition-colors">
Roadmap
</Link>
</li>
<li>
<Link href="#community" className="text-muted-foreground hover:text-primary transition-colors">
Community
</Link>
</li>
</ul>
</div>
<div>
<h3 className="font-semibold mb-4">Resources</h3>
<ul className="space-y-2">
<li>
<a href="#" className="text-muted-foreground hover:text-primary transition-colors">
Whitepaper
</a>
</li>
<li>
<a href="#" className="text-muted-foreground hover:text-primary transition-colors">
Documentation
</a>
</li>
<li>
<a href="#" className="text-muted-foreground hover:text-primary transition-colors">
Smart Contract
</a>
</li>
<li>
<a href="#" className="text-muted-foreground hover:text-primary transition-colors">
Audit Report
</a>
</li>
</ul>
</div>
<div>
<h3 className="font-semibold mb-4">Legal</h3>
<ul className="space-y-2">
<li>
<a href="#" className="text-muted-foreground hover:text-primary transition-colors">
Terms of Service
</a>
</li>
<li>
<a href="#" className="text-muted-foreground hover:text-primary transition-colors">
Privacy Policy
</a>
</li>
<li>
<a href="#" className="text-muted-foreground hover:text-primary transition-colors">
Disclaimer
</a>
</li>
<li>
<a href="#" className="text-muted-foreground hover:text-primary transition-colors">
Contact Us
</a>
</li>
</ul>
</div>
</div>
<div className="mt-12 pt-8 border-t border-border text-center text-muted-foreground">
<p>© {currentYear} MEME Token. All rights reserved.</p>
<p className="mt-2 text-sm">
Cryptocurrency investments are subject to high market risk. Please make your investments cautiously.
</p>
</div>
</div>
</footer>
)
}
export { Footer }

73
src/components/hero.tsx Normal file
View File

@ -0,0 +1,73 @@
"use client"
import Image from "next/image"
import { Button } from "@/components/ui/button"
import { motion } from "framer-motion"
function Hero() {
return (
<section className="relative min-h-screen flex items-center pt-24 pb-16 px-6 md:px-12 lg:px-24 overflow-hidden">
<div className="absolute inset-0 bg-gradient-to-b from-background to-background/80 z-0" />
{/* Background circles */}
<div className="absolute top-1/4 left-1/4 w-96 h-96 rounded-full bg-primary/10 blur-3xl" />
<div className="absolute bottom-1/4 right-1/4 w-64 h-64 rounded-full bg-primary/20 blur-3xl" />
<div className="container mx-auto grid md:grid-cols-2 gap-12 items-center relative z-10">
<motion.div
initial={{ opacity: 0, x: -50 }}
animate={{ opacity: 1, x: 0 }}
transition={{ duration: 0.8, delay: 0.2 }}
>
<h1 className="text-4xl md:text-6xl font-bold mb-6">
The Next Generation <span className="text-primary">Meme Coin</span>
</h1>
<p className="text-lg md:text-xl text-muted-foreground mb-8 max-w-lg">
Join the revolution of meme coins with our innovative, community-driven cryptocurrency that combines humor with real utility.
</p>
<div className="flex flex-col sm:flex-row gap-4">
<Button size="lg" className="text-lg">
Buy Now
</Button>
<Button size="lg" variant="outline" className="text-lg">
View Whitepaper
</Button>
</div>
<div className="mt-12 grid grid-cols-3 gap-6">
<div className="text-center">
<p className="text-3xl font-bold text-primary">$10M+</p>
<p className="text-sm text-muted-foreground">Market Cap</p>
</div>
<div className="text-center">
<p className="text-3xl font-bold text-primary">25K+</p>
<p className="text-sm text-muted-foreground">Holders</p>
</div>
<div className="text-center">
<p className="text-3xl font-bold text-primary">100K+</p>
<p className="text-sm text-muted-foreground">Community</p>
</div>
</div>
</motion.div>
<motion.div
className="relative"
initial={{ opacity: 0, scale: 0.8 }}
animate={{ opacity: 1, scale: 1 }}
transition={{ duration: 0.8, delay: 0.4 }}
>
<div className="relative w-full aspect-square max-w-md mx-auto">
{/* Placeholder for meme coin image */}
<div className="absolute inset-0 rounded-full bg-primary/20 animate-pulse" />
<div className="absolute inset-4 rounded-full bg-primary/30" />
<div className="absolute inset-8 rounded-full bg-primary/40 flex items-center justify-center">
<span className="text-6xl">🚀</span>
</div>
</div>
</motion.div>
</div>
</section>
)
}
export { Hero }

48
src/components/navbar.tsx Normal file
View File

@ -0,0 +1,48 @@
"use client"
import Link from "next/link"
import { Button } from "@/components/ui/button"
import { motion } from "framer-motion"
function Navbar() {
return (
<motion.header
className="fixed top-0 left-0 right-0 z-50 py-4 px-6 md:px-12 lg:px-24"
initial={{ opacity: 0, y: -20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.5 }}
>
<div className="container mx-auto flex items-center justify-between">
<Link href="/" className="flex items-center gap-2">
<span className="text-2xl font-bold text-primary">MEME</span>
</Link>
<nav className="hidden md:flex items-center gap-8">
<Link href="#about" className="text-foreground hover:text-primary transition-colors">
About
</Link>
<Link href="#tokenomics" className="text-foreground hover:text-primary transition-colors">
Tokenomics
</Link>
<Link href="#roadmap" className="text-foreground hover:text-primary transition-colors">
Roadmap
</Link>
<Link href="#community" className="text-foreground hover:text-primary transition-colors">
Community
</Link>
</nav>
<div className="flex items-center gap-4">
<Button variant="outline" className="hidden md:flex">
Connect Wallet
</Button>
<Button>
Buy Now
</Button>
</div>
</div>
</motion.header>
)
}
export { Navbar }

127
src/components/roadmap.tsx Normal file
View File

@ -0,0 +1,127 @@
"use client"
import { motion } from "framer-motion"
function Roadmap() {
const roadmapItems = [
{
phase: "Phase 1",
title: "Launch & Community Building",
items: [
"Website and social media launch",
"Community building on Twitter, Telegram, and Discord",
"Initial marketing campaign",
"Token launch on DEX",
"CoinGecko and CoinMarketCap listings"
],
status: "completed"
},
{
phase: "Phase 2",
title: "Expansion & Partnerships",
items: [
"Strategic partnerships with influencers",
"CEX listings (Tier 2 exchanges)",
"Enhanced marketing campaigns",
"Community growth initiatives",
"Development of utility features"
],
status: "in-progress"
},
{
phase: "Phase 3",
title: "Utility Development",
items: [
"Launch of staking platform",
"NFT collection release",
"Community governance implementation",
"Major CEX listings (Tier 1 exchanges)",
"Cross-chain bridge deployment"
],
status: "upcoming"
},
{
phase: "Phase 4",
title: "Ecosystem Expansion",
items: [
"Meme marketplace development",
"Mobile app launch",
"Metaverse integration",
"Global marketing campaign",
"Strategic acquisitions"
],
status: "upcoming"
}
]
return (
<section id="roadmap" className="py-24 px-6 md:px-12 lg:px-24 bg-secondary/30">
<div className="container mx-auto">
<motion.div
className="text-center mb-16"
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6 }}
viewport={{ once: true }}
>
<h2 className="text-3xl md:text-5xl font-bold mb-4">Roadmap</h2>
<p className="text-lg text-muted-foreground max-w-2xl mx-auto">
Our strategic plan for growth and development over time.
</p>
</motion.div>
<div className="relative">
{/* Vertical line */}
<div className="absolute left-1/2 transform -translate-x-1/2 h-full w-1 bg-primary/30 hidden md:block"></div>
<div className="space-y-12">
{roadmapItems.map((item, index) => (
<motion.div
key={index}
className="relative"
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6, delay: index * 0.1 }}
viewport={{ once: true }}
>
<div className={`md:flex items-center ${index % 2 === 0 ? 'md:flex-row' : 'md:flex-row-reverse'}`}>
{/* Circle on timeline */}
<div className="absolute left-1/2 transform -translate-x-1/2 w-6 h-6 rounded-full hidden md:block">
<div className={`w-full h-full rounded-full ${
item.status === 'completed' ? 'bg-primary' :
item.status === 'in-progress' ? 'bg-yellow-500 animate-pulse' :
'bg-secondary border-2 border-primary/50'
}`}></div>
</div>
<div className={`md:w-1/2 ${index % 2 === 0 ? 'md:pr-12 md:text-right' : 'md:pl-12'}`}>
<div className="bg-card rounded-lg p-6 shadow-lg">
<div className={`inline-block px-3 py-1 rounded-full text-xs font-semibold mb-2 ${
item.status === 'completed' ? 'bg-primary/20 text-primary' :
item.status === 'in-progress' ? 'bg-yellow-500/20 text-yellow-500' :
'bg-secondary text-muted-foreground'
}`}>
{item.phase}
</div>
<h3 className="text-xl font-bold mb-4">{item.title}</h3>
<ul className="space-y-2">
{item.items.map((listItem, listIndex) => (
<li key={listIndex} className="flex items-start">
<span className="mr-2 text-primary"></span>
<span className="text-muted-foreground">{listItem}</span>
</li>
))}
</ul>
</div>
</div>
</div>
</motion.div>
))}
</div>
</div>
</div>
</section>
)
}
export { Roadmap }

View File

@ -0,0 +1,144 @@
"use client"
import { motion } from "framer-motion"
function Tokenomics() {
const tokenDistribution = [
{ name: "Public Sale", percentage: 40, color: "bg-primary" },
{ name: "Team & Advisors", percentage: 15, color: "bg-blue-500" },
{ name: "Marketing", percentage: 10, color: "bg-purple-500" },
{ name: "Development", percentage: 15, color: "bg-pink-500" },
{ name: "Liquidity", percentage: 10, color: "bg-yellow-500" },
{ name: "Community Rewards", percentage: 10, color: "bg-orange-500" }
]
return (
<section id="tokenomics" className="py-24 px-6 md:px-12 lg:px-24">
<div className="container mx-auto">
<motion.div
className="text-center mb-16"
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6 }}
viewport={{ once: true }}
>
<h2 className="text-3xl md:text-5xl font-bold mb-4">Tokenomics</h2>
<p className="text-lg text-muted-foreground max-w-2xl mx-auto">
Our token economics are designed for long-term sustainability and growth.
</p>
</motion.div>
<div className="grid md:grid-cols-2 gap-12 items-center">
<motion.div
initial={{ opacity: 0, x: -20 }}
whileInView={{ opacity: 1, x: 0 }}
transition={{ duration: 0.6 }}
viewport={{ once: true }}
>
<div className="bg-card rounded-lg p-8 shadow-lg">
<h3 className="text-2xl font-bold mb-6">Token Distribution</h3>
<div className="space-y-6">
{tokenDistribution.map((item, index) => (
<div key={index}>
<div className="flex justify-between mb-2">
<span>{item.name}</span>
<span className="font-semibold">{item.percentage}%</span>
</div>
<div className="w-full bg-secondary rounded-full h-2.5">
<div
className={`${item.color} h-2.5 rounded-full`}
style={{ width: `${item.percentage}%` }}
></div>
</div>
</div>
))}
</div>
<div className="mt-8 p-4 bg-secondary/50 rounded-lg">
<h4 className="font-semibold mb-2">Token Details</h4>
<div className="grid grid-cols-2 gap-4">
<div>
<p className="text-sm text-muted-foreground">Name</p>
<p className="font-medium">MEME Token</p>
</div>
<div>
<p className="text-sm text-muted-foreground">Symbol</p>
<p className="font-medium">MEME</p>
</div>
<div>
<p className="text-sm text-muted-foreground">Total Supply</p>
<p className="font-medium">1,000,000,000</p>
</div>
<div>
<p className="text-sm text-muted-foreground">Blockchain</p>
<p className="font-medium">Ethereum</p>
</div>
</div>
</div>
</div>
</motion.div>
<motion.div
initial={{ opacity: 0, x: 20 }}
whileInView={{ opacity: 1, x: 0 }}
transition={{ duration: 0.6, delay: 0.2 }}
viewport={{ once: true }}
>
<div className="bg-card rounded-lg p-8 shadow-lg">
<h3 className="text-2xl font-bold mb-6">Transaction Fees</h3>
<div className="space-y-6">
<div>
<div className="flex justify-between items-center mb-4">
<div>
<h4 className="font-semibold">Buy Fee: 5%</h4>
<p className="text-sm text-muted-foreground">Breakdown of fees when buying tokens</p>
</div>
<span className="text-3xl">💸</span>
</div>
<div className="grid grid-cols-2 gap-4">
<div className="bg-secondary/50 p-3 rounded-lg">
<p className="font-medium">3%</p>
<p className="text-sm text-muted-foreground">Marketing</p>
</div>
<div className="bg-secondary/50 p-3 rounded-lg">
<p className="font-medium">2%</p>
<p className="text-sm text-muted-foreground">Liquidity</p>
</div>
</div>
</div>
<div>
<div className="flex justify-between items-center mb-4">
<div>
<h4 className="font-semibold">Sell Fee: 7%</h4>
<p className="text-sm text-muted-foreground">Breakdown of fees when selling tokens</p>
</div>
<span className="text-3xl">🔥</span>
</div>
<div className="grid grid-cols-3 gap-4">
<div className="bg-secondary/50 p-3 rounded-lg">
<p className="font-medium">3%</p>
<p className="text-sm text-muted-foreground">Marketing</p>
</div>
<div className="bg-secondary/50 p-3 rounded-lg">
<p className="font-medium">2%</p>
<p className="text-sm text-muted-foreground">Liquidity</p>
</div>
<div className="bg-secondary/50 p-3 rounded-lg">
<p className="font-medium">2%</p>
<p className="text-sm text-muted-foreground">Burn</p>
</div>
</div>
</div>
</div>
</div>
</motion.div>
</div>
</div>
</section>
)
}
export { Tokenomics }

View File

@ -0,0 +1,53 @@
import * as React from "react"
import { Slot } from "@radix-ui/react-slot"
import { cva, type VariantProps } from "class-variance-authority"
import { cn } from "@/lib/utils"
const buttonVariants = cva(
"inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
{
variants: {
variant: {
default: "bg-primary text-primary-foreground hover:bg-primary/90",
destructive:
"bg-destructive text-destructive-foreground hover:bg-destructive/90",
outline:
"border border-input bg-background hover:bg-accent hover:text-accent-foreground",
secondary:
"bg-secondary text-secondary-foreground hover:bg-secondary/80",
ghost: "hover:bg-accent hover:text-accent-foreground",
link: "text-primary underline-offset-4 hover:underline",
},
size: {
default: "h-10 px-4 py-2",
sm: "h-9 rounded-md px-3",
lg: "h-11 rounded-md px-8",
icon: "h-10 w-10",
},
},
defaultVariants: {
variant: "default",
size: "default",
},
}
)
export interface ButtonProps
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
VariantProps<typeof buttonVariants> {
asChild?: boolean
}
function Button(
{ className, variant, size, asChild = false, ...props }: ButtonProps,
) {
const Comp = asChild ? Slot : "button"
return (
<Comp
className={cn(buttonVariants({ variant, size, className }))}
{...props}
/>
)
}
export { Button, buttonVariants }

6
src/lib/utils.ts Normal file
View File

@ -0,0 +1,6 @@
import { type ClassValue, clsx } from "clsx"
import { twMerge } from "tailwind-merge"
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}

74
tailwind.config.js Normal file
View File

@ -0,0 +1,74 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
'./src/pages/**/*.{js,ts,jsx,tsx,mdx}',
'./src/components/**/*.{js,ts,jsx,tsx,mdx}',
'./src/app/**/*.{js,ts,jsx,tsx,mdx}',
],
theme: {
container: {
center: true,
padding: "2rem",
screens: {
"2xl": "1400px",
},
},
extend: {
colors: {
border: "hsl(var(--border))",
input: "hsl(var(--input))",
ring: "hsl(var(--ring))",
background: "hsl(var(--background))",
foreground: "hsl(var(--foreground))",
primary: {
DEFAULT: "hsl(var(--primary))",
foreground: "hsl(var(--primary-foreground))",
},
secondary: {
DEFAULT: "hsl(var(--secondary))",
foreground: "hsl(var(--secondary-foreground))",
},
destructive: {
DEFAULT: "hsl(var(--destructive))",
foreground: "hsl(var(--destructive-foreground))",
},
muted: {
DEFAULT: "hsl(var(--muted))",
foreground: "hsl(var(--muted-foreground))",
},
accent: {
DEFAULT: "hsl(var(--accent))",
foreground: "hsl(var(--accent-foreground))",
},
popover: {
DEFAULT: "hsl(var(--popover))",
foreground: "hsl(var(--popover-foreground))",
},
card: {
DEFAULT: "hsl(var(--card))",
foreground: "hsl(var(--card-foreground))",
},
},
borderRadius: {
lg: "var(--radius)",
md: "calc(var(--radius) - 2px)",
sm: "calc(var(--radius) - 4px)",
},
keyframes: {
"accordion-down": {
from: { height: 0 },
to: { height: "var(--radix-accordion-content-height)" },
},
"accordion-up": {
from: { height: "var(--radix-accordion-content-height)" },
to: { height: 0 },
},
},
animation: {
"accordion-down": "accordion-down 0.2s ease-out",
"accordion-up": "accordion-up 0.2s ease-out",
},
},
},
plugins: [require("tailwindcss-animate")],
}

28
tsconfig.json Normal file
View File

@ -0,0 +1,28 @@
{
"compilerOptions": {
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"plugins": [
{
"name": "next"
}
],
"paths": {
"@/*": ["./src/*"]
}
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"exclude": ["node_modules"]
}