diff --git a/public/presentation/kids-screenshot.png b/public/presentation/kids-screenshot.png new file mode 100644 index 00000000..226f485a Binary files /dev/null and b/public/presentation/kids-screenshot.png differ diff --git a/src/app/presentation/notes/page.tsx b/src/app/presentation/notes/page.tsx new file mode 100644 index 00000000..e65d9774 --- /dev/null +++ b/src/app/presentation/notes/page.tsx @@ -0,0 +1,141 @@ +"use client"; + +import { useCallback, useEffect, useRef, useState } from "react"; +import { ChevronLeft, ChevronRight, RadioTower, WifiOff } from "lucide-react"; + +type DeckState = { + currentSlide: number; + totalSlides: number; + notes: string[]; +}; + +export default function PresenterNotesPage() { + const channelRef = useRef(null); + const [state, setState] = useState(null); + const [connected, setConnected] = useState(false); + + const send = useCallback((message: Record) => { + channelRef.current?.postMessage(message); + }, []); + + useEffect(() => { + if (typeof window === "undefined" || typeof BroadcastChannel === "undefined") return; + + const channel = new BroadcastChannel("prompts-presentation"); + channelRef.current = channel; + + channel.onmessage = (event) => { + const data = event.data; + if (data?.type === "state") { + setConnected(true); + setState({ + currentSlide: data.currentSlide ?? 0, + totalSlides: data.totalSlides ?? 0, + notes: Array.isArray(data.notes) ? data.notes : [], + }); + } + }; + + channel.postMessage({ type: "request" }); + const retry = setInterval(() => { + if (!channelRef.current) return; + channelRef.current.postMessage({ type: "request" }); + }, 1000); + + return () => { + clearInterval(retry); + channel.close(); + channelRef.current = null; + }; + }, []); + + useEffect(() => { + const handleKeyDown = (event: KeyboardEvent) => { + if (event.key === "ArrowRight" || event.key === " " || event.key === "PageDown") { + event.preventDefault(); + send({ type: "next" }); + } else if (event.key === "ArrowLeft" || event.key === "PageUp") { + event.preventDefault(); + send({ type: "prev" }); + } + }; + + window.addEventListener("keydown", handleKeyDown); + return () => window.removeEventListener("keydown", handleKeyDown); + }, [send]); + + const current = state?.currentSlide ?? 0; + const total = state?.totalSlides ?? 0; + const notes = state?.notes ?? []; + const currentNote = notes[current]; + const nextNote = notes[current + 1]; + const atStart = current <= 0; + const atEnd = total > 0 && current >= total - 1; + + return ( +
+
+
+ Presenter notes + + {connected ? : } + {connected ? "Synced" : "Waiting for deck…"} + +
+
+ {total > 0 ? `Slide ${current + 1} / ${total}` : "—"} +
+
+ +
+
+
Now
+
+ {connected ? ( +

+ {currentNote || "No note for this slide."} +

+ ) : ( +

+ Open the presentation in another window and this view will sync automatically. +

+ )} +
+
+ +
+
Next
+

+ {atEnd ? "End of deck." : nextNote || "—"} +

+
+
+ +
+ + + {total > 0 ? `${current + 1} / ${total}` : "—"} + + +
+
+ ); +} diff --git a/src/app/presentation/page.tsx b/src/app/presentation/page.tsx index 2bd94827..347e572b 100644 --- a/src/app/presentation/page.tsx +++ b/src/app/presentation/page.tsx @@ -1,29 +1,24 @@ import { - Blocks, + ArrowRight, Bot, - BrainCircuit, - CheckCircle2, - CircleDotDashed, - ClipboardCheck, - Clock3, - DatabaseZap, - FileText, - Filter, + BookOpen, + Boxes, + Code2, GitBranch, + Gamepad2, + Globe, Layers3, - Lightbulb, + Lock, MessageSquareText, Network, PackageCheck, - Puzzle, - RefreshCw, - Route, - Scissors, + Rocket, + Search, + Share2, ShieldCheck, Sparkles, - Target, - TimerReset, - WandSparkles, + Star, + Workflow, } from "lucide-react"; import type { LucideIcon } from "lucide-react"; import Image from "next/image"; @@ -31,31 +26,24 @@ import type { ReactNode } from "react"; import { SlideContent, SlideDeck, SlideHighlight, SlideTitle } from "@/components/presentation/SlideDeck"; export const metadata = { - title: "Prompt Tasarımı ve Context Yönetimi | Presentation", - description: "30 dakikalık Türkçe konuşma: prompt tasarımı, context yönetimi ve prompts.chat.", + title: "prompts.chat: An Open Prompt Ecosystem for the Age of Agents | Microsoft Build", + description: + "15-minute lightning talk at Microsoft Build: how prompts.chat grew from a GitHub repo into an open prompt ecosystem — platform, book, and game — for the age of agents.", }; const speakerNotes = [ - "Açılışta sunumun amacını netleştir: Bu konuşma prompt ezberlemek değil, bağlamı bilinçli yönetmek üzerine. 30 dakika sonunda herkesin kendi işine uygulayabileceği bir kontrol listesi olacak.", - "Konuşmacı slaytı kısa tutulmalı. Kişisel hikaye: Awesome ChatGPT Prompts ile başlayan topluluk deneyimi, prompts.chat ile promptların paylaşılabilir, sürümlenebilir ve geliştirilebilir varlıklara dönüşmesi.", - "Akışı anlat: önce zihinsel model, sonra promptun anatomisi, sonra context yönetimi ve ölçüm. prompts.chat bölümünü ürün demosu gibi değil, bu prensiplerin pratik karşılığı olarak konumlandır.", - "Ana mesaj: Modeli sadece cevap makinesi gibi değil, sınırlı dikkat alanına sahip bir ekip arkadaşı gibi düşünün. Prompt tasarımı görevi tanımlar; context yönetimi modelin neye bakacağını seçer.", - "Prompt tasarımının yalnızca güzel cümle yazmak olmadığını vurgula. Rol, hedef, veri, sınır, örnek ve çıktı sözleşmesi bir araya geldiğinde modelin çalışma alanı oluşur.", - "Bu slaytta kötü prompt / iyi prompt farkını canlı okuyarak göster. İyi örneğin daha uzun olduğu için değil, karar yükünü azalttığı için iyi olduğunu söyle.", - "Context penceresini dosya dolabı değil, toplantı masası metaforu ile anlat. Masaya her şeyi koymak odak kaybettirir; doğru şeyleri doğru sırayla koymak performansı artırır.", - "Bağlam katmanlarını sırayla açıkla. Sistem ve geliştirici talimatlarının politikayı, kullanıcı mesajının amacı, araç sonuçlarının kanıtı, geçmişin ise sürekliliği taşıdığını anlat.", - "Önemli ayrım: Context çokluğu kalite demek değildir. Gürültü, eski kararlar ve çelişkili talimatlar modeli kararsızlaştırır. Context tasarrufu aynı zamanda kalite kontrolüdür.", - "Kısa bir teknik çerçeve ver: seç, sırala, sıkıştır, doğrula. Bu dört fiil context yönetiminin günlük pratiği olabilir.", - "Örnekler model davranışını güçlü biçimde kilitler. Ancak yanlış örnekler de yanlış davranışı kilitler. Örnekleri az ama temsil gücü yüksek seçmek gerektiğini vurgula.", - "Çıktı sözleşmesi özellikle ekiplerde önemlidir. JSON, tablo, diff, adım adım plan gibi formatlar otomasyon ve tekrar üretilebilirlik sağlar.", - "Araç kullanan ajanlarda prompt, sadece cevap formatını değil yetki sınırını da belirler. Ne zaman arama yapmalı, ne zaman sormalı, ne zaman durmalı gibi kararları açık yazın.", - "Context yönetiminin operasyonel tarafı: uzun konuşmalarda özet, dosya tabanlı işlerde ilgili parçalar, arama tabanlı işlerde kaynak ve alıntı. Her şeyi tek mesaja doldurmak yerine akış tasarla.", - "Hata modlarını örneklerle anlat: belirsiz hedef, eski bağlam, çelişki, görünmez varsayım, format eksikliği. Bunlar model hatası gibi görünür ama çoğu zaman tasarım hatasıdır.", - "Ölçüm slaytında küçük bir test setinin değerini anlat. Aynı promptu birkaç gerçek senaryo ile denemek, tek seferlik iyi cevaptan daha güvenilirdir.", - "prompts.chat'i bağlamla ilişkilendir: iyi promptlar tek kişide kalmamalı. Paylaşım, sürümleme ve geri bildirim prompt kalitesini artırır.", - "Ekip pratiğine geç: promptlar kod gibi yaşamalı. Sahiplik, değişiklik geçmişi, review ve örnek çıktılar promptun güvenilirliğini artırır.", - "Kapanış kontrol listesini yavaş oku. Dinleyicilerin kendi promptlarını bu beş soruyla gözden geçirmesini iste.", - "Son slaytta tek cümlelik kapanış: İyi prompt, modele ne yapacağını söyler; iyi context yönetimi, neye dayanarak yapacağını belirler.", + "Okay, hi everyone. So I want to start with a mistake that, honestly, a lot of people make. They think that when AI models get smarter, prompts will not matter anymore — like, prompting is just a temporary trick and the next model will make it useless. But actually, for me, it's the opposite. Even the best models give you better answers when you give them better prompts. And in the age of agents, prompts are kind of like atoms — every agent is basically made of them. So no, prompts are not going away. They actually matter more than before. So in the next fifteen minutes, I want to show you why, and the open ecosystem I'm building around them: prompts.chat.", + "But first, a quick hello. I'm Fatih. I'm a developer advocate on the WordPress team at Automattic. I also created the Awesome ChatGPT Prompts project, and I'm a GitHub Star. Okay, that's enough about me — let's actually talk about prompts.", + "So, this whole thing actually started as a tiny GitHub repo. Just a simple list of prompts you could copy and paste. And one detail people are always surprised by — this is not new at all. I created it almost four years ago, literally about one week after OpenAI announced ChatGPT. The book came later. Honestly, back then I didn't expect much. But it kind of exploded — it became one of the most starred AI projects on GitHub, used by tens of millions of people. And that told me something: a good prompt is actually worth sharing.", + "But here's the problem, right? Most prompts just get lost. They're hidden in screenshots, random gists, old chat history. No version, no owner, no review. That great prompt you wrote last week? It's probably gone the second you closed the tab. And okay, that's annoying for us as people — but honestly, it completely falls apart once agents are involved.", + "So why does it fall apart for agents? Well, when an agent acts for you, the prompt is not just a casual message anymore. It's actually the plan. It's the contract. It's basically the source code for how that agent behaves. Look at this one — a role, a goal, the sources it can use, the limits, and when to stop. You really want to save and improve something like this, right? Not lose it somewhere in a chat.", + "So this is exactly what prompts.chat does. It treats prompts as real, shareable things. You can discover good ones, fork them, keep versions, reuse them. And it's open source, so you can even host it yourself — your team actually owns its own prompt library.", + "Now, why does being open matter so much, especially for agents? I'd say three reasons. First, you can actually read what the agent was told to do. Second, the same prompt works across different models and tools. And third, open prompts plug right into agents, editors, an MCP layer. So basically, a world full of agents needs an open world of prompts.", + "Okay, now two things people don't really expect. The first one is a book. It's called The Interactive Book of Prompting. It's free, and it's not some boring PDF — it's actually interactive, with live demos you can try right there on the page, from the basics all the way to agents.", + "And the second one is a game. So, this is Promi — a little robot — on an adventure through Prompt Land. It's a fun way for kids to learn how to talk to AI. Because, honestly, this skill shouldn't only be for engineers, right? It kind of belongs to everyone, including the next generation.", + "So if you put it all together, you actually get one open loop. The repo where it all began, the platform to discover and reuse, the book to learn, the game to bring in new people, and an API and MCP layer that feeds everything back to both humans and agents. So good prompts come in, the community makes them better, and they go back out.", + "Okay, so here's the big picture. As agents start doing real work, the prompt is how we steer them — it's becoming the interface to these systems. Now, around those prompts you need some tooling — a way to manage them, version them, test them, serve them. And a lot of people now call this the \"harness\". So, just to be clear, the harness is not the prompt itself — it's actually the tooling that keeps your prompts accurate and well-tuned. And honestly, the same model can give you very different results depending on how good that harness is. So let's keep this whole thing open, shared, and easy to improve — together.", + "And that's pretty much it. So, come build this open prompt ecosystem with us. Check out prompts.chat, read the book, play the game with your kids, and take a look at the project on GitHub. Thank you so much — and I think we have a moment for maybe one question.", ]; type CardProps = { @@ -113,45 +101,39 @@ function FlowStep({ icon: Icon, title, text }: { icon: LucideIcon; title: string ); } -function ContextLayer({ label, description, tone }: { label: string; description: string; tone: string }) { - return ( -
-
-
-

{label}

-

{description}

-
-
- ); -} - -function MiniChecklist({ items }: { items: string[] }) { - return ( -
- {items.map((item) => ( -
- - {item} -
- ))} -
- ); -} - export default function PresentationPage() { return (
-
- +
+ prompts.chat logo + prompts.chat logo
- Prompt Tasarımı ve Context Yönetimi - - 30 dakikalık pratik bir çerçeve: daha iyi talimat, daha temiz bağlam, daha güvenilir AI çıktısı. + prompts.chat + + Building an Open Prompt Ecosystem for the Age of Agents +

+ Smarter models don't make prompts obsolete — prompts are the{" "} + atoms of every agent. +

- prompts.chat/presentation - Ok tuşları, boşluk, F, N + Microsoft Build + 15-min lightning talk
@@ -163,7 +145,7 @@ export default function PresentationPage() {
Fatih Kadir Akın profil fotoğrafı
-

Konuşmacı

Fatih Kadir Akın

- WordPress Developer Advocate, Automattic - Creator of prompts.chat + Developer Advocate, WordPress @ Automattic +
Creator of prompts.chat +
GitHub Star

- Merhaba, ben Fatih. + Hi, I'm Fatih. - Geliştiricilerin hayatını kolaylaştıran uygulamalar geliştiriyorum; bunlardan biri de{" "} + I build tools that make developers' lives easier — one of them is{" "} prompts.chat.
-
- WordPress - WordPress -
Automattic
+
+ + GitHub Star +
-
- Bugünkü rota -
- - - - +
+
+ It started as a GitHub repo + + Awesome ChatGPT Prompts — a simple list of copy-paste prompts that grew + into one of the most-starred AI repositories in the world. + +

+ And it's not new — the repo (and later the book) are almost{" "} + four years old, born just a week after OpenAI announced ChatGPT. +

+
+
+ + One of GitHub's most popular AI projects. + + + People copied these prompts into every AI tool imaginable. + + + The prompt itself became something worth sharing. +
- AI ile çalışmak: çok zeki ama bağlama bağımlı bir ekip arkadaşı + But prompts get lost
- - Modelin optimizasyon hedefi belirsizse cevap da belirsizleşir. + + Trapped in screenshots, gists, and DMs. - - Ne yapılmayacağı, ne yapılacağı kadar önemlidir. + + No history, no review, no ownership. - - Model en son ve en belirgin bağlama fazla ağırlık verir. + + The good ones disappear when the tab closes.
- İyi prompt ne yapılacağını, iyi context yönetimi ise{" "} - neye dayanarak yapılacağını belirler. + Annoying for humans — and broken for agents.
- Prompt tasarımı cümle süslemek değildir + In the age of agents, a prompt is a spec - Prompt, modelle aranızdaki çalışma sözleşmesidir. - Cevabın amacı, kapsamı, kaynakları, formatı ve kalite barı bu sözleşmede yer alır. + When an agent acts on your behalf, the prompt stops being a casual message. It becomes the{" "} + contract — the source code of behavior.
-
- {[ - ["Rol", "Hangi perspektiften düşünecek?"], - ["Görev", "Tam olarak neyi üretecek?"], - ["Bağlam", "Hangi bilgiye dayanacak?"], - ["Kısıt", "Neyi yapmayacak veya aşmayacak?"], - ["Çıktı", "Nasıl teslim edecek?"], - ].map(([label, text]) => ( -
-
{label[0]}
-
-

{label}

-

{text}

-
-
- ))} -
-
- -
-
- Kötü prompt / iyi prompt - - Uzun olan değil, karar yükünü azaltan prompt daha iyidir. - -
-
- - {`Bana context management hakkında iyi bir yazı yaz.`} - - - {`Rol: Kıdemli AI ürün danışmanı. -Amaç: Teknik olmayan ürün ekibine context management anlat. -Bağlam: 30 dakikalık şirket içi eğitim. -Kısıt: Jargon kullanma, 3 örnek ver, riskleri belirt. -Çıktı: Başlık, 5 maddelik özet, uygulanabilir kontrol listesi.`} - -
-
- -
- Context penceresi dosya dolabı değil, toplantı masasıdır - - Masaya her şeyi koyarsanız ekip odaklanamaz. Doğru belgeleri, doğru sırayla, doğru ayrıntı seviyesinde getirirsiniz. - -
- - - - -
-
- -
-
- Bağlam katmanları - - Model tek bir metni değil, üst üste binmiş talimat ve kanıt katmanlarını yorumlar. - -
-
- - - - - -
-
- -
- Daha fazla context her zaman daha iyi değildir -
- - Alakasız detaylar, önemli sinyali gömer. - - - Geçmişte doğru olan bilgi bugün yanlış olabilir. - - - Model hangi talimata uyacağını tahmin etmek zorunda kalır. - -
- - Context yönetimi, token tasarrufu değil; dikkat yönetimidir. - -
- -
- Pratik yöntem: seç, sırala, sıkıştır, doğrula -
- - - - -
-
- -
-
- Örnekler davranışı kilitler - - Few-shot örnekler modele sadece formatı değil, neyi iyi saydığınızı gösterir. - -
-
-
- -

Örnek seçerken

-
- -
-
- -
-
- Çıktı sözleşmesi otomasyonun kapısıdır - - İnsan okuyacaksa okunabilirlik, sistem okuyacaksa şema önemlidir. - -
- - {`{ - "summary": "en fazla 3 cümle", - "risks": ["kanıta dayalı risk listesi"], - "next_actions": [ - { "owner": "rol", "task": "yapılacak iş", "priority": "P0 | P1 | P2" } - ], - "confidence": "low | medium | high" -}`} + + {`Role: Release notes agent for our repo. +Goal: Summarize merged PRs since the last tag. +Sources: GitHub API, CHANGELOG.md. +Limits: No breaking-change claims without a label. +Stop: When the draft is posted for review. +Output: Markdown, grouped by feature / fix / chore.`}
-
- Ajanlarda prompt = yetki ve durma kuralları -
- - Bilgi eksikse arama yap; tahminle doldurma. - - - Kapsam veya risk davranışı etkiliyorsa kullanıcıya dön. - - - Başarı kriteri tamamlandıysa yeni iş icat etme. - -
-
- -
-
- Uzun işlerde context akışı tasarla - - Tek dev prompt yerine, işi aşamalara böl: keşif, plan, uygulama, doğrulama, özet. - -
-
- {[ - { icon: Network, title: "Keşif", text: "Dosya, kaynak ve kısıtları topla." }, - { icon: Route, title: "Plan", text: "Kararları ve bağımlılıkları görünür yap." }, - { icon: Blocks, title: "Uygulama", text: "Sadece gerekli bağlamı sonraki adıma taşı." }, - { icon: ClipboardCheck, title: "Doğrulama", text: "Çıktıyı ölçüt ve kaynakla kontrol et." }, - ].map(({ icon: Icon, title, text }) => ( -
-
- -
-
-

{title}

-

{text}

-
-
- ))} -
-
- -
- En sık görülen hata modları -
- - - - -
-
- -
-
- Promptları ölç: tek iyi cevap yetmez - - Küçük bir test seti, promptun gerçek hayatta dayanıklı olup olmadığını gösterir. - -
-
- -
-
-
- prompts.chat: promptları paylaşılabilir hale getirmek + prompts.chat: an open prompt ecosystem - Promptlar kaybolan sohbet parçaları olmamalı. Keşfedilebilir, fork edilebilir, iyileştirilebilir ve tekrar kullanılabilir olmalı. + Prompts as first-class assets — discoverable, forkable, versioned, and + reusable. Open source and self-hostable.
-
- - İyi örneği arayıp bulmak, sıfırdan başlamaktan hızlıdır. +
+ + Find a proven prompt instead of starting from scratch. - - Promptlar review ve geri bildirimle olgunlaşır. + + Branch it, tweak it, make it yours. - - Aynı kaliteyi farklı ekip ve iş akışlarına taşırsınız. + + Prompts mature through review and feedback. + + + Carry quality across teams, tools, and agents.
- Promptlar kod gibi yaşamalı -
- - - - + Why open matters for agents +
+ + You can read exactly what the agent was told to do. + + + The same instruction travels across models and tools. + + + Open prompts plug into agents, IDEs, and an MCP layer. + +
+ + An ecosystem of agents needs an open ecosystem of prompts. + +
+ +
+
+ Learn it: The Interactive Book of Prompting + + A free, interactive prompt-engineering guide — with live, hands-on demos + instead of a static PDF. + +
+
+ + Hands-on chapters, from fundamentals to agents. +
+
+ + Runnable demos you can try right on the page. +
+
+
+ prompts.chat/book + Open & community-driven +
+
+
+
+
+ The Interactive Book of Prompting cover +
-
+
- Kapanış kontrol listesi + Play it: Promi in Prompt Land - Bir sonraki promptunuzu göndermeden önce bu beş soruyu sorun. + A game-based way for kids to learn how to talk to AI — because this + literacy belongs to everyone. +
+
+ + Join Promi the robot on an adventure through Prompt Land. +
+
+ + Kids practice asking AI for what they actually want. +
+
+
+ prompts.chat/kids + For the next generation +
- +
+
+
+ Promi in Prompt Land — the kids game +
+
+
+ +
+ One open loop +
+ + + + + +
+ + Prompts flow in, get refined by the community, and flow back out to{" "} + humans and agents. + +
+ +
+
+ +
+ Prompts are the new interface + + As agents take action, the prompt is how we steer them — and the tooling that manages those prompts is what + people now call the “harness”. + +

+ The harness isn't the prompt — it's what keeps your prompts accurate and well-tuned. So let's + keep it open, shared, and improvable. +

- +
- Teşekkürler + Thank you - İyi prompt modele ne yapacağını söyler. -
- İyi context yönetimi neye dayanarak yapacağını belirler. + Come build the open prompt ecosystem with us.
prompts.chat - Q&A + /book + /kids + github.com/f/prompts.chat +
+
+ Questions
diff --git a/src/components/presentation/SlideDeck.tsx b/src/components/presentation/SlideDeck.tsx index f1e58b00..cf0d8c45 100644 --- a/src/components/presentation/SlideDeck.tsx +++ b/src/components/presentation/SlideDeck.tsx @@ -1,7 +1,7 @@ "use client"; import { Children, ReactNode, useCallback, useEffect, useMemo, useRef, useState } from "react"; -import { ChevronLeft, ChevronRight, Maximize, Minimize, StickyNote, X } from "lucide-react"; +import { ChevronLeft, ChevronRight, Maximize, Minimize, MonitorPlay, StickyNote, X } from "lucide-react"; import Link from "next/link"; import { Button } from "@/components/ui/button"; import { cn } from "@/lib/utils"; @@ -18,6 +18,8 @@ export function SlideDeck({ children, notes }: SlideDeckProps) { const [showNotes, setShowNotes] = useState(false); const swipeStartX = useRef(null); const containerRef = useRef(null); + const channelRef = useRef(null); + const currentSlideRef = useRef(currentSlide); const totalSlides = slides.length; const currentNote = notes?.[currentSlide]; @@ -29,6 +31,60 @@ export function SlideDeck({ children, notes }: SlideDeckProps) { setCurrentSlide((prev) => Math.max(prev - 1, 0)); }, []); + const broadcastState = useCallback(() => { + channelRef.current?.postMessage({ + type: "state", + currentSlide: currentSlideRef.current, + totalSlides, + notes: notes ?? [], + }); + }, [notes, totalSlides]); + + const openPresenterView = useCallback(() => { + window.open( + "/presentation/notes", + "presentation-notes", + "width=960,height=720,menubar=no,toolbar=no,location=no,status=no" + ); + }, []); + + useEffect(() => { + if (typeof window === "undefined" || !notes || typeof BroadcastChannel === "undefined") return; + + const channel = new BroadcastChannel("prompts-presentation"); + channelRef.current = channel; + channel.onmessage = (event) => { + const data = event.data; + if (!data || typeof data !== "object") return; + switch (data.type) { + case "request": + broadcastState(); + break; + case "next": + nextSlide(); + break; + case "prev": + prevSlide(); + break; + case "goto": + if (typeof data.index === "number") { + setCurrentSlide(Math.max(0, Math.min(data.index, totalSlides - 1))); + } + break; + } + }; + + return () => { + channel.close(); + channelRef.current = null; + }; + }, [notes, totalSlides, nextSlide, prevSlide, broadcastState]); + + useEffect(() => { + currentSlideRef.current = currentSlide; + broadcastState(); + }, [currentSlide, broadcastState]); + const toggleFullscreen = useCallback(() => { if (document.fullscreenElement) { document.exitFullscreen(); @@ -67,12 +123,15 @@ export function SlideDeck({ children, notes }: SlideDeckProps) { } else if (event.key === "n" || event.key === "N") { event.preventDefault(); setShowNotes((value) => !value); + } else if (event.key === "p" || event.key === "P") { + event.preventDefault(); + openPresenterView(); } }; window.addEventListener("keydown", handleKeyDown); return () => window.removeEventListener("keydown", handleKeyDown); - }, [nextSlide, prevSlide, toggleFullscreen, totalSlides]); + }, [nextSlide, prevSlide, toggleFullscreen, totalSlides, openPresenterView]); return (
{notes && ( - + <> + + + )}
@@ -166,7 +237,7 @@ export function SlideDeck({ children, notes }: SlideDeckProps) { className="h-11 w-11 rounded-full bg-background/70 shadow-sm backdrop-blur hover:bg-background/90" > - Önceki + Previous
@@ -178,7 +249,7 @@ export function SlideDeck({ children, notes }: SlideDeckProps) { "h-2.5 rounded-full transition-all duration-300", index === currentSlide ? "w-8 bg-primary" : "w-2.5 bg-muted-foreground/30 hover:bg-muted-foreground/50" )} - aria-label={`${index + 1}. slayta git`} + aria-label={`Go to slide ${index + 1}`} /> ))}
@@ -191,14 +262,14 @@ export function SlideDeck({ children, notes }: SlideDeckProps) { className="h-11 w-11 rounded-full bg-background/70 shadow-sm backdrop-blur hover:bg-background/90" > - Sonraki + Next
{showNotes && (
-
Konuşmacı notu
-

{currentNote || "Bu slayt için not yok."}

+
Speaker note
+

{currentNote || "No note for this slide."}

)}