A modern, customizable portfolio template built with Astro 5 and DaisyUI 5. A beautiful, fast, and highly customizable portfolio template for developers, designers, and creatives.
- π¨ 6 Built-in Themes - Light, Dark, Synthwave, Retro, Valentine, and Dim
- π 6 Content Collections - Blog, Projects, Work, Education, Hackathons, and About
- π¨ Keystatic CMS - Visual content editor with live preview and GitHub integration
- π Type-Safe Content - Full TypeScript support with validated schemas
- π± Fully Responsive - Mobile-first design with DaisyUI components
- β‘ Fast & Optimized - Static site generation with automatic image optimization
- π Smooth Transitions - Page transitions using Astro's View Transitions API
- π¦ MDX Support - Enhanced markdown with component imports (Spotify, YouTube, Twitter)
- π― Configuration-Driven - Customize everything through a central config file
- πΈ FAB Flower Menu - Expandable floating action button for extra links (desktop)
- π± Mobile Dock Navigation - Bottom navigation bar for mobile devices
- β Featured Projects - Highlight your best work on the homepage
- π¨ Modern Stack - Astro 5 + Tailwind CSS 4 + DaisyUI 5 + TypeScript
- π SEO Optimized - Meta tags, Open Graph, and semantic HTML
- βΏ Accessible - Built with accessibility in mind
- Node.js 18+ or 20+
- npm, pnpm, or yarn
# Clone the repository
git clone https://github.com/lauroguedes/bloomfolio.git
# Navigate to the project directory
cd bloomfolio
# Install dependencies
npm install
# Start the development server
npm run devVisit http://localhost:4321 to see your portfolio!
All commands are run from the root of the project:
| Command | Action |
|---|---|
npm install |
Install dependencies |
npm run dev |
Start dev server at localhost:4321 |
npm run build |
Build production site to ./dist/ |
npm run preview |
Preview production build locally |
npm run astro check |
Run TypeScript and Astro checks |
npm run astro ... |
Run Astro CLI commands |
All site configuration is managed through Keystatic CMS or by editing content files directly in src/content/.
- Start the development server:
npm run dev - Navigate to
http://localhost:4321/keystatic - Edit General Settings to configure:
- Theme selector (dropdown vs toggle)
- Section visibility
- Extra links (FAB & Dock)
Control which sections appear on your homepage through General Settings in Keystatic:
- About section
- Projects showcase (shows up to 3 featured projects)
- Blog posts (shows 3 most recent)
- Work experience timeline
- Education history
- Hackathon participation
- Contact section
The Hero section is always visible.
Choose between a theme selector dropdown or a simple light/dark toggle in General Settings.
Available Themes: light, dark, synthwave, retro, valentine, dim
Configure the floating action button (desktop) and mobile dock navigation:
extraLinks:
- link: /blog/guide
icon: BookOpen
label: Guide
displayOn: both # Options: both, dock, fab
- link: /resume.pdf
icon: FileText
label: Resume
displayOn: fab # Only show on desktop FABThe displayOn option controls where each link appears:
both- Shows on both FAB (desktop) and Dock (mobile)fab- Only shows on the floating action button (desktop)dock- Only shows on the bottom dock (mobile)
bloomfolio/
βββ public/ # Static assets
β βββ favicon.svg
βββ src/
β βββ assets/ # Images and media
β β βββ bloomfolio.png
β βββ components/ # Reusable components
β β βββ About.astro
β β βββ Blog.astro
β β βββ BlogCard.astro
β β βββ Contact.astro
β β βββ Dock.astro # Mobile bottom navigation
β β βββ FabFlower.astro # Desktop floating action button
β β βββ Hackathons.astro
β β βββ Hero.astro
β β βββ ProjectCard.astro
β β βββ Projects.astro
β β βββ SkillBadge.astro
β β βββ Spotify.astro
β β βββ ThemeSelector.astro
β β βββ ThemeToggle.astro
β β βββ Timeline.astro
β β βββ Twitter.astro
β β βββ YouTube.astro
β βββ content/ # Content collections
β β βββ about/ # About section (1 file)
β β βββ blog/ # Blog posts (.md or .mdx)
β β βββ education/ # Education history
β β βββ hackathons/# Hackathon entries
β β βββ projects/ # Portfolio projects
β β βββ work/ # Work experience
β βββ layouts/ # Page layouts
β β βββ Layout.astro
β β βββ BlogLayout.astro
β β βββ ProjectLayout.astro
β βββ pages/ # File-based routing
β β βββ index.astro
β β βββ blog/
β β β βββ index.astro
β β β βββ [...slug].astro
β β βββ projects/
β β βββ index.astro
β β βββ [...slug].astro
β βββ styles/
β β βββ global.css # Tailwind + DaisyUI + Typography
β βββ content.config.ts # Content schemas
βββ astro.config.mjs # Astro configuration
βββ package.json
βββ tsconfig.json
βββ README.md
Bloomfolio offers two powerful ways to manage your content: the Keystatic CMS for a visual editing experience, or direct file editing for developers who prefer working with code.
Keystatic is a modern, Git-based headless CMS that provides a user-friendly interface for managing your content without touching code.
-
Start the development server:
npm run dev
-
Navigate to the admin panel:
http://localhost:4321/keystatic -
Start creating and editing content through the visual interface!
Keystatic is a Git-based CMS that:
- Stores content as files in your repository (not in a database)
- Provides a beautiful visual editor with live preview
- Works with local development and GitHub/GitLab workflows
- Generates type-safe content with full TypeScript support
- Integrates seamlessly with Astro's Content Collections
Learn more: Keystatic Documentation
Singletons (one-per-site content):
- Hero Section - Your name, title, avatar, social links
- About Section - Personal bio with photo (supports Markdown)
Collections (multiple entries):
- Blog Posts - Articles with cover images, tags, and rich media embeds
- Projects - Portfolio items with screenshots, descriptions, and tech stacks
- Work Experience - Timeline of employment history
- Education - Academic background
- Hackathons - Competitive coding events and achievements
-
Create New Entries
- Click "Create entry" in any collection
- Fill out the form fields (Keystatic validates required fields)
- Use the rich text editor for Markdown content
- Upload images directly through the interface
-
Edit Existing Content
- Select any entry from the collection list
- Make changes in the visual editor
- See live preview of your content
-
Rich Media Embeds (Blog posts only)
- Click the "+" button in the content editor
- Select from available components: Spotify, YouTube, Twitter
- Paste the URL and Keystatic handles the rest
β οΈ Important: Media components (Spotify, YouTube, Twitter) are only available in blog posts. Files must use the.mdocextension (not.md). To extend components to other collections, see the technical guide in CLAUDE.md. -
Save Changes
- All changes are saved as file edits in
src/content/ - Changes are automatically detected by Astro's dev server
- Commit and push your changes like any other code
- All changes are saved as file edits in
Local Mode (Current Setup)
- Content stored in
src/content/directory - Changes saved as file system edits
- Perfect for personal portfolios and single-user sites
GitHub/Cloud Mode (Future upgrade)
- Content synced with GitHub repository
- Enable collaboration with non-technical users
- Manage content from anywhere via hosted admin panel
- See Keystatic Cloud documentation for setup
If you prefer working directly with files, all content is stored in src/content/ as Markdown, YAML, or Markdoc files.
Create a new file in src/content/blog/:
---
title: "Your Post Title"
description: "Brief description for SEO"
image: "./featured-image.png"
publishDate: "2024-01-25"
tags: ["Tag1", "Tag2"]
---
Your content here...File Extensions:
.md- Standard Markdown for regular blog posts.mdoc- Markdoc with component support (required for media embeds)
Rich Media Embeds (.mdoc files only):
Note: Media components only work in blog collection currently.
# Spotify Embed
{% Spotify url="https://open.spotify.com/track/..." /%}
# YouTube Video
{% YouTube url="https://youtube.com/watch?v=..." /%}
# Twitter/X Post
{% Twitter url="https://x.com/username/status/..." /%}Create a new file in src/content/projects/:
---
featured: true # Show on homepage (max 3 featured projects)
title: "Project Name"
description: "Brief description"
image: "./screenshot.png"
startDate: "2023-01-15"
endDate: "2023-06-30" # Optional (omit for ongoing)
skills: ["React", "Node.js", "MongoDB"]
demoLink: "https://demo.example.com" # Optional
sourceLink: "https://github.com/..." # Optional
---
Detailed project description...Set featured: true to display the project on the homepage. Up to 3 featured projects are shown, sorted by most recent.
Create a new file in src/content/work/:
---
title: "Company Name"
subtitle: "Job Title"
location: "City, Country" # Optional
startDate: "2020-01-15"
endDate: "2023-06-30" # Optional (omit for current position)
logo: "https://company-logo-url.com" # Optional
link: "https://company-website.com" # Optional
skills: ["React", "TypeScript", "Node.js"] # Optional
---
Job description and achievements...The timeline displays duration automatically and skills are shown in modal dialogs.
Create a new file in src/content/education/:
---
title: "Institution Name"
subtitle: "Degree/Course"
startDate: "2015-09-01"
endDate: "2019-06-30" # Optional
logo: "https://institution-logo-url.com" # Optional
link: "https://institution.edu" # Optional
---
Educational details and achievements...Create a new file in src/content/hackathons/:
---
title: "Hackathon Name"
location: "City, State or Virtual"
description: "Brief hackathon summary"
startDate: "2023-11-23"
endDate: "2023-11-25" # Optional
logo: "https://hackathon-logo-url.com" # Optional
sourceLink: "https://github.com/..." # Optional
---
Detailed information about the hackathon and your project...Hero (src/content/hero/index.yaml):
name: Your Name
title: Your Professional Title
description: Brief description of your portfolio
avatar: "./avatar.png"
location: π Your Location
githubUrl: https://github.com/username
linkedinUrl: https://linkedin.com/in/username
# ... other social linksAbout (src/content/about/index.md):
---
title: "About Me"
photo: "./photo.png"
link: "https://linkedin.com/in/username" # Optional - used for "More Work Experience" button
---
Your about content with **Markdown** formatting...Image Paths:
- Use relative paths like
"./image.png"for local images - Images are automatically optimized by Astro
- Supported formats: PNG, JPG, WEBP, AVIF, SVG
Dates:
- Format:
YYYY-MM-DD(e.g., "2024-01-15") - Leave
endDateempty for ongoing positions/projects
Skills/Tags:
- Arrays of strings:
["React", "TypeScript", "Node.js"] - Display as badges in the UI
- Keystatic Documentation - Complete CMS guide
- Keystatic Content Components - Creating custom components
- Astro Content Collections - Type-safe content schemas
- Markdoc Syntax - Enhanced Markdown format
For remote content editing from anywhere, you can enable Keystatic's GitHub mode:
- GitHub account
- Repository hosted on GitHub
-
Create GitHub OAuth App
Visit GitHub Developer Settings and create a new Github App:
- Application name: Bloomfolio Keystatic
- Homepage URL:
http://localhost:4321(for local development) - Authorization callback URL:
http://localhost:4321/api/keystatic/github/oauth/callback
For production, use your deployed URL instead.
-
Set Environment Variables
Copy
.env.exampleto.env:cp .env.example .env
Fill in your values:
KEYSTATIC_GITHUB_CLIENT_ID=your_client_id_here KEYSTATIC_GITHUB_CLIENT_SECRET=your_client_secret_here KEYSTATIC_SECRET=$(openssl rand -base64 32) PUBLIC_KEYSTATIC_REPO_OWNER=your-github-username PUBLIC_KEYSTATIC_REPO_NAME=bloomfolio PUBLIC_KEYSTATIC_GITHUB_APP_SLUG=your-github-app-slug -
Restart Development Server
npm run dev
-
Access Keystatic
Navigate to
http://localhost:4321/keystaticand sign in with GitHub.
For production deployment (Vercel, Netlify, etc.):
- Add all environment variables to your hosting platform's environment settings
- Update OAuth App callback URL to your production domain
- Set
PUBLIC_KEYSTATIC_GITHUB_APP_SLUG(optional, for GitHub App mode)
Learn more: Keystatic GitHub Mode Documentation
- GitHub Mode: Set environment variables (content synced with GitHub)
- Local Mode: Remove/unset environment variables (content stored locally)
The configuration automatically detects which mode to use based on environment variables.
Edit theme settings via Keystatic CMS at /keystatic or directly in src/content/general/index.yaml:
enableThemeSelector: true # Dropdown with 6 themes (false = simple toggle)To change available themes, edit src/styles/global.css:
@plugin "daisyui" {
themes: light --default, dark --prefersdark, synthwave, retro, valentine, dim;
}Add custom CSS in component <style> tags or extend src/styles/global.css:
@import "tailwindcss";
@plugin "@tailwindcss/typography";
@plugin "daisyui" { ... };
/* Your custom styles here */- Create a new component in
src/components/ - Import and add to
src/pages/index.astro - Add a visibility toggle in
keystatic.config.ts(general singleton) - Update
src/content.config.tsschema to match
npm run buildOutput is generated in dist/ directory.
- Connect your GitHub repository
- Vercel auto-detects Astro
- Deploy!
- Connect your repository
- Build command:
npm run build - Publish directory:
dist
- Connect your repository
- Build command:
npm run build - Build output directory:
dist
Bloomfolio works with any static hosting platform that supports Node.js builds:
- GitHub Pages
- AWS S3 + CloudFront
- Firebase Hosting
- Render
- Railway
- Astro 5 - Static site generator
- Tailwind CSS 4 - Utility-first CSS framework
- Tailwind Typography - Beautiful prose styling
- DaisyUI 5 - Component library for Tailwind
- TypeScript - Type safety
- Markdoc - Enhanced Markdown with components
- Keystatic - Git-based CMS for content management
- Lucide Icons - Icon library
- Complete Guide - Comprehensive setup and customization guide
- Content Collections Guide - Learn about Astro Content Collections
- Markdown Guide - Master Markdown and MDX syntax
- Astro Docs - Official Astro documentation
- Tailwind CSS Docs - Tailwind CSS documentation
- DaisyUI Docs - DaisyUI component documentation
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
- Built with Astro
- Styled with Tailwind CSS and DaisyUI
- Icons from Lucide
- Inspired by modern portfolio designs and the developer community
- π Documentation
- π Report Issues
- π¬ Discussions
Please if you find this project helpful, consider giving it a β on GitHub!
Crafted by an Artisan βοΈ Lauro Guedes