Building DATASTAR: From Concept to Deployment
A comprehensive tutorial on creating a professional portfolio website using Next.js, Tailwind CSS, MDX, and GitHub Pages. Learn about design decisions, implementation challenges, and deployment strategies.
Building DATASTAR: From Concept to Deployment
A Complete Tutorial on Creating a Professional Portfolio Website with Next.js, Tailwind CSS, and GitHub Pages
π Table of Contents
- Introduction
- The Vision
- Technology Choices
- Design System
- Development Process
- Internationalization
- Deployment Setup
- Custom Domain Configuration
- GitHub Actions CI/CD
- Lessons Learned
- Results
π― Introduction
This tutorial documents the complete journey of building DATASTAR - a professional portfolio website for a researcher transitioning from astrophysics to AI/ML in biomedical sciences. The site showcases research projects, publications, and professional experience with a unique astronomy-inspired design.
Live Site: datastar.space
Repository: github.com/drAbreu/web
π‘ The Vision
Goals
- Professional Presence - Showcase research at the intersection of astrophysics, AI, and biomedical sciences
- Bilingual Support - Reach both English and Spanish-speaking audiences
- Visual Identity - Create a unique "twilight mode" aesthetic inspired by astronomy
- Interactive Experience - Implement modern UI patterns (spotlight effects, smooth animations)
- Easy Maintenance - Set up automated deployment for quick updates
- Performance - Ensure fast load times and excellent SEO
Design Philosophy
The site draws inspiration from:
- Cosmic aesthetics - Deep space colors, stellar gradients
- Modern minimalism - Clean layouts, generous whitespace
- Technical elegance - Smooth animations, professional typography
- Accessibility - Clear hierarchy, readable fonts, responsive design
π οΈ Technology Choices
Framework: Next.js 16
Why Next.js?
- β Static Site Generation (SSG) for GitHub Pages
- β App Router for modern React patterns
- β Built-in optimization (images, fonts, CSS)
- β TypeScript support out of the box
- β Excellent developer experience
Alternative considered: Astro, Hugo Decision: Next.js offers the best balance of features, performance, and maintainability
Styling: Tailwind CSS
Why Tailwind?
- β Utility-first approach for rapid development
- β Easy customization (color palette, spacing)
- β No CSS conflicts or specificity issues
- β Purge unused styles automatically
- β Responsive design utilities
Alternative considered: CSS Modules, Styled Components Decision: Tailwind's utility classes make responsive design and maintenance much easier
Language: TypeScript
Why TypeScript?
- β Type safety prevents runtime errors
- β Better IDE support and autocomplete
- β Easier refactoring
- β Self-documenting code
Deployment: GitHub Pages
Why GitHub Pages?
- β Free hosting for static sites
- β Custom domain support
- β HTTPS certificate included
- β Integrated with GitHub Actions
- β Excellent uptime and performance
Alternative considered: Vercel, Netlify Decision: GitHub Pages offers simplicity and zero cost
π¨ Design System
Color Palette: "Twilight Mode"
The entire color scheme was extracted from the DATASTAR logo, creating a cohesive cosmic theme:
/* Deep Space Colors */
--brand-navy: #1a2845 /* Deep space navy */
--brand-purple: #4a3a5a /* Twilight purple */
--brand-burgundy: #8b4560 /* Dusk burgundy */
/* Warm Sunset Colors */
--brand-coral: #c97870 /* Sunset coral (primary accent) */
--brand-orange: #f4a566 /* Golden hour (secondary accent) */
--brand-gold: #ffc488 /* Stellar gold (highlights) */
Typography
Font: Inter by Google Fonts
- Excellent readability on screens
- Wide range of weights (300-800)
- Professional, modern appearance
- Optimized for digital displays
Hierarchy:
- Headings: Bold, large scale (4xl-8xl)
- Body: Regular weight, comfortable line height
- Accents: Semibold for emphasis
Layout Principles
- Mobile-First - Design for small screens, enhance for desktop
- Generous Whitespace - Let content breathe
- Clear Hierarchy - Guide the eye naturally
- Consistent Spacing - Use Tailwind's spacing scale
- Smooth Transitions - Animate state changes
π» Development Process
Phase 1: Project Setup
# Start with template repository
git clone https://github.com/Dingzeefs/website-template.git
# Initialize Next.js project
npm install
# Start development server
npm run dev
Initial Configuration:
next.config.js- Static export settingstailwind.config.ts- Custom color palettetsconfig.json- TypeScript compiler options.gitignore- Exclude build artifacts
Phase 2: Core Components
1. Navbar Component (src/components/Navbar.tsx)
Features:
- Sticky positioning
- Language switcher (EN/ES)
- Hamburger menu for mobile
- Smooth animations
- Gradient call-to-action button
Key Implementation:
export default function Navbar({ language, setLanguage, navTranslations }) {
const [mobileMenuOpen, setMobileMenuOpen] = useState(false)
return (
<header className="fixed top-0 left-0 right-0 z-50">
{/* Desktop navigation */}
{/* Mobile menu */}
</header>
)
}
2. Gradient Button (src/components/ui/gradient-button.tsx)
Features:
- Animated gradient background
- Hover effect with reversed gradient
- Uses Radix UI for accessibility
- Class Variance Authority for variants
Implementation:
const gradientButtonVariants = cva([
"gradient-button",
"inline-flex items-center justify-center",
"rounded-full px-9 py-4",
// ...more classes
])
export const GradientButton = React.forwardRef<HTMLButtonElement, Props>(
({ className, variant, asChild = false, ...props }, ref) => {
const Comp = asChild ? Slot : "button"
return <Comp className={cn(gradientButtonVariants({ variant, className }))} ref={ref} {...props} />
}
)
CSS Magic:
.gradient-button::before {
/* Normal gradient */
background: linear-gradient(135deg, navy, purple, burgundy, orange);
opacity: 1;
}
.gradient-button::after {
/* Reversed gradient for hover */
background: linear-gradient(135deg, orange, burgundy, purple, navy);
opacity: 0;
}
.gradient-button:hover::before { opacity: 0; }
.gradient-button:hover::after { opacity: 1; }
3. Spotlight Cursor (src/components/ui/spotlight-cursor.tsx)
Features:
- Follows mouse movement
- Radial gradient effect
- Canvas-based rendering
- Configurable radius, brightness, color
Implementation:
const useSpotlightEffect = (config: SpotlightConfig) => {
const canvasRef = useRef<HTMLCanvasElement>(null)
useEffect(() => {
const canvas = canvasRef.current
const ctx = canvas.getContext('2d')
const handleMouseMove = (event: MouseEvent) => {
mouseX = event.clientX
mouseY = event.clientY
}
const draw = () => {
// Create radial gradient at mouse position
const gradient = ctx.createRadialGradient(
mouseX, mouseY, 0,
mouseX, mouseY, config.radius
)
// ... render
requestAnimationFrame(draw)
}
// ... event listeners
}, [config])
return canvasRef
}
Phase 3: Page Development
Home Page (src/app/page.tsx)
Structure:
-
Hero Section
- Full-screen background image (moon with clouds)
- Gradient overlay
- Animated headline
- Stats grid (years, publications, expertise)
- Expertise tags
- CTA buttons
-
Projects Section
- 3x2 grid of project cards
- Animated on hover
- Color-coded by topic
- Links to external resources
Key Features:
- Responsive grid (1 column mobile, 3 columns desktop)
- Smooth hover animations
- Gradient text effects
- Background images with overlays
CV Page (src/app/cv/page.tsx)
Design Inspiration: Brittany Chiang's portfolio
Layout:
-
Sidebar (Desktop) - Sticky navigation
- Name and tagline
- Section navigation with active indicators
- Language switcher
- Academic links (ORCID, NASA/ADS, Google Scholar)
- Social media
-
Main Content
- About section
- Experience (Academic + Industry)
- Projects
- Education
- Publications
- Awards
- Outreach & Teaching
Interactive Features:
- Spotlight cursor effect (coral color)
- Active section highlighting
- Smooth scroll with offset
- Hover effects on cards
- Conditional rendering of EMBO resources
Implementation Details:
const [activeSection, setActiveSection] = useState("")
useEffect(() => {
const handleScroll = () => {
const sections = document.querySelectorAll("section[id]")
sections.forEach((section) => {
const sectionTop = section.getBoundingClientRect().top
if (sectionTop <= 100) {
setActiveSection(section.getAttribute("id") || "")
}
})
}
window.addEventListener("scroll", handleScroll)
return () => window.removeEventListener("scroll", handleScroll)
}, [])
Phase 4: Refinements
Removing Teal/Cyan Colors
Problem: Initial design included bright teal/cyan accents that clashed with the twilight theme.
Solution: Systematically replaced all accent-teal and accent-mint with warm twilight colors:
- Language switcher: teal β orange
- Hover states: teal β gold
- Active navigation: teal β coral
- Project cards: teal β gold/coral
- Spotlight: teal β coral
Files Changed:
src/app/globals.css- CSS variablestailwind.config.ts- Color definitionssrc/components/Navbar.tsx- All hover statessrc/app/page.tsx- All accent colorssrc/app/cv/page.tsx- All interactive elements
Result: Cohesive twilight aesthetic throughout the entire site.
Compressing CV Spacing
Problem: Initial CV layout had too much whitespace, requiring excessive scrolling.
Changes:
// Section spacing
mb-24 β mb-16 // 33% reduction
// Heading spacing
mb-12 β mb-8 // Better rhythm
// Item spacing
space-y-12 β space-y-8 // Experience
space-y-8 β space-y-6 // Awards
space-y-6 β space-y-4 // Publications
Result: More compact, scannable CV while maintaining readability.
Improving Typography
Problem: Default system fonts lacked the professional polish desired.
Solution: Integrated Google Fonts with Inter typeface:
<!-- src/app/layout.tsx -->
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="anonymous" />
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&display=swap" rel="stylesheet" />
/* src/app/globals.css */
body {
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
font-feature-settings: 'cv02', 'cv03', 'cv04', 'cv11';
font-optical-sizing: auto;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
π Internationalization
Architecture
Structure:
src/locales/
βββ en.ts # Home page - English
βββ es.ts # Home page - Spanish
βββ cv-en.ts # CV page - English
βββ cv-es.ts # CV page - Spanish
Implementation
Translation Hook (src/lib/i18n.ts):
export type Language = "en" | "es"
export const translations = { en, es }
export function useTranslation(lang: Language = "en") {
return translations[lang]
}
Usage in Components:
export default function Page() {
const [language, setLanguage] = useState<Language>("en")
const t = translations[language]
return (
<div>
<h1>{t.hero.title}</h1>
<p>{t.hero.description}</p>
</div>
)
}
Translation Strategy
English (Primary):
- Original content
- Technical terms in English
- International academic audience
Spanish:
- Natural, idiomatic translations
- Technical accuracy maintained
- Regional neutral (not specific to Spain/Latin America)
Example:
// en.ts
hero: {
title: "Illuminating insights through science",
cta: {
research: "Explore My Research",
cv: "View Full CV"
}
}
// es.ts
hero: {
title: "Iluminando conocimiento a travΓ©s de la ciencia",
cta: {
research: "Explorar Mi InvestigaciΓ³n",
cv: "Ver CV Completo"
}
}
π Deployment Setup
Migration Strategy
Challenge: Existing GitHub Pages site using Quarto needed to be preserved while deploying new Next.js site.
Solution:
- Create Legacy Branch:
cd /Users/jabreu/PycharmProjects/web
git add -A
git commit -m "Save current state"
git branch legacy_web
git push origin legacy_web
- Clean Master Branch:
git rm -rf .
git clean -fdx
- Copy New Site:
# From development repo
cd /Users/jabreu/PycharmProjects/web-new
rsync -av --exclude='node_modules' --exclude='.next' --exclude='out' . /Users/jabreu/PycharmProjects/web/
- Configure for GitHub Pages:
# Create CNAME for custom domain
echo "datastar.space" > CNAME
# Create .nojekyll to prevent Jekyll processing
touch .nojekyll
# Update README
vim README.md
Initial Deployment Attempt
Problem: Committed built artifacts (_next/, index.html) directly to repo.
Issues:
- Large repo size
- Mixed source and build files
- Hard to maintain
- Messy commit history
Result: Site deployed but repo structure was chaotic.
Refactoring to Clean Structure
Solution: Remove build artifacts, keep only source code, use GitHub Actions for builds.
# Remove all built files
git rm -rf index.html cv.html 404.html _next/ _not-found/ *.txt *.png *.jpg
# Commit clean structure
git add -A
git commit -m "β»οΈ Refactor: Clean repo structure + GitHub Actions CI/CD"
π Custom Domain Configuration
DNS Setup
Domain: datastar.space (registered at domain provider)
DNS Records:
# A Records (Apex domain)
Type: A
Name: @
Value: 185.199.108.153
Type: A
Name: @
Value: 185.199.109.153
Type: A
Name: @
Value: 185.199.110.153
Type: A
Name: @
Value: 185.199.111.153
# CNAME Record (www subdomain)
Type: CNAME
Name: www
Value: drAbreu.github.io
Why 4 A Records?
- Load balancing across GitHub's servers
- Redundancy (if one IP fails)
- Better global performance
- DDoS protection
TTL (Time To Live):
- Initial: 30 minutes (for quick fixes during setup)
- Production: 1-24 hours (for stability)
GitHub Pages Configuration
Settings β Pages:
- Source: GitHub Actions (not "Deploy from a branch")
- Custom Domain: datastar.space
- Enforce HTTPS: β Enabled (after DNS propagation)
CNAME File:
# In repository root
echo "datastar.space" > CNAME
git add CNAME
git commit -m "Add custom domain"
git push
DNS Propagation
Timeline:
- DNS records added
- Wait 10-30 minutes (fast)
- Up to 48 hours (worst case)
- Check propagation: dnschecker.org
Verification:
nslookup datastar.space
# Expected output:
Server: 192.168.178.1
Address: 192.168.178.1#53
Non-authoritative answer:
Name: datastar.space
Address: 185.199.108.153
Name: datastar.space
Address: 185.199.109.153
Name: datastar.space
Address: 185.199.110.153
Name: datastar.space
Address: 185.199.111.153
HTTPS Certificate
Automatic Certificate:
- GitHub automatically provisions Let's Encrypt certificate
- Takes ~24 hours after DNS verification
- Auto-renews before expiration
- Force HTTPS redirects all HTTP traffic
βοΈ GitHub Actions CI/CD
Workflow Design
Goals:
- Automatic deployment on every push to
master - Clean separation of source and build artifacts
- Fast build times
- Clear error messages
Workflow File (.github/workflows/deploy.yml)
name: Deploy Next.js to GitHub Pages
on:
push:
branches: ["master"]
workflow_dispatch: # Allow manual triggers
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: "pages"
cancel-in-progress: false
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: "20"
cache: 'npm'
- name: Setup Pages
uses: actions/configure-pages@v4
- name: Install dependencies
run: npm ci
- name: Build with Next.js
run: npm run build
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: ./out
deploy:
runs-on: ubuntu-latest
needs: build
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
Initial Workflow Issues
Problem 1: Environment Protection
Error: Branch "master" is not allowed to deploy to github-pages
due to environment protection rules.
Cause: GitHub Pages environment had branch restrictions.
Solution: Removed environment specification from workflow:
# Before (failed):
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
# After (works):
deploy:
runs-on: ubuntu-latest
needs: build
Alternative: Configure environment to allow all branches.
Deployment Flow
1. Developer pushes to master
β
2. GitHub detects push
β
3. Workflow triggers automatically
β
4. Job 1: Build
- Checkout code
- Install Node.js 20
- Cache dependencies
- Run npm ci (clean install)
- Run npm run build
- Upload ./out as artifact
β
5. Job 2: Deploy
- Download artifact from Job 1
- Deploy to GitHub Pages
β
6. Site updated (3-5 minutes)
Monitoring Deployments
GitHub Actions Tab:
- Real-time build logs
- Success/failure status
- Build duration
- Error messages
GitHub Deployments Tab:
- Production environment status
- Deployment history
- Rollback capability
Example Successful Deployment:
β build (1m 30s)
β Checkout (2s)
β Setup Node (5s)
β Setup Pages (1s)
β Install dependencies (30s)
β Build with Next.js (45s)
β Upload artifact (7s)
β deploy (15s)
β Deploy to GitHub Pages (15s)
Total time: 1m 45s
π Lessons Learned
1. Separate Source from Build Artifacts
Mistake: Initially committed _next/, out/, and built HTML files to the repository.
Problem:
- Bloated repository
- Merge conflicts on build files
- Unclear what's source vs. generated
- Wasted storage and bandwidth
Solution: Use GitHub Actions to build on-demand, keep only source in repo.
Benefit: Clean, maintainable codebase.
2. Design System First
Success: Extracting the color palette from the DATASTAR logo before coding saved significant refactoring time.
Approach:
- Analyze logo colors
- Create comprehensive palette (6-8 colors)
- Define usage rules (primary, accent, highlight)
- Document in design system file
- Configure Tailwind with custom colors
- Use consistently across all components
Benefit: Cohesive visual identity, easy to make global changes.
3. Remove Conflicting Colors Early
Mistake: Started with template colors (teal/cyan) that clashed with the twilight theme.
Impact: Had to systematically search and replace across entire codebase.
Lesson: Establish color palette and remove template defaults immediately.
4. Test DNS Propagation
Discovery: DNS propagation can be instant or take hours.
Best Practice:
- Use low TTL (30 min) during setup
- Test with
nslookupbefore pushing code - Use dnschecker.org for global verification
- Increase TTL to 1-24 hours once stable
5. GitHub Actions vs. Manual Deployment
Manual Deployment:
- Build locally
- Commit built files
- Push to GitHub
- β Error-prone, tedious, messy repo
GitHub Actions:
- Push source code
- Automatic build and deploy
- β Clean, reliable, professional
Lesson: Set up CI/CD from the start, even for simple sites.
6. Mobile-First Design
Success: Designing for mobile first, then enhancing for desktop, resulted in:
- Better mobile experience
- Cleaner code (progressive enhancement)
- Faster development (less refactoring)
Approach:
- Design smallest screen first (320px)
- Add breakpoints as needed (sm, md, lg, xl)
- Test on real devices
7. Internationalization Architecture
Success: Separate translation files for each page made management easy.
Structure:
src/locales/
βββ en.ts # Home EN
βββ es.ts # Home ES
βββ cv-en.ts # CV EN
βββ cv-es.ts # CV ES
Benefits:
- Easy to find translations
- Can translate pages independently
- Translators can work on specific files
- Type-safe with TypeScript
8. Performance Optimization
Next.js Image Component:
<Image
src="/background.jpg"
alt="Description"
fill
priority // Above fold
quality={85}
/>
Benefits:
- Automatic WebP conversion
- Responsive images
- Lazy loading
- Blur placeholder
9. Documentation Matters
Lesson: Writing comprehensive README and tutorial:
- Forces you to understand your own code
- Makes future updates easier
- Helps others learn
- Creates shareable content
Best Practice: Document as you build, not after.
10. Version Control Best Practices
Branch Strategy:
master- Production codelegacy_web- Old Quarto site (preserved)- Feature branches for major changes
Commit Messages:
- Use conventional commits
- Be descriptive
- Include emoji for quick scanning
Examples:
β¨ feat: Add spotlight cursor effect to CV page
π fix: Resolve mobile menu toggle issue
β»οΈ refactor: Clean repo structure + GitHub Actions
π docs: Update README with deployment instructions
π¨ style: Replace teal with twilight colors
π― Results
Metrics
Performance:
- β‘ Load Time: < 1 second (static export)
- π¨ First Contentful Paint: ~0.4s
- π Lighthouse Score: 95+ (Performance)
- π± Mobile-Friendly: 100% (Google test)
SEO:
- β Meta tags configured
- β Open Graph images
- β Twitter Card
- β Semantic HTML
- β Alt text on all images
Accessibility:
- β ARIA labels
- β Keyboard navigation
- β Focus indicators
- β Color contrast (WCAG AA)
Code Quality:
- β TypeScript (no any types)
- β ESLint passing
- β No console errors
- β Responsive design (320px - 4K)
Features Delivered
β Bilingual Support (EN/ES) β Twilight Theme (custom color palette) β Interactive CV (spotlight cursor, active nav) β Project Showcase (animated cards) β Responsive Design (mobile-first) β Custom Domain (datastar.space) β HTTPS (Let's Encrypt) β CI/CD (GitHub Actions) β Clean Codebase (source only, no build artifacts)
Before & After
Before (Quarto Site):
- Static site generator (R-based)
- Orange/blue color scheme
- English only
- Manual deployment
- Limited interactivity
After (DATASTAR):
- Modern React framework (Next.js)
- Custom twilight theme
- Bilingual (EN/ES)
- Automatic deployment
- Rich interactions (spotlight, animations)
- Better performance
- Easier to maintain
π Future Enhancements
Short Term
-
Blog Section
- Markdown-based posts
- Code syntax highlighting
- RSS feed
- Search functionality
-
Projects Page
- Detailed project pages
- Image galleries
- Demo videos
- GitHub integration
-
Analytics
- Privacy-friendly (Plausible or Fathom)
- Track page views
- Monitor engagement
Medium Term
-
Contact Form
- Server-side validation
- Spam protection
- Email notifications
-
Publications Integration
- Auto-fetch from ORCID API
- Citation counts
- Download PDFs
-
Newsletter
- Email subscription
- Research updates
- Monthly digest
Long Term
-
Morgenrot Subdomain
- Separate mental health book site
- Different theme (calm, psychological)
morgenrot.datastar.space
-
Interactive Visualizations
- Research data visualization
- D3.js or Observable
- Astronomy simulations
-
CMS Integration
- Contentful or Sanity.io
- Non-technical content updates
- Preview deployments
π‘ Conclusion
Building DATASTAR was a journey from concept to deployed website, touching on:
- Design - Creating a cohesive visual identity
- Development - Modern React patterns and TypeScript
- Internationalization - Supporting multiple languages
- DevOps - CI/CD with GitHub Actions
- Networking - DNS configuration and custom domains
The result is a professional, performant, maintainable portfolio site that accurately represents the intersection of astrophysics, AI, and biomedical research.
Key Takeaways:
- β¨ Design system first - Establish colors and typography early
- π Automate deployment - GitHub Actions saves time and reduces errors
- π Internationalization - Structure for i18n from the start
- π± Mobile-first - Better experience, cleaner code
- π Document everything - Future you will thank present you
π Resources
Code & Documentation
- Live Site: datastar.space
- Repository: github.com/drAbreu/web
- Legacy Site: github.com/drAbreu/web/tree/legacy_web
Tools & Frameworks
Design Inspiration
Learning Resources
π€ About the Author
Dr. Jorge Abreu-Vicente, PhD
Astrophysicist turned AI/ML researcher specializing in biomedical sciences, knowledge graphs, and open science.
- ORCID: 0000-0002-0211-6416
- GitHub: @drAbreu
- LinkedIn: abreujorge-dataresearch
Published: November 30, 2025
Last Updated: November 30, 2025
Reading Time: ~30 minutes
If this tutorial helped you build your own portfolio site, I'd love to hear about it! Feel free to reach out or share your creation.

Jorge Abreu-Vicente, PhD
Astrophysicist & Data Scientist
Bridging astrophysics and data science with expertise in machine learning, computational simulations, and biomedical AI. From studying cosmic phenomena to advancing healthcare technology.
Interested in collaborating? Let's connect!
