Next.js × Tailwind CSSで作る🐰AIおみくじアプリ💝🪄

# 🎀✨ Koroちゃんの超かわいいおみくじアプリ 🐰🔮<br>
🎀✨ Koro-chan's Super Cute Fortune-Telling App 🐰🔮

🌸Koro's Kawaii Omikuji🌸

React で作る超可愛い365日運勢アプリ 🎋
Super cute 365-day fortune app made with React 🎋

100種類の日本語&英語バイリンガル翻訳🎌
100 different bilingual Japanese & English translations 🎌

MarkdownAI (v0,ChatGPT,Gemini,Claude,Copilot AI etc...)

<a href="https://b_lecemouxv47.v0.build/" target="_blank">![おみくじを引く.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3937957/84b2a947-6dde-1a24-1c2f-e2873ec5c34c.jpeg)</a>


https://b_LEcEmOuxv47.v0.build/

Koroちゃん（兎耳コロちゃん）です🐰
今日は、Next.jsを使って、とってもキラキラで可愛いKoroちゃんのおみくじアプリを一緒に作っちゃいましょう🌟

Hi, I'm Koro-chan (Usamimi Koro-chan) 🐰
Today, let's create a super sparkly and cute Koro-chan's fortune-telling app together using Next.js! 🌟

[Koroちゃんおみくじ](https://b_LEcEmOuxv47.v0.build/ "Koro's Omikuji")



## 🌈 このアプリの魅力ポイント<br>
🌈Charm Points of This App

- 💖  100種類以上の日本語と英語のおみくじメッセージ！運勢たくさん！<br>Over 100 enchanting fortune messages in both Japanese and English! So many destinies to discover!
- 🎉 ふわふわハートとキラキラエフェクトでめちゃかわいい！<br>Ultra-adorable with fluffy floating hearts and twinkling sparkle effects!
- 🌙 お昼も夜も使えるダークモード対応！<br>Usable day and night with our magical dark mode transformation!
- 📱 スマホでもパソコンでも、どこでも占えちゃう！<br> Divine your fortune anywhere - on your pocket crystal ball (smartphone) or your desktop magic mirror (computer)!
- 🔤 おみくじの文字サイズが自動で調整されるの、すごい！<br>The fortune message magically resizes itself - how wonderfully clever!


## 🍭 使った技術 <br>
🍭 Our Spellbinding Toolkit

- <b>Next.js (App Router) </b><br>- Webアプリの魔法の杖✨ <br>- The magic wand for crafting web app wonders ✨
- <b>Tailwind CSS</b><br> - 見た目をかわいくする魔法の絵の具🎨 <br> - The enchanted paintbrush for creating cuteness 🎨
- <b>shadcn/ui</b><br> - 便利な魔法のUIコンポーネント箱📦 <br>- A treasure chest of handy magical UI components 📦
- <b>Lucide Icons</b><br> - かわいいアイコンがいっぱいの宝石箱💎 <br>- A jewelry box overflowing with the cutest little icons 💎
- <b>React Hooks</b><br> - アプリをもっと賢くする魔法の呪文書📜 <br>- The spell book for making our app extra smart and savvy 📜



## 🎨 完成形はこんな感じ <br>
🎨 Here's What the Finished Product Looks Like

<a href="https://b_lecemouxv47.v0.build/" target="_blank">![Koroの可愛いおみくじ.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3937957/c9e92c08-3446-66cf-b415-f267e70d3922.jpeg)</a>


かわいいでしょ？😍 それじゃあ、コードを見ていきましょう！
Isn't it cute? 😍 Now, let's take a look at the code!

## 📝魔法のコード全文 <br>
📝Full text of the magic code

まずは、KoroOmikuji.tsxというファイルを作って、以下のコードを書いてね！
First, create a file called KoroOmikuji.tsx and write the following code!

```tsx
'use client'

import { useState, useEffect, useRef } from 'react'
import { Button } from "@/components/ui/button"
import { Card, CardContent } from "@/components/ui/card"
import { Heart, Sparkles, Star } from 'lucide-react'
import Image from 'next/image'

export default function KoroOmikuji() {
  const [isRevealed, setIsRevealed] = useState(false)
  const [isShaking, setIsShaking] = useState(false)
  const [fortune, setFortune] = useState({ ja: '', en: '', luck: '' })
  const fortuneRef = useRef<HTMLParagraphElement>(null)
  
  const fortunes = [
    { ja: "キラキラ幸せがいっぱい降り注ぐよ♪", en: "Sparkling happiness rains down on you♪", luck: "超大吉" },
    { ja: "夢見るキミの願い事、きっと叶うよ☆", en: "Your dreamy wish will surely come true☆", luck: "大吉" },
    // ... (他のおみくじメッセージ)
  ];

  const drawFortune = () => {
    setIsShaking(true)
    setTimeout(() => {
      const randomFortune = fortunes[Math.floor(Math.random() * fortunes.length)]
      setFortune(randomFortune)
      setIsRevealed(true)
      setIsShaking(false)
    }, 1000)
  }

  useEffect(() => {
    const adjustFontSize = () => {
      if (fortuneRef.current) {
        let fontSize = 20;
        fortuneRef.current.style.fontSize = `\${fontSize}px`;
        while (fortuneRef.current.scrollWidth > fortuneRef.current.offsetWidth && fontSize > 10) {
          fontSize--;
          fortuneRef.current.style.fontSize = `\${fontSize}px`;
        }
      }
    };

    if (isRevealed) {
      adjustFontSize();
      window.addEventListener('resize', adjustFontSize);
    }

    return () => window.removeEventListener('resize', adjustFontSize);
  }, [isRevealed, fortune]);

  return (
    <Card className="w-full max-w-md bg-gradient-to-br from-pink-50 to-purple-50 dark:from-pink-950 dark:to-purple-950 overflow-hidden">
      <CardContent className="p-6">
        <div className="flex flex-col items-center gap-6 text-center relative">
          <div className="absolute inset-0 overflow-hidden pointer-events-none">
            {[...Array(12)].map((_, i) => (
              <Heart
                key={i}
                className="absolute text-pink-200 animate-float"
                style={{
                  left: `\${Math.random() * 100}%`,
                  top: `\${Math.random() * 100}%`,
                  animationDelay: `\${Math.random() * 5}s`,
                  width: `\${Math.random() * 20 + 10}px`,
                  height: `\${Math.random() * 20 + 10}px`
                }}
              />
            ))}
          </div>

          <div className="space-y-2">
            <h1 className="text-4xl font-bold text-pink-400 font-serif tracking-wide">Koro's Omikuji</h1>
            <p className="text-lg text-pink-300">キラキラ☆おみくじ</p>
          </div>

          <div className="relative w-64 h-64">
            <Image
              src="https://hebbkx1anhila5yf.public.blob.vercel-storage.com/S__66600971.jpg-T8RIoerNLqMDUjhk8KNN1p4yD5rQYP.jpeg"
              alt="Koro-chan"
              width={256}
              height={256}
              className={`rounded-full border-4 border-pink-200 shadow-xl \${isShaking ? 'animate-shake' : ''}`}
            />
            <Sparkles className="absolute top-0 right-0 text-yellow-300 animate-pulse" />
            <Star className="absolute bottom-0 left-0 text-yellow-300 animate-pulse" />
          </div>

          <div className="relative w-full min-h-[180px] flex items-center justify-center">
            {!isRevealed ? (
              <Button
                onClick={drawFortune}
                className="bg-pink-400 hover:bg-pink-500 text-white px-8 py-4 rounded-full shadow-lg transform transition hover:scale-105 font-medium text-lg"
              >
                おみくじを引く♪
              </Button>
            ) : (
              <div className="bg-white/95 dark:bg-black/95 p-4 rounded-2xl shadow-xl w-full transform animate-unfold">
                <div className="mb-2">
                  <span className="text-2xl font-bold text-pink-500">{fortune.luck}</span>
                </div>
                <p 
                  ref={fortuneRef}
                  className="text-xl font-medium text-pink-500 dark:text-pink-300 mb-2 whitespace-nowrap overflow-hidden"
                >
                  {fortune.ja}
                </p>
                <p className="text-sm text-pink-400 dark:text-pink-200">
                  {fortune.en}
                </p>
                <div className="flex justify-center gap-2 mt-3">
                  <Heart className="text-pink-400 w-5 h-5 animate-bounce" fill="currentColor" />
                  <Heart className="text-pink-300 w-5 h-5 animate-bounce delay-100" fill="currentColor" />
                  <Heart className="text-pink-200 w-5 h-5 animate-bounce delay-200" fill="currentColor" />
                </div>
              </div>
            )}
          </div>
          
          {isRevealed && (
            <Button
              onClick={() => setIsRevealed(false)}
              variant="ghost"
              className="text-pink-400 hover:text-pink-500 hover:bg-pink-50"
            >
              もう一度占う♡
            </Button>
          )}
          
          <div className="text-sm text-pink-300">
            @KoroVRM
          </div>
        </div>
      </CardContent>

      <style jsx global>{`
        @keyframes float {
          0%, 100% { transform: translateY(0) rotate(0deg); }
          50% { transform: translateY(-20px) rotate(20deg); }
        }
        @keyframes unfold {
          0% { transform: scaleY(0.1); opacity: 0; }
          100% { transform: scaleY(1); opacity: 1; }
        }
        @keyframes shake {
          0%, 100% { transform: translateX(0); }
          25% { transform: translateX(-5px); }
          75% { transform: translateX(5px); }
        }
        .animate-float {
          animation: float 3s ease-in-out infinite;
        }
        .animate-unfold {
          animation: unfold 0.6s ease-out;
        }
        .animate-shake {
          animation: shake 0.2s ease-in-out 5;
        }
      `}</style>
    </Card>
  )
}
```

## 🪄 魔法のコードの解説 <br>
🪄 Explanation of the Magical Code

次に、このかわいい魔法のコードの中身を、詳しく見ていきましょう💖
Next, let's take a closer look at what's inside this cute magic code 💖

### 1. おみくじメッセージの宝箱 📜 <br>
１. Treasure Box of Fortune Messages 📜

```typescript
const fortunes = [
  { ja: "キラキラ幸せがいっぱい降り注ぐよ♪", en: "Sparkling happiness rains down on you♪", luck: "超大吉" },
  { ja: "夢見るキミの願い事、きっと叶うよ☆", en: "Your dreamy wish will surely come true☆", luck: "大吉" },
  // ... (他のおみくじメッセージ)
];
```

これが、Koroちゃんが用意したおみくじメッセージの宝箱だよ！日本語と英語のメッセージ、そして運勢が入ってるんだ。全部で100個くらいあるから、いろんなメッセージが出てくるよ✨

This is the treasure box of fortune messages that Koro-chan prepared for us! It contains Japanese and English messages, as well as the fortune level. There are about 100 messages in total, so you'll get a variety of fortunes✨

### 2. おみくじを引く魔法の呪文 🎐 <br>
２. The Magic Spell for Drawing a Fortune 🎐

```typescript
const drawFortune = () => {
  setIsShaking(true)
  setTimeout(() => {
    const randomFortune = fortunes[Math.floor(Math.random() * fortunes.length)]
    setFortune(randomFortune)
    setIsRevealed(true)
    setIsShaking(false)
  }, 1000)
}
```

この関数がおみくじを引く時の魔法の呪文だよ！まず、Koroちゃんの画像がゆれるようにして（`setIsShaking(true)`）、1秒待ってから（`setTimeout`）、ランダムにおみくじを選んで表示するんだ。わくわくするね🌟

This function is the magic spell for drawing a fortune! First, it makes Koro-chan's image shake (`setIsShaking(true)`), then waits for 1 second (`setTimeout`), and finally selects and displays a random fortune. It's so exciting🌟

### 3. 文字サイズを自動調整する魔法 📏 <br>
３. The Magic of Auto-Adjusting Font Size 📏


```typescript
useEffect(() => {
  const adjustFontSize = () => {
    if (fortuneRef.current) {
      let fontSize = 20;
      fortuneRef.current.style.fontSize = `\${fontSize}px`;
      while (fortuneRef.current.scrollWidth > fortuneRef.current.offsetWidth && fontSize > 10) {
        fontSize--;
        fortuneRef.current.style.fontSize = `\${fontSize}px`;
      }
    }
  };

  if (isRevealed) {
    adjustFontSize();
    window.addEventListener('resize', adjustFontSize);
  }

  return () => window.removeEventListener('resize', adjustFontSize);
}, [isRevealed, fortune]);
```

これは、おみくじの結果がきれいに表示されるようにする魔法の呪文だよ！長いメッセージも短いメッセージも、ぴったりのサイズで表示されるんだ。すごいでしょ？😊

This is the magic spell that makes sure the fortune results are displayed beautifully! Whether the message is long or short, it will be shown in just the right size. Isn't that amazing?😊



### 4. かわいいデザインの魔法 🎨 <br>
４. The Magic of Cute Design 🎨

### カラーパレット <br>
Color Palette

- メインカラー：優しいピンク (`#F9A8D4`) <br>Main color: Gentle pink (`#F9A8D4`)
- アクセントカラー：パープル (`#E9D5FF`)<br>Accent color: Purple (`#E9D5FF`)
- テキストカラー：ダークピンク (`#EC4899`)<br>Text color: Dark pink (`#EC4899`)


###  レスポンシブ対応<br> 
Responsive Design

スマートフォンでもPCでも最適な表示になるよう、Tailwind CSSのユーティリティクラスを活用：
Utilizing Tailwind CSS utility classes for optimal display on both smartphones and PCs:

```typescript
<div className="w-full max-w-md mx-auto">
```


### ダークモード対応<br>
Dark Mode Support

```typescript
<Card className="bg-gradient-to-br from-pink-50 to-purple-50 dark:from-pink-950 dark:to-purple-950">
```


###  フォーチュンカード<br> 
Fortune Card

```typescriptreact
<Card className="w-full max-w-md bg-gradient-to-br from-pink-50 to-purple-50 dark:from-pink-950 dark:to-purple-950 overflow-hidden">
  {/* ... */}
</Card>
```

このカードが、おみくじアプリ全体を包み込んでるんだ。ピンクから紫のグラデーションで、とってもかわいい感じになってるよ！ダークモードにも対応してるから、夜でも使えるんだ🌙✨

This card wraps the entire fortune-telling app. With a gradient from pink to purple, it gives a very cute feel! It also supports dark mode, so you can use it at night too🌙✨


### 5. ふわふわハートを作る魔法 🎀 <br>
５. The Magic of Creating Fluffy Hearts 🎀

```typescriptreact
{[...Array(12)].map((_, i) => (
  <Heart
    key={i}
    className="absolute text-pink-200 animate-float"
    style={{
      left: `\${Math.random() * 100}%`,
      top: `\${Math.random() * 100}%`,
      animationDelay: `\${Math.random() * 5}s`,
      width: `\${Math.random() * 20 + 10}px`,
      height: `\${Math.random() * 20 + 10}px`
    }}
  />
))}
```

これが、画面上をふわふわ浮かぶハートを作る魔法だよ！ランダムな位置とサイズで12個のハートが浮かんでるように見えるんだ。とってもロマンチック💕

This is the magic that creates the fluffy floating hearts on the screen! It makes 12 hearts appear to be floating with random positions and sizes. It's so romantic💕

### 6. Koroちゃんの魔法の鏡 🐰 <br>
６. Koro-chan's Magic Mirror 🐰

```typescriptreact
<div className="relative w-64 h-64">
  <Image
    src="https://hebbkx1anhila5yf.public.blob.vercel-storage.com/S__66600971.jpg-T8RIoerNLqMDUjhk8KNN1p4yD5rQYP.jpeg"
    alt="Koro-chan"
    width={256}
    height={256}
    className={`rounded-full border-4 border-pink-200 shadow-xl \${isShaking ? 'animate-shake' : ''}`}
  />
  <Sparkles className="absolute top-0 right-0 text-yellow-300 animate-pulse" />
  <Star className="absolute bottom-0 left-0 text-yellow-300 animate-pulse" />
</div>
```

ここがKoroちゃんの魔法の鏡を表示する部分だよ。丸い形にして、ピンクの枠をつけてるんだ。おみくじを引く時には`animate-shake`クラスがつくから、ゆれるようになるんだよ。キラキラとお星様のアイコンもついてて、とってもかわいいでしょ？✨

This is the part that displays Koro-chan's magic mirror. It's made into a circular shape with a pink frame. When drawing a fortune, the `animate-shake` class is added, making it shake. With sparkling and star icons, it's super cute, isn't it?✨

### 7. おみくじ結果を表示する魔法の巻物 📜 <br>
７. The Magic Scroll Displaying Fortune Results 📜

```typescriptreact
<div className="bg-white/95 dark:bg-black/95 p-4 rounded-2xl shadow-xl w-full transform animate-unfold">
  <div className="mb-2">
    <span className="text-2xl font-bold text-pink-500">{fortune.luck}</span>
  </div>
  <p 
    ref={fortuneRef}
    className="text-xl font-medium text-pink-500 dark:text-pink-300 mb-2 whitespace-nowrap overflow-hidden"
  >
    {fortune.ja}
  </p>
  <p className="text-sm text-pink-400 dark:text-pink-200">
    {fortune.en}
  </p>
  <div className="flex justify-center gap-2 mt-3">
    <Heart className="text-pink-400 w-5 h-5 animate-bounce" fill="currentColor" />
    <Heart className="text-pink-300 w-5 h-5 animate-bounce delay-100" fill="currentColor" />
    <Heart className="text-pink-200 w-5 h-5 animate-bounce delay-200" fill="currentColor" />
  </div>
</div>
```

ここがおみくじの結果を表示する魔法の巻物だよ。運勢、日本語のメッセージ、英語のメッセージが順番に表示されるんだ。下にはかわいくはずむハートもついてるよ。`animate-unfold`クラスのおかげで、結果がふわっと現れるようになってるんだ。素敵でしょ？🌸

This is the magic scroll that displays the fortune results. The fortune level, Japanese message, and English message are displayed in order. There are cute bouncing hearts at the bottom too. Thanks to the `animate-unfold` class, the result appears with a soft unfolding animation. Isn't it lovely?🌸

### 8. アニメーションの魔法の呪文 💫 <br>
８. The Magic Spells for Animations 💫

```css
@keyframes float {
  0%, 100% { transform: translateY(0) rotate(0deg); }
  50% { transform: translateY(-20px) rotate(20deg); }
}
@keyframes unfold {
  0% { transform: scaleY(0.1); opacity: 0; }
  100% { transform: scaleY(1); opacity: 1; }
}
@keyframes shake {
  0%, 100% { transform: translateX(0); }
  25% { transform: translateX(-5px); }
  75% { transform: translateX(5px); }
}
```

これらが、アプリをもっとかわいく動かすための魔法の呪文だよ。ふわふわ浮かぶハート、ふわっと広がる結果表示、ゆれるKoroちゃんの画像、全部ここで定義されてるんだ。これらの魔法のおかげで、アプリがとってもキュートに動くんだよ🎀

These are the magic spells that make the app move in a cuter way. The fluffy floating hearts, the softly expanding result display, the shaking Koro-chan image - they're all defined here. Thanks to these spells, the app moves in a super cute way🎀

## 🚀 デプロイ <br>
🚀deploy

このKoroちゃんおみくじアプリは、[Vercel](https://b_LEcEmOuxv47.v0.build/)にデプロイされています。実際に動くアプリを見ていただけます！
This Koro Chan Omikuji application is deployed on [Vercel](https://b_LEcEmOuxv47.v0.build/). You can see the application in action!

Next.jsとTailwind CSSを使うことで、見た目も機能も充実した可愛いおみくじアプリを作ることができました。
By using Next.js and Tailwind CSS, I were able to create a lovely fortune-telling application that looks and functions well.

このプロジェクトを通じて、モダンなWeb技術とかわいいデザインの融合について多くの学びがありました。
Through this project, I learned a lot about blending modern web technology with cute design.


## 🎈 まとめ <br>
🎈 Summary

これで、Koroちゃんの超かわいいおみくじアプリの完成🎉
And with that, Koro-chan's super cute fortune-telling app is complete🎉

このアプリは：
This app:

- Next.jsとReact Hooksの魔法で、動きのあるアプリを作ったよ <br>Uses the magic of Next.js and React Hooks to create an interactive app
- Tailwind CSSとshadcn/uiの魔法で、見た目をキラキラ可愛くしたの <br>Uses the magic of Tailwind CSS and shadcn/ui to make the appearance sparkly and cute
- たくさんのアニメーションの魔法で、楽しい体験を作れたね <br>Creates a fun experience with lots of animation magic
- 日本語と英語のバイリンガル対応で、みんなが使えるようになってるよ <br>Is bilingual in Japanese and English, so everyone can use it


みんなも、この魔法のコードを使って自分だけのかわいいおみくじアプリを作ってみてね🌈✨
Everyone, try using this magical code to create your own cute fortune-telling app🌈✨

## 🌟 カスタマイズのアイデア <br>
🌟 Customization Ideas

1. 🎨 色やグラデーションを変えて、自分好みの魔法の世界を作ってみよう <br> Try changing the colors and gradients to create your own magical world
2. 🐇 Koroちゃんの画像を自分のお気に入りキャラクターに変えてみるのも楽しいかも <br> It might be fun to change Koro-chan's image to your favorite character
3. 🌌 新しいアニメーションの魔法を追加して、もっと華やかにしてみよう <br> Try adding new animation magic to make it even more glamorous
4. 📱 SNSシェア機能をつけて、みんなに運勢を教えられる魔法をかけるのも面白いね <br> It could be interesting to add a social media sharing feature so you can share your fortune with everyone






Koroちゃんと一緒に、楽しい魔法のコーディングしようね💖🐰
Let's do some fun magical coding with Koro-chan💖🐰

Happy magical coding✨🌈🎀


## 🔗 参考リンク<br>
🔗 Reference Links

- [Next.js公式ドキュメント](https://nextjs.org/docs)
- [Tailwind CSS公式ドキュメント](https://tailwindcss.com/docs)
- [shadcn/ui](https://ui.shadcn.com/)
- [Lucide Icons](https://lucide.dev/)



## 🐇 作者について <br>
🐇 About Author

- Twitter: [@KoroVRM](https://twitter.com/KoroVRM)
- GitHub: [このプロジェクトのリポジトリ](https://github.com/korovrm)

https://www.foriio.com/korovrm

https://note.com/korovrm/


🪄Next.js × Tailwind CSS で作る🐰
100種類の癒し系日本語&英語バイリンガルAIおみくじアプリ💝

https://qiita.com/korovrm/items/cd088d24ca9f0066fa9f

https://zenn.dev/korovrm/articles/288ae2b82a6d59

https://zenn.dev/korovrm/books/8e7e595a299eb4

https://zenn.dev/korovrm/books/a836c4d432e4ac

https://qiita.com/korovrm/items/7b32f7c15954e530e104

https://korochan-ai-chatbot.created.app/