A filterable portfolio built with Astro.
A detailed article about this starter can be found here: Building a Filterable Portfolio with Astro and Vue
Live demo: codesandbox.io/p/github/ttntm/astro-portfolio-starter
- Astro (developed and tested with version 4.0.2)
- Vue (Astro integration)
- Tailwind CSS (Astro integration) + typography plugin
- Fork, clone or download
cd
into the root folder- run
npm install
- run
npm run dev
- open a browser and go to
http://localhost:4321
- Astro:
./astro.config.mjs
- Tailwind:
./tailwind.config.cjs
CSS (in ./src/styles/
) is processed by Astro directly; this project is using the Tailwind integration module.
Deployment:
Astro requires the final deployed URL in its config file.
Replace the placeholder with your site's URL and keep the trailing slash:
case 'production':
build.siteURL = 'https://example.com/'
break
Page structure and templates are stored in ./src/layouts/
and can be edited there.
./layouts/Base.astro
exposes 2 slots - one named header
and a default one - which are used to inject the actual page content.
The portfolio is a collection that's defined in ./src/content/config.ts
. Collection pages (in ./src/content/portfolio/
) are processed in alphabetical order by the [...path].astro
page template in ./src/pages/
. Its getStaticPaths()
function processes the whole collection and generates both the index/list page (via path: undefined
) and the individual project pages (via path: page.slug
) rendered by the project page template in ./src/layouts/PortfolioLayoutSingle.astro
.
Page content is stored in
./src/pages/
(Astro's default; see docs)./src/content/portfolio/
Images are stored in ./public/img/
and are not being processed by any image optimization.
This is probably not ideal, but getImage()
from astro:image
(docs) can only be used on the server side, meaning that conditional rendering based on filtered data will make it break (yes, I tried).
If image size and performance should become an issue at some point: I can recommend using unlazy together with a (blurred) placeholder image and an intersection observer (i.e. useIntersectionObserver() from VueUse).
Portfolio projects must have one or more tags as defined for the portfolio
collection in ./src/content/config.ts
.
Tags are extracted and processed automatically by the getStaticPaths()
function of the [...path].astro
page template in ./src/pages
and the PortfolioList.vue
component in ./src/components/interactive/
to build the tag-based filters/sub-navigation.