Design-First. Performance-Obsessed. Detail-Perfect.
# Install dependencies
npm install
# Set up environment variables (see below)
cp .env.example .env
# Run development server
npm run dev
# Build for production
npm run build
# Start production server
npm startBefore deployment, you need to set up these free services:
- Go to sanity.io
- Create a free account
- Create a new project
- Note your Project ID and Dataset (usually "production")
- Generate an API token with Editor permissions
- Go to resend.com
- Sign up for free tier
- Verify your domain OR use their test domain for development
- Generate an API key
- Already set up β
- Blob storage token will be auto-generated on deployment
- Go to google.com/recaptcha
- Create a new site (reCAPTCHA v3)
- Add your domain: manecharo.com
- Note your Site Key and Secret Key
Create a .env file in the root directory:
# Sanity CMS
NEXT_PUBLIC_SANITY_PROJECT_ID=your_project_id_here
NEXT_PUBLIC_SANITY_DATASET=production
SANITY_API_TOKEN=your_token_here
# NextAuth (Authentication)
NEXTAUTH_URL=https://manecharo.com
NEXTAUTH_SECRET=generate_with_command_below
ADMIN_PASSWORD_HASH=see_below_for_hash
# Resend (Email)
RESEND_API_KEY=re_your_api_key_here
RESEND_FROM_EMAIL=noreply@manecharo.com
# Vercel Blob (auto-populated on Vercel)
BLOB_READ_WRITE_TOKEN=
# Analytics (auto-populated on Vercel)
NEXT_PUBLIC_VERCEL_ANALYTICS_ID=auto
# Google reCAPTCHA v3
NEXT_PUBLIC_RECAPTCHA_SITE_KEY=your_site_key_here
RECAPTCHA_SECRET_KEY=your_secret_key_hereopenssl rand -base64 32Your password is: Letmeupdateyou2005
Run this Node script to generate the hash:
node -e "const bcrypt = require('bcryptjs'); bcrypt.hash('Letmeupdateyou2005', 10, (err, hash) => console.log(hash));"Copy the output to ADMIN_PASSWORD_HASH in your .env file.
npm install -g @sanity/cli# In your project root
cd sanity
npm installimport { defineConfig } from 'sanity'
import { deskTool } from 'sanity/desk'
import { visionTool } from '@sanity/vision'
import { schemaTypes } from './src/lib/sanity/schemas'
export default defineConfig({
name: 'default',
title: 'Manecharo Portfolio',
projectId: process.env.NEXT_PUBLIC_SANITY_PROJECT_ID || '',
dataset: process.env.NEXT_PUBLIC_SANITY_DATASET || 'production',
plugins: [deskTool(), visionTool()],
schema: {
types: schemaTypes,
},
})sanity deployChoose a subdomain (e.g., manecharo-portfolio)
Your studio will be at: https://manecharo-portfolio.sanity.studio
Website/
βββ src/
β βββ app/ # Next.js App Router
β β βββ (pages)/
β β β βββ page.tsx # Landing page
β β β βββ work/ # Projects
β β β βββ about/ # About page
β β β βββ capabilities/ # Capabilities page
β β β βββ contact/ # Contact page
β β β βββ thoughts/ # Blog (brutalist)
β β βββ update/ # Admin panel
β β βββ api/ # API routes
β β βββ layout.tsx # Root layout
β β βββ globals.css # Global styles
β βββ components/
β β βββ layout/ # Navigation, Footer, etc.
β β βββ sections/ # Page sections
β β βββ ui/ # Reusable components
β βββ lib/
β βββ sanity/ # Sanity client & schemas
βββ public/
β βββ videos/ # Hero videos
β βββ images/ # Static images
βββ package.json
βββ tailwind.config.ts
βββ next.config.mjs
Upload these to /public/videos/:
-
hero-bg.mp4 (Desktop)
- Resolution: 1920x1080
- Length: 10-20 seconds (seamless loop)
- Size: <5MB
- Format: MP4 (H.264)
-
hero-bg-mobile.mp4 (Mobile)
- Resolution: 1080x1920 (portrait)
- Same length as desktop
- Size: <3MB
- Format: MP4 (H.264)
-
hero-poster.jpg (Fallback)
- Resolution: 1920x1080
- First frame of video
- Format: JPG
Upload these to /public/images/:
-
portrait.jpg (About page)
- Resolution: 1200x1600 (portrait)
- High quality headshot
-
blog-default-1.jpg through blog-default-5.jpg
- Resolution: 1200x630
- Black/white/red geometric patterns
- For blog posts without custom images
-
og-image.png (Social sharing)
- Resolution: 1200x630
- Your name + branding
-
Favicons
- favicon.ico (32x32)
- apple-touch-icon.png (180x180)
- icon-192.png, icon-512.png
- Go to
https://your-project-id.sanity.studio - Login with your Sanity account
- Add projects, blog posts, and page content
Create /CONTENT.md with this structure:
## LANDING PAGE
Tagline: Your custom tagline here
Stats: Your stats text here
## ABOUT PAGE
Short Version: [Your biography]
Education: [Your education details]
## PROJECTS
### Project Name
Year: 2024
Role: Lead Designer
Challenge: [Description]
What I Did: [Description]
Results:
β Result 1
β Result 2
Tags: product-design, ux-ui-design
[Repeat for other projects]Then manually add to Sanity Studio.
- Push to GitHub (if not done)
git init
git add .
git commit -m "Initial commit"
git remote add origin https://github.com/Manecharo/Manecharo.git
git push -u origin main- Import to Vercel
- Go to vercel.com/new
- Import your GitHub repository
- Add all environment variables (from
.env) - Deploy
- Configure Domain
- Go to Project Settings β Domains
- Add
manecharo.com - Follow DNS configuration instructions
Every push to main auto-deploys to production. That's it!
- URL:
https://manecharo.com/update - Password:
Letmeupdateyou2005
- Manage projects via Sanity Studio
- Manage blog posts via Sanity Studio
- Edit page content via Sanity Studio
Note: All content management happens in Sanity Studio for the best editing experience.
- Unique directional page transitions
- Pages slide in from the direction of the menu clicked
- Buttery smooth 600ms animations
- Full-screen autoplay video
- Separate mobile/desktop versions
- Graceful fallback to poster image
- Completely different design language
- Easter egg access: Click footer logo 3x rapidly
- Supports writing, video, and audio posts
- Tag-based filtering system
- Masonry grid layout
- Smooth animations
- Password-protected via NextAuth
- All content managed through Sanity Studio
- Secure and easy to use
rm -rf node_modules package-lock.json
npm install- Check
NEXT_PUBLIC_SANITY_PROJECT_IDis correct - Verify images are uploaded in Sanity Studio
- Ensure CORS is configured in Sanity (sanity.io/manage)
- Verify
ADMIN_PASSWORD_HASHis correctly generated - Check
NEXTAUTH_SECRETis set - Ensure
NEXTAUTH_URLmatches your domain
- Verify
RESEND_API_KEYis valid - Check domain is verified in Resend
- Look at Vercel function logs for errors
Target Lighthouse scores:
- Performance: 90+
- Accessibility: 95+
- Best Practices: 95+
- SEO: 100
Optimizations included:
- Next.js Image component for all images
- Lazy loading below the fold
- Code splitting
- WebP format with JPEG fallback
- Preloaded fonts
- ISR (Incremental Static Regeneration)
- Go to Sanity Studio
- Click "Project" β "Create"
- Fill in all fields
- Upload images (1-5)
- Publish
Changes appear within 1 hour (ISR revalidation).
Same process in Sanity Studio under "Post".
Same process in Sanity Studio under "Page Content".
For technical issues:
- Check this README
- Review Next.js docs
- Review Sanity docs
- Check Vercel deployment logs
Β© 2024 Manuel Echavarria Romero. All rights reserved.
Built with Next.js 14, TypeScript, Tailwind CSS, Sanity.io, and β€οΈ
