A personalized digital scrapbook/portfolio inspired by sharyap.com, built with Next.js, React, Tailwind CSS, and Howler.js. Use it to practice design, animations, and web development while learning how each part works.
npm install
npm run devOpen http://localhost:3000.
src/app/layout.tsx— Root layout. Wraps every page; fonts and global providers (theme, sound) live here.src/app/page.tsx— Home page. A Client Component ("use client") because it usesuseStatefor the open modal.src/app/globals.css— Global styles and Tailwind. CSS variables here drive light/dark theme colors.
Learning: In the App Router, layout.tsx is shared across routes and doesn’t re-mount on navigation. Use it for headers, providers, and fonts.
- State:
page.tsxholdsopenSection(which modal is open) andtoastDismissed. Child components receive callbacks likeonOpenSectionandonDismiss. - Context:
ThemeProviderandSoundProviderusecreateContext+useContextso any component can read theme/sound and trigger toggles without passing props through every level.
Learning: Lift state to the lowest common parent that needs it. Use Context for “global” settings (theme, sound).
tailwind.config.ts— Custom colors (scrapbook.cream,scrapbook.ink, etc.), fonts, and keyframes (fade-in,slide-up,wiggle).darkMode: "class"means dark styles apply when<html>has the classdark.- Utility classes: Components use Tailwind for layout (
flex,gap), spacing (p-4,mt-2), and responsive design (md:text-5xl). Dark variants use thedark:prefix.
Learning: Put design tokens (colors, animations) in tailwind.config.ts. Use dark: for dark-mode styles.
SoundProvider.tsx— Wraps the app and exposessfxEnabled,toggleSfx, andplayClick(). When SFX is on,playClick()lazy-loads Howler and plays a click sound.- Adding sounds: Put an audio file (e.g.
click.mp3) inpublic/sounds/. The provider already points to/sounds/click.mp3. If the file is missing, the app still works (errors are handled).
Learning: Howler’s new Howl({ src: ['/sounds/click.mp3'], volume: 0.3 }) and .play() are enough for simple SFX. Lazy-load with import('howler') so the library only loads when needed.
| File | Role |
|---|---|
Header.tsx |
Top bar with dark mode and SFX toggles; uses useTheme() and useSound(). |
Hero.tsx |
Intro text with staggered CSS animations (animate-fade-in, animate-slide-up). |
SectionButtons.tsx |
Buttons for about, links, work, faq, contact, downloads; toggles modal. |
Modal.tsx |
Overlay + panel; Escape and backdrop click close it; locks body scroll when open. |
sections/*.tsx |
Content for each modal. Replace with your own copy and links. |
Footer.tsx |
Bottom bar. |
DesktopToast.tsx |
“Best on desktop” notice; dismissible once. |
ScrapbookSticker.tsx |
Small hover animation (Tailwind animate-wiggle) for practice. |
- CSS (Tailwind): Keyframes in
tailwind.config.ts→animation: { "fade-in": "fade-in 0.4s ease-out forwards" }→ useanimate-fade-inin JSX. Delay withstyle={{ animationDelay: '100ms' }}. - Hover:
hover:scale-105,hover:animate-wiggleon buttons and the sticker.
Learning: Start with Tailwind keyframes and utility classes. Later you can add Framer Motion or CSS @keyframes in globals.css for more complex animations.
- Copy: Edit
Hero.tsxand the section components insrc/components/sections/with your name, bio, links, and projects. - Colors/fonts: Change
scrapbook.*colors and font variables intailwind.config.tsandlayout.tsx. - Sounds: Add
public/sounds/click.mp3(and others) and optionally add moreHowlinstances inSoundProvider.tsxfor different actions.
npm run dev— Dev server with hot reload.npm run build— Production build.npm run start— Run production build locally.npm run lint— Run ESLint.
Enjoy building and learning.