A modern, customizable portfolio template built with Astro 7 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, GitHub integration, and Astro 7 support
- π Type-Safe Content - Full TypeScript support with validated schemas
- π± Fully Responsive - Mobile-first design with DaisyUI components
- β‘ Fast & Optimized - Server rendering with automatic image optimization
- π Smooth Transitions - Page transitions using Astro's View Transitions API
- π¦ Markdoc Support - Enhanced markdown with custom Spotify, YouTube, and Twitter tags
- π― 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
- π·οΈ Project Categories - Organize projects by custom categories (managed via Keystatic CMS)
- π 3 Projects Page Layouts - Grid, Horizontal Tabs, or Sidebar layout (configurable in General Settings)
- π§ Content Sidebar - Sticky H1/H2 article navigation with collapsible H3 sublevels, global defaults, per-page overrides, and a responsive mobile outline
- π Blog Drafts - Keep unfinished posts in Keystatic without listing them or exposing their public page
- π Inline Links in Hero - Add clickable links inside Hero title and description using
[link:<url>]text[/link]syntax - π¨ Modern Stack - Astro 7 + Vite 8 + Tailwind CSS 4 + DaisyUI 5 + TypeScript 6
- π SEO Optimized - Meta tags, Open Graph, and semantic HTML
- βΏ Accessible - Built with accessibility in mind
- Node.js 22.12.0 or newer
- npm, pnpm, or yarn
Astro 7 requires Node.js 22.12.0 or newer. The included .nvmrc selects that minimum version, and @keystatic/astro 5.2 declares Astro 7 compatibility.
Astro 7 uses Vite 8 and its stricter Rust compiler. Run npm run check and npm run build after changing components or content to catch invalid templates and schema errors.
# 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 check |
Run TypeScript, Astro, and content 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)
- Content sidebar visibility and left/right position
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.
Organize your projects by custom categories. Categories are managed via Keystatic CMS as a dedicated collection:
- Go to
/keystaticβ Project Categories - Create categories with a name, description, emoji icon, and sort order
- When editing a Project, select its category from the dropdown
Three default categories are included: π€ AI Made, π Real Projects, π§ͺ Experiments.
On the /projects page, projects are grouped under their category heading. Uncategorized projects appear in an "Other" section.
Choose from 3 layout styles for the projects listing page in General Settings β Projects Page Layout:
| Layout | Description |
|---|---|
| Grid (default) | Stacked category sections with card grids |
| Horizontal Tabs | DaisyUI tabs-border with an All tab followed by category tabs |
| Sidebar | DaisyUI menu with an All item followed by category items |
Blog posts and project detail pages automatically build an On this page menu from H1, H2, and H3 headings. H3 links are grouped beneath their nearest H2 and start collapsed; use the chevron beside an H2 to reveal them. On desktop the menu stays sticky beside the article and scrolls internally when it reaches its maximum height. On mobile it becomes a compact, collapsible outline above the content.
Configure the defaults in General Settings:
- Show Content Sidebar: enabled by default
- Content Sidebar Position:
rightby default;leftis also available
Each Blog Post and Project includes Override Global Content Sidebar in Keystatic. Enable it to replace both global values for that page. When editing files manually, use:
contentSidebar:
discriminant: true
value:
show: true
position: leftOmit contentSidebar to use the global settings.
You can add clickable links inside the Hero section's Title and Description fields using a simple syntax:
[link:<url>]visible text[/link]
Example:
Astro Portfolio Template built with [link:https://daisyui.com]πΌ DaisyUI[/link]
Renders as: Astro Portfolio Template built with πΌ DaisyUI
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
β β βββ ProjectsLayoutGrid.astro # Grid layout (default)
β β βββ ProjectsLayoutTabsHorizontal.astro # Horizontal tabs layout
β β βββ ProjectsLayoutTabsVertical.astro # Sidebar menu layout
β β βββ 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 .mdoc)
β β βββ education/ # Education history
β β βββ general/ # General settings
β β βββ hackathons/# Hackathon entries
β β βββ projectCategories/ # Project category definitions
β β βββ 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
β βββ utils/
β β βββ iconMapper.ts
β β βββ parseInlineLinks.ts # [link:<url>]text[/link] parser
β βββ content.config.ts # Content schemas
βββ astro.config.mjs # Astro configuration
βββ keystatic.config.ts # Keystatic CMS 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 - Published articles and unlisted drafts 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)
- For Blog Posts, leave Published unchecked until the article is ready
- 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"
published: true
publishDate: "2024-01-25"
tags: ["Tag1", "Tag2"]
---
Your content here...Set published: false to keep the article as a draft. Drafts remain editable in Keystatic but are excluded from the homepage, the Blog page, and direct public access.
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)
category: real-projects # Category slug (managed in Project Categories)
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. The category field references a slug from the Project Categories collection.
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 Title with [link:https://example.com]a link[/link]"
description: Brief description of your portfolio
avatar: "./avatar.png"
location: π Your Location
socialLinks:
- url: https://github.com/username
icon: GitHub
label: GitHub
# ... 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!
Bloomfolio uses output: "server" with @astrojs/vercel because Keystatic needs on-demand routes. To deploy elsewhere, install that platform's Astro 7-compatible adapter, replace the Vercel adapter in astro.config.mjs, and follow the platform's server-rendered deployment instructions.
- Astro 7 - Server-rendered web framework with component islands
- 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 with Astro 7 support
- Lucide Icons - Icon library
- Complete Guide - Comprehensive setup and customization guide
- Content Collections Guide - Learn about Astro Content Collections
- Markdown Guide - Master Markdown and Markdoc 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