Sınav öncesi gece geç saatlere kadar çalışıp her şeyi ezberlemeye çalıştıysanız, ne kadar zor olduğunu bilirsiniz. Flashcard'lar (kart çalışma yöntemi) en etkili çalışma araçlarından biridir. Çünkü **aktif hatırlama** prensibini kullanırlar — beyninizi bilgiyi pasif bir şekilde tekrar okumak yerine, aktif olarak çekmeye zorlarlar.
Dijital bir flashcard uygulaması geliştirmek, modern web geliştirmeyi eğitim psikolojisiyle birleştirir. Bu rehberde, Next.js (frontend ve backend için) ve MongoDB (veri depolama için) kullanarak tam yığın (full-stack) bir flashcard uygulaması nasıl oluşturulur, adım adım anlatacağım.
Neden Flashcard Uygulaması Geliştirelim?
Dijital flashcard'lar, fiziksel kartlara göre birkaç avantaj sunar:
- **Taşınabilirlik**: İnternet varsa dükkanlarınız her yerden erişilebilir
- **Aralıklı tekrar (spaced repetition)**: Algoritmalar tekrar zamanlamasını optimize edebilir
- **Medya desteği**: Görseller, ses dosyaları ve formatlama
- **İlerleme takibi**: Öğrenme performansınız hakkında analitik veriler
Gerçek Hayat Kullanım Senaryoları
Koda dalmadan önce, uygulamamızın parladığı bu senaryoları düşünün:
1. **Tıp Öğrencileri**: Görsellerle detaylı anatomi flashcard'ları oluşturmak
2. **Dil Öğrenenler**: Telaffuz ses dosyalarıyla kelime hazinesi dükkanları hazırlamak
3. **Profesyonel Sertifikasyon**: Karmaşık teknik kavramları sistematik olarak organize etmek
Teknoloji Yığını (Tech Stack) Özeti
Kullanacağımız araçlar:
- **Next.js 14** (Sunucu tarafı renderlama özelliğine sahip React framework'ü)
- **MongoDB Atlas** (Bulut veritabanı)
- **Mongoose** (MongoDB nesne modelleme aracı)
- **Tailwind CSS** (Styling için)
Neden bu yığın? Next.js hem frontend'i hem de API route'larını yönetir, bu da deployment'ı basitleştirir. MongoDB'nin esnek şeması, değişen flashcard yapıları için uygundur.
Projeyi Kurma
Önce yeni bir Next.js projesi oluşturalım:
```bash
npx create-next-app@latest flashcard-app
cd flashcard-app
npm install mongoose mongodb
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
```
`tailwind.config.js` dosyasını yapılandıralım:
```javascript
/** @type {import('tailwindcss').tailwind.config} */
module.exports = {
content: [
"./app/**/*.{js,jsx,ts,jsx}",
"./pages/**/*.{js,jsx,ts,jsx}",
"./components/**/*.{js,jsx,ts,jsx}",
],
theme: {
extend: {},
},
plugins: [],
}
```
`app/globals.css` dosyasına ekleyin:
```css
@tailwind base;
@tailwind components;
@tailwind utilities;
```
Veritabanı Bağlantısı
`lib/mongodb.js` dosyasını oluşturun:
```javascript
import { MongoClient } from 'mongodb'
const uri = process.env.MONGODB_URI
const options = {
useNewUrlParser: true,
useUnifiedTopology: true,
}
let client
let clientPromise
if (!process.env.MONGODB_URI) {
throw new Error('Lütfen MongoDB URI\'nizi .env.local dosyasına ekleyin')
}
if (process.env.NODE_ENV === 'development') {
if (!global._mongoClientPromise) {
client = new MongoClient(uri, options)
global._mongoClientPromise = client.connect()
}
clientPromise = global._mongoClientPromise
} else {
client = new MongoClient(uri, options)
clientPromise = client.connect()
}
export default clientPromise
```
Flashcard Modeli Oluşturma
`models/Flashcard.js` dosyasında:
```javascript
import mongoose from 'mongoose'
const flashcardSchema = new mongoose.Schema({
question: {
type: String,
required: true,
},
answer: {
type: String,
required: true,
},
deck: {
type: String,
required: true,
},
tags: [String],
createdAt: {
type: Date,
default: Date.now,
},
})
export default mongoose.models.Flashcard || mongoose.model('Flashcard', flashcardSchema)
```
API Route'ları
Next.js API route'ları backend mantığımızı yönetir. `pages/api/flashcards/index.js` oluşturun:
```javascript
import dbConnect from '../../../lib/dbConnect'
import Flashcard from '../../../models/Flashcard'
export default async function handler(req, res) {
const { method } = req
await dbConnect()
switch (method) {
case 'GET':
try {
const flashcards = await Flashcard.find({})
res.status(200).json(flashcards)
} catch (error) {
res.status(400).json({ success: false })
}
break
case 'POST':
try {
const flashcard = await Flashcard.create(req.body)
res.status(201).json(flashcard)
} catch (error) {
res.status(400).json({ success: false })
}
break
default:
res.status(400).json({ success: false })
break
}
}
```
Frontend Bileşenleri
Form bileşeni `components/FlashcardForm.js`:
```javascript
import { useState } from 'react'
export default function FlashcardForm({ onSubmit }) {
const [question, setQuestion] = useState('')
const [answer, setAnswer] = useState('')
const [deck, setDeck] = useState('')
const handleSubmit = async (e) => {
e.preventDefault()
const response = await fetch('/api/flashcards', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ question, answer, deck })
})
if (response.ok) {
const newFlashcard = await response.json()
onSubmit(newFlashcard)
setQuestion('')
setAnswer('')
setDeck('')
}
}
return (
)
}
```
Çalışma Arayüzü (Study Mode)
Aktif hatırlama pratiği için `components/StudyMode.js`:
```javascript
import { useState, useEffect } from 'react'
export default function StudyMode({ flashcards }) {
const [currentIndex, setCurrentIndex] = useState(0)
const [showAnswer, setShowAnswer] = useState(false)
const [shuffledCards, setShuffledCards] = useState([])
useEffect(() => {
setShuffledCards([...flashcards].sort(() => Math.random() - 0.5))
}, [flashcards])
const nextCard = () => {
setShowAnswer(false)
if (currentIndex < shuffledCards.length - 1) {
setCurrentIndex(currentIndex + 1)
}
}
const prevCard = () => {
setShowAnswer(false)
if (currentIndex > 0) {
setCurrentIndex(currentIndex - 1)
}
}
if (!shuffledCards.length) return
Kullanılabilir flashcard yok
const card = shuffledCards[currentIndex]
return (
Soru:
{card.question}
{showAnswer && (
Cevap:
{card.answer}
)}
onClick={() => setShowAnswer(!showAnswer)}
className="bg-gray-500 text-white px-4 py-2 rounded"
>
{showAnswer ? 'Cevabı Gizle' : 'Cevabı Göster'}
{currentIndex > 0 && (
)}
{currentIndex < shuffledCards.length - 1 && (
)}
{currentIndex + 1} / {shuffledCards.length}
)
}
```
Ana Uygulama Sayfası
`app/page.js` oluşturun:
```javascript
import { useState, useEffect } from 'react'
import FlashcardForm from '../components/FlashcardForm'
import StudyMode from '../components/StudyMode'
export default function Home() {
const [flashcards, setFlashcards] = useState([])
const [activeView, setActiveView] = useState('create')
const [selectedDeck, setSelectedDeck] = useState('')
useEffect(() => {
fetchFlashcards()
}, [])
const fetchFlashcards = async () => {
const response = await fetch('/api/flashcards')
const data = await response.json()
setFlashcards(data)
}
const addFlashcard = (newFlashcard) => {
setFlashcards([newFlashcard, ...flashcards])
}
const filteredCards = selectedDeck
? flashcards.filter(card => card.deck === selectedDeck)
: flashcards
const decks = [...new Set(flashcards.map(card => card.deck))]
return (
Flashcard Çalışma Uygulaması
onClick={() => setActiveView('create')}
className={`px-4 py-2 mr-2 rounded ${
activeView === 'create' ? 'bg-blue-500 text-white' : 'bg-white'
}`}
>
Flashcard Oluştur
onClick={() => setActiveView('study')}
className={`px-4 py-2 rounded ${
activeView === 'study' ? 'bg-blue-500 text-white' : 'bg-white'
}`}
disabled={flashcards.length === 0}
>
Çalışma Modu
{activeView === 'create' && (
)}
{activeView === 'study' && (
value={selectedDeck}
onChange={(e) => setSelectedDeck(e.target.value)}
className="w-full p-2 border rounded"
>
{decks.map(deck => (
))}
)}
{activeView === 'study' &&
Dükkanlarınız
{decks.length === 0 ? (
Henüz dükkan yok. Yukarıdan ilk flashcard'ınızı oluşturun!
) : (
{deck} ({flashcards.filter(c => c.deck === deck).length} kart)
{decks.map(deck => (
))}
)}
)
}
```
Deployment İçin Düşünülmesi Gerekenler
Production ortamı için şu geliştirmeleri düşünebilirsiniz:
1. **Kimlik Doğrulama**: NextAuth.js ile kullanıcı hesapları ekleyin
2. **Aralıklı Tekrar (Spaced Repetition)**: SM-2 gibi algoritmaları implement edin
3. **Zengin Medya**: Flashcard'lara görsel ve ses desteği ekleyin
4. **Çevrimdışı Destek**: PWA yetenekleri için service worker kullanın
Vercel'e (Next.js için optimize edilmiş) veya benzer platformlara deploy edin. MongoDB Atlas kümesi kurun ve environment variable'ları yapılandırın.
Sonuç
Bu flashcard uygulaması, temel kavramları gösterirken aynı zamanda pratik bir çözüm sunar. Artık ihtiyaçlarınıza göre genişletilebilecek bir temelınız var. Dil öğreniyor olun, sınava hazırlanıyor olun ya da profesyonel materyal ezberliyor olun — dijital flashcard'lar etkili ve özelleştirilebilir bir çözüm sağlar.
Basitten başlayın, sık sık iyileştirin ve temel kullanıcı deneyimine odaklanın. Öğrenme yolculuğunuzda başarılar dilerim!
SSS
S: MongoDB deneyimine ihtiyacım var mı?
C: Temel bilgi yardımcı olur ama zorunlu değil. JSON yapısını anladığınızda MongoDB'nin belge modeli çok sezgisel hale geliyor.
S: Flashcard'lara resim ekleyebilir miyim?
C: Tabii! Şemayı resim URL'leriyle genişletin ve form bileşenlerini dosya yüklemeyi destekleyecek şekilde değiştirin.
S: Aralıklı tekrar (spaced repetition) nasıl implement edilir?
C: Zaman damgalı tekrar geçmişi saklayın, sonra hatırlama performansına göre optimal aralıkları hesaplayın. `supermemo` gibi kütüphaneler algoritmalar konusunda yardımcı olabilir.
S: Bu mobil cihazlar için uygun mu?
C: Tailwind gibi responsive CSS framework'leriyle evet. Yerel uygulamalara yakın deneyim için PWA özellikleri eklemeyi düşünün.
Yorumlar (0)
Henüz yorum yapılmamış. İlk yorumu siz yapın!
Yorum Yap