A modern, responsive personal portfolio website built with Next.js, TypeScript, Tailwind CSS, and Motion. Fork it, customize it, and make it your own.
- Next.js Server-Side Rendering — Fast initial page loads with server-side data fetching
- Tailwind CSS — Utility-first styling with custom dark theme
- Motion Animations — Smooth, performant animations throughout
- Blog System — Markdown-based articles with tag filtering and modal reading
- GitHub Integration — Automatically fetches and displays GitHub repositories
- Responsive Design — Mobile-first layout with adaptive grid system
- Docker Development — Containerized development and production environments
| Category | Technology |
|---|---|
| Framework | Next.js 16, React 19, TypeScript |
| Styling | Tailwind CSS with custom theme |
| Animations | Motion (Framer Motion) |
| Markdown | react-markdown with GitHub Flavored Markdown |
| Build | Turbopack (dev), OpenNext for Cloudflare (production) |
| Deploy | Cloudflare Workers via GitHub Actions |
| Container | Docker with multi-stage builds (local testing) |
# Clone the repository
git clone https://github.com/ds-brandao/personalWebsite.git
cd personalWebsite/next-app
npm install
# Start the development server
npm run devOpen http://localhost:3000 in your browser.
docker compose up dev# With Node.js
cd next-app
npm run build
npm run start
# With Docker
docker build -t personal-website .
docker run -p 80:80 personal-website├── next-app/ # Next.js application
│ ├── app/
│ │ ├── (tabs)/ # Home, Articles, Projects routes
│ │ ├── globals.css # Design tokens (warm-neutral light/dark)
│ │ └── fonts.ts # Schibsted Grotesk, Hanken Grotesk, JetBrains Mono
│ ├── components/ # React components
│ │ ├── Hero.tsx # Home hero
│ │ ├── ProjectGrid.tsx # Project cards + commits panel
│ │ ├── ArticleCard.tsx # Blog post cards
│ │ └── ActivityFeed.tsx # Unified recent activity feed
│ ├── lib/
│ │ └── data.ts # Server-side data fetching
│ ├── types/
│ │ └── index.ts # TypeScript type definitions
│ ├── public/
│ │ ├── config/ # Configuration files
│ │ │ ├── config.json # Personal info & tags
│ │ │ └── articles.json # Blog post metadata
│ │ ├── blog-posts/ # Markdown blog posts
│ │ └── images/ # Static images
│ └── package.json
├── Dockerfile # Multi-stage Docker build
├── docker-compose.yaml # Development environment
└── README.md
Edit next-app/public/config/config.json to set your name, social links, and tags:
{
"personal": {
"name": "Your Name"
},
"social": {
"github": { "username": "your-username", "url": "https://github.com/..." },
"email": "your@email.com",
"linkedin": "https://linkedin.com/in/..."
},
"tags": { ... }
}- Create a Markdown file in
next-app/public/blog-posts/ - Add metadata to
next-app/public/config/articles.json:
{
"title": "Article Title",
"summary": "Brief description",
"markdown": "/blog-posts/article.md",
"image": "/images/blog/article.jpg",
"objectPosition": "center 50%",
"tags": ["Tag1", "Tag2"]
}Repository and commit data is fetched anonymously (60 requests/hour). To raise the limit to 5,000/hour, provide a token:
cd next-app
echo "GITHUB_TOKEN=your-token-here" > .env.localThe site deploys to Cloudflare Workers via the OpenNext Cloudflare adapter.
.github/workflows/deploy.yaml:
- Push to
main→ production deploy todbrandao.com+ smoke test - Pull requests → preview version with its own shareable URL (production untouched)
Requires two repository secrets: CLOUDFLARE_API_TOKEN (the "Edit Cloudflare Workers" token template) and CLOUDFLARE_ACCOUNT_ID.
cd next-app
npx wrangler login # once
npm run deploy # opennextjs-cloudflare build && deployTest the production build in workerd locally (no deploy):
cd next-app
npm run preview- KV namespace
personal-website-inc-cachebacks the incremental cache (5-minute GitHub data revalidation); its id is bound inwrangler.jsonc npx wrangler secret put GITHUB_TOKEN— raises the GitHub API limit for the Worker- The Worker owns the
dbrandao.comandwww.dbrandao.comcustom domains (www 301s to the apex). The former Zero Trust tunnel DNS record was removed at cutover.
docker build -t personal-website .
docker run -d -p 3100:3000 personal-websiteContributions are welcome! Here's how you can help:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Please make sure your code:
- Passes linting (
npm run lintinnext-app/) - Builds successfully (
npm run buildinnext-app/) - Follows the existing code style
Found a bug or have a feature request? Open an issue with a clear description and steps to reproduce.
This project is licensed under the MIT License.