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
cdinto 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/'
breakPage 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.
