├── .npmrc ├── public ├── post_img.webp ├── profile.webp ├── social_img.webp ├── itemPreview.webp ├── robots.txt └── favicon.svg ├── src ├── env.d.ts ├── styles │ └── global.css ├── pages │ ├── 404.astro │ ├── rss.xml.js │ ├── blog │ │ ├── [slug].astro │ │ ├── [...page].astro │ │ └── tag │ │ │ └── [tag] │ │ │ └── [...page].astro │ ├── store │ │ ├── [slug].astro │ │ └── [...page].astro │ ├── services.astro │ ├── projects.astro │ ├── index.astro │ └── cv.astro ├── config.ts ├── components │ ├── cv │ │ └── TimeLine.astro │ ├── Footer.astro │ ├── Header.astro │ ├── Card.astro │ ├── SideBar.astro │ ├── SideBarMenu.astro │ ├── HorizontalShopItem.astro │ ├── HorizontalCard.astro │ ├── BaseHead.astro │ └── SideBarFooter.astro ├── lib │ └── createSlug.ts ├── content │ ├── config.ts │ ├── store │ │ ├── item1.md │ │ ├── item2.md │ │ └── item3.md │ └── blog │ │ ├── post2.md │ │ ├── post1.md │ │ └── post3.md └── layouts │ ├── BaseLayout.astro │ ├── PostLayout.astro │ └── StoreItemLayout.astro ├── .vscode ├── extensions.json └── launch.json ├── tsconfig.json ├── .gitignore ├── astro.config.mjs ├── tailwind.config.cjs ├── .github └── FUNDING.yml ├── package.json ├── LICENSE └── README.md /.npmrc: -------------------------------------------------------------------------------- 1 | # Expose Astro dependencies for `pnpm` users 2 | shamefully-hoist=true 3 | -------------------------------------------------------------------------------- /public/post_img.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/manuelernestog/astrofy/HEAD/public/post_img.webp -------------------------------------------------------------------------------- /public/profile.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/manuelernestog/astrofy/HEAD/public/profile.webp -------------------------------------------------------------------------------- /public/social_img.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/manuelernestog/astrofy/HEAD/public/social_img.webp -------------------------------------------------------------------------------- /src/env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// -------------------------------------------------------------------------------- /public/itemPreview.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/manuelernestog/astrofy/HEAD/public/itemPreview.webp -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Allow: / 3 | 4 | Sitemap: https://astrofy-template.netlify.app/sitemap-index.xml -------------------------------------------------------------------------------- /src/styles/global.css: -------------------------------------------------------------------------------- 1 | .time-line-container>div:last-child .education__time>.education__line { 2 | display: none; 3 | } -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["astro-build.astro-vscode"], 3 | "unwantedRecommendations": [] 4 | } 5 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "command": "./node_modules/.bin/astro dev", 6 | "name": "Development server", 7 | "request": "launch", 8 | "type": "node-terminal" 9 | } 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "astro/tsconfigs/base", 3 | "compilerOptions": { 4 | "strictNullChecks": true, 5 | "baseUrl": ".", 6 | "paths": { 7 | "@components/*": [ 8 | "src/components/*" 9 | ], 10 | "@layouts/*": [ 11 | "src/layouts/*" 12 | ] 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # build output 2 | dist/ 3 | .cache 4 | # dependencies 5 | node_modules/ 6 | 7 | # logs 8 | npm-debug.log* 9 | yarn-debug.log* 10 | yarn-error.log* 11 | pnpm-debug.log* 12 | 13 | 14 | # environment variables 15 | .env 16 | .env.production 17 | 18 | # macOS-specific files 19 | .DS_Store 20 | 21 | # Astro 22 | .astro/ -------------------------------------------------------------------------------- /astro.config.mjs: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'astro/config'; 2 | import mdx from '@astrojs/mdx'; 3 | import sitemap from '@astrojs/sitemap'; 4 | import tailwind from "@astrojs/tailwind"; 5 | 6 | // https://astro.build/config 7 | export default defineConfig({ 8 | site: 'https://astrofy-template.netlify.app', 9 | integrations: [mdx(), sitemap(), tailwind()] 10 | }); -------------------------------------------------------------------------------- /src/pages/404.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import BaseLayout from "../layouts/BaseLayout.astro"; 3 | --- 4 | 5 | 6 |
7 |

🏝

8 |

404

9 |

The page you're looking for couldn't be found.

10 | Home 11 |
12 |
13 | -------------------------------------------------------------------------------- /src/config.ts: -------------------------------------------------------------------------------- 1 | // Place any global data in this file. 2 | // You can import this data from anywhere in your site by using the `import` keyword. 3 | 4 | export const SITE_TITLE = 'Astrofy | Personal Portfolio Website Template'; 5 | export const SITE_DESCRIPTION = 'Astrofy is a free and open-source template for your Personal Portfolio Website built with Astro and TailwindCSS. Create in minutes a website with Blog, CV, Project Section, Store and RSS Feed.'; 6 | export const GENERATE_SLUG_FROM_TITLE = true 7 | export const TRANSITION_API = true -------------------------------------------------------------------------------- /src/components/cv/TimeLine.astro: -------------------------------------------------------------------------------- 1 | --- 2 | const { title, subtitle } = Astro.props; 3 | --- 4 | 5 |
6 |
7 | 8 | 9 |
10 |
11 |

{title}

12 | {subtitle} 13 |

14 | 15 |

16 |
17 |
18 | -------------------------------------------------------------------------------- /src/pages/rss.xml.js: -------------------------------------------------------------------------------- 1 | import rss from "@astrojs/rss"; 2 | import { SITE_TITLE, SITE_DESCRIPTION } from "../config"; 3 | import { getCollection } from "astro:content"; 4 | 5 | export async function get(context) { 6 | const blog = await getCollection("blog"); 7 | return rss({ 8 | title: SITE_TITLE, 9 | description: SITE_DESCRIPTION, 10 | site: import.meta.env.SITE, 11 | items: blog.map((post) => ({ 12 | title: post.data.title, 13 | pubDate: post.data.pubDate, 14 | description: post.data.description, 15 | link: `/blog/${post.slug}/`, 16 | })), 17 | }); 18 | } 19 | -------------------------------------------------------------------------------- /tailwind.config.cjs: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'], 4 | theme: { 5 | extend: {}, 6 | }, 7 | plugins: [require("@tailwindcss/typography"),require("daisyui")], 8 | daisyui: { 9 | themes: true, // true: all themes | false: only light + dark | array: specific themes like this ["light", "dark", "cupcake"] 10 | darkTheme: "dark", // name of one of the included themes for dark mode 11 | logs: false, // Shows info about daisyUI version and used config in the console when building your CSS 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/components/Footer.astro: -------------------------------------------------------------------------------- 1 | --- 2 | const today = new Date(); 3 | --- 4 | 5 | 15 | 16 | -------------------------------------------------------------------------------- /src/lib/createSlug.ts: -------------------------------------------------------------------------------- 1 | // Adapted from https://equk.co.uk/2023/02/02/generating-slug-from-title-in-astro/ 2 | 3 | import { GENERATE_SLUG_FROM_TITLE } from '../config' 4 | 5 | export default function (title: string, staticSlug: string) { 6 | return ( 7 | !GENERATE_SLUG_FROM_TITLE ? staticSlug : title 8 | // remove leading & trailing whitespace 9 | .trim() 10 | // output lowercase 11 | .toLowerCase() 12 | // replace spaces 13 | .replace(/\s+/g, '-') 14 | // remove special characters 15 | .replace(/[^\w-]/g, '') 16 | // remove leading & trailing separtors 17 | .replace(/^-+|-+$/g, '') 18 | ) 19 | } 20 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # github: USERNAME or github: [USERNAME, USERNAME, USERNAME, USERNAME] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: #manuelernestogr 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: ["https://manuelernestog.github.io/support-my-work/"] 13 | -------------------------------------------------------------------------------- /src/components/Header.astro: -------------------------------------------------------------------------------- 1 |
4 | 17 |
18 | -------------------------------------------------------------------------------- /src/components/Card.astro: -------------------------------------------------------------------------------- 1 | --- 2 | const { title, img, desc, url, badge, tags, target = "_blank" } = Astro.props; 3 | import { Image } from "astro:assets"; 4 | --- 5 | 6 | 23 | 24 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "astrofy", 3 | "description": "Astrofy is a free and open-source template for your Personal Portfolio Website built with Astro and TailwindCSS. Create in minutes a website with Blog, CV, Project Section, Store and RSS Feed.", 4 | "type": "module", 5 | "version": "3.0.0", 6 | "private": true, 7 | "scripts": { 8 | "dev": "astro dev", 9 | "start": "astro dev", 10 | "build": "astro build", 11 | "preview": "astro preview", 12 | "astro": "astro" 13 | }, 14 | "dependencies": { 15 | "@astrojs/mdx": "^2.0.3", 16 | "@astrojs/rss": "^3.0.0", 17 | "@astrojs/sitemap": "^3.0.1", 18 | "@astrojs/tailwind": "^5.0.3", 19 | "astro": "^4.0.2", 20 | "daisyui": "^4.4.10", 21 | "dayjs": "^1.11.9", 22 | "sharp": "^0.32.6", 23 | "tailwindcss": "^3.3.5" 24 | }, 25 | "devDependencies": { 26 | "@tailwindcss/typography": "^0.5.10" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /public/favicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 13 | 14 | -------------------------------------------------------------------------------- /src/components/SideBar.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import SideBarFooter from "./SideBarFooter.astro"; 3 | import { Image } from "astro:assets"; 4 | import SideBarMenu from "./SideBarMenu.astro"; 5 | const { sideBarActiveItemID } = Astro.props; 6 | --- 7 | 8 |
9 | 10 | 23 |
24 | -------------------------------------------------------------------------------- /src/pages/blog/[slug].astro: -------------------------------------------------------------------------------- 1 | --- 2 | import { CollectionEntry, getCollection } from "astro:content"; 3 | import { BlogSchema } from "../../content/config"; 4 | import PostLayout from "../../layouts/PostLayout.astro"; 5 | import createSlug from "../../lib/createSlug" 6 | 7 | export async function getStaticPaths() { 8 | const postEntries = await getCollection("blog"); 9 | return postEntries.map((entry) => ({ 10 | params: { slug: createSlug(entry.data.title, entry.slug) }, 11 | props: { entry }, 12 | })); 13 | } 14 | 15 | interface Props { 16 | entry: CollectionEntry<"blog">; 17 | } 18 | 19 | const { entry } = Astro.props; 20 | const post: BlogSchema = entry.data; 21 | const { Content } = await entry.render(); 22 | --- 23 | 24 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /src/pages/store/[slug].astro: -------------------------------------------------------------------------------- 1 | --- 2 | import { CollectionEntry, getCollection } from "astro:content"; 3 | import { StoreSchema } from "../../content/config"; 4 | import StoreItemLayout from "../../layouts/StoreItemLayout.astro"; 5 | 6 | export async function getStaticPaths() { 7 | const itemEntries = await getCollection("store"); 8 | return itemEntries.map((entry) => ({ 9 | params: { slug: entry.slug }, 10 | props: { entry }, 11 | })); 12 | } 13 | 14 | interface Props { 15 | entry: CollectionEntry<"store">; 16 | } 17 | 18 | const { entry } = Astro.props; 19 | const item: StoreSchema = entry.data; 20 | const { Content } = await entry.render(); 21 | --- 22 | 23 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Manuel Ernesto Garcia 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/components/SideBarMenu.astro: -------------------------------------------------------------------------------- 1 | --- 2 | const { sideBarActiveItemID } = Astro.props; 3 | const activeClass = "bg-base-300"; // For primary color replace with `active` class 4 | --- 5 | 6 | 22 | 23 | 27 | -------------------------------------------------------------------------------- /src/components/HorizontalShopItem.astro: -------------------------------------------------------------------------------- 1 | --- 2 | const { 3 | title, 4 | img, 5 | desc, 6 | url, 7 | badge, 8 | pricing, 9 | oldPricing, 10 | checkoutUrl, 11 | details = true, 12 | custom_link = false, 13 | custom_link_label = "", 14 | } = Astro.props; 15 | import { Image } from "astro:assets"; 16 | --- 17 | 18 | 47 | -------------------------------------------------------------------------------- /src/content/config.ts: -------------------------------------------------------------------------------- 1 | import { z, defineCollection } from "astro:content"; 2 | const blogSchema = z.object({ 3 | title: z.string(), 4 | description: z.string(), 5 | pubDate: z.coerce.date(), 6 | updatedDate: z.string().optional(), 7 | heroImage: z.string().optional(), 8 | badge: z.string().optional(), 9 | tags: z.array(z.string()).refine(items => new Set(items).size === items.length, { 10 | message: 'tags must be unique', 11 | }).optional(), 12 | }); 13 | 14 | const storeSchema = z.object({ 15 | title: z.string(), 16 | description: z.string(), 17 | custom_link_label: z.string(), 18 | custom_link: z.string().optional(), 19 | updatedDate: z.coerce.date(), 20 | pricing: z.string().optional(), 21 | oldPricing: z.string().optional(), 22 | badge: z.string().optional(), 23 | checkoutUrl: z.string().optional(), 24 | heroImage: z.string().optional(), 25 | }); 26 | 27 | export type BlogSchema = z.infer; 28 | export type StoreSchema = z.infer; 29 | 30 | const blogCollection = defineCollection({ schema: blogSchema }); 31 | const storeCollection = defineCollection({ schema: storeSchema }); 32 | 33 | export const collections = { 34 | 'blog': blogCollection, 35 | 'store': storeCollection 36 | } -------------------------------------------------------------------------------- /src/components/HorizontalCard.astro: -------------------------------------------------------------------------------- 1 | --- 2 | const { title, img, desc, url, badge, tags, target = "_blank" } = Astro.props; 3 | import { Image } from "astro:assets"; 4 | const tag_url = url.split("/").slice(0, -1).join("/") + "/tag"; 5 | --- 6 | 7 | 44 | -------------------------------------------------------------------------------- /src/layouts/BaseLayout.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import BaseHead from "../components/BaseHead.astro"; 3 | import Header from "../components/Header.astro"; 4 | import Footer from "../components/Footer.astro"; 5 | import SideBar from "../components/SideBar.astro"; 6 | import { ViewTransitions } from "astro:transitions"; 7 | 8 | import { SITE_TITLE, SITE_DESCRIPTION, TRANSITION_API } from "../config"; 9 | 10 | const { 11 | image, 12 | title = SITE_TITLE, 13 | description = SITE_DESCRIPTION, 14 | includeSidebar = true, 15 | sideBarActiveItemID, 16 | ogType, 17 | } = Astro.props; 18 | --- 19 | 20 | 21 | 22 | 23 | 24 | {TRANSITION_API && } 25 | 26 | 27 |
28 | 29 |
30 |
31 |
32 |
33 | 34 |
35 |
36 |
37 |
38 | {includeSidebar && } 39 |
40 | 41 | 42 | -------------------------------------------------------------------------------- /src/pages/services.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import BaseLayout from "../layouts/BaseLayout.astro"; 3 | import HorizontalCard from "../components/HorizontalCard.astro"; 4 | --- 5 | 6 | 7 |
8 |
Services Header
9 |
10 | 11 | 18 |
19 | 25 |
26 | 33 |
34 | 40 |
41 | -------------------------------------------------------------------------------- /src/components/BaseHead.astro: -------------------------------------------------------------------------------- 1 | --- 2 | // Import the global.css file here so that it is included on 3 | // all pages through the use of the component. 4 | import '../styles/global.css'; 5 | 6 | export interface Props { 7 | title: string; 8 | description: string; 9 | image?: string; 10 | ogType?: string; 11 | } 12 | 13 | const { title, description, image = '/social_img.webp', ogType = 'website' } = Astro.props; 14 | --- 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | {title} 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /src/layouts/PostLayout.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import { type BlogSchema } from "../content/config"; 3 | import BaseLayout from "./BaseLayout.astro"; 4 | import dayjs from "dayjs"; 5 | import localizedFormat from "dayjs/plugin/localizedFormat"; 6 | 7 | export interface Props extends BlogSchema {} 8 | 9 | const { title, description, pubDate, updatedDate, heroImage, badge, tags = [] } = Astro.props; 10 | dayjs.extend(localizedFormat); 11 | const displayDate = dayjs(pubDate).format("ll") 12 | import { Image } from "astro:assets"; 13 | --- 14 | 15 | 16 |
17 |
18 | {heroImage && {title}} 19 |

{title}

20 | {pubDate && } 21 |
22 | {badge &&
{badge}
} 23 | { 24 | tags && 25 | tags.map((tag) => ( 26 | 27 | {tag} 28 | 29 | )) 30 | } 31 | { 32 | updatedDate && ( 33 |
34 | {" "} 35 | Last updated on {" "} 36 |
37 | ) 38 | } 39 |
40 | 41 |
42 |
43 |
44 | -------------------------------------------------------------------------------- /src/content/store/item1.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Demo Item 1" 3 | description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua." 4 | custom_link_label: "Live Preview" 5 | custom_link: "https://demourl.com/" 6 | updatedDate: "Sep 15 2022" 7 | pricing: "$15" 8 | badge: "Featured" 9 | checkoutUrl: "https://checkouturl.com/" 10 | heroImage: "/itemPreview.webp" 11 | --- 12 | 13 | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Vitae ultricies leo integer malesuada nunc vel risus commodo viverra. Adipiscing enim eu turpis egestas pretium. Euismod elementum nisi quis eleifend quam adipiscing. In hac habitasse platea dictumst vestibulum. Sagittis purus sit amet volutpat. Netus et malesuada fames ac turpis egestas. Eget magna fermentum iaculis eu non diam phasellus vestibulum lorem. Varius sit amet mattis vulputate enim. Habitasse platea dictumst quisque sagittis. Integer quis auctor elit sed vulputate mi. Dictumst quisque sagittis purus sit amet. 14 | 15 | Morbi tristique senectus et netus. Id semper risus in hendrerit gravida rutrum quisque non tellus. Habitasse platea dictumst quisque sagittis purus sit amet. Tellus molestie nunc non blandit massa. Cursus vitae congue mauris rhoncus. Accumsan tortor posuere ac ut. Fringilla urna porttitor rhoncus dolor. Elit ullamcorper dignissim cras tincidunt lobortis. In cursus turpis massa tincidunt dui ut ornare lectus. Integer feugiat scelerisque varius morbi enim nunc. Bibendum neque egestas congue quisque egestas diam. Cras ornare arcu dui vivamus arcu felis bibendum. Dignissim suspendisse in est ante in nibh mauris. Sed tempus urna et pharetra pharetra massa massa ultricies mi. -------------------------------------------------------------------------------- /src/content/store/item2.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Demo Item 2" 3 | description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua." 4 | custom_link_label: "Custom Btn" 5 | custom_link: "https://customurl.com/" 6 | updatedDate: "Sep 11 2022" 7 | pricing: "$10" 8 | oldPricing: "$25.5" 9 | checkoutUrl: "https://checkouturl.com/" 10 | heroImage: "/itemPreview.webp" 11 | --- 12 | 13 | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Vitae ultricies leo integer malesuada nunc vel risus commodo viverra. Adipiscing enim eu turpis egestas pretium. Euismod elementum nisi quis eleifend quam adipiscing. In hac habitasse platea dictumst vestibulum. Sagittis purus sit amet volutpat. Netus et malesuada fames ac turpis egestas. Eget magna fermentum iaculis eu non diam phasellus vestibulum lorem. Varius sit amet mattis vulputate enim. Habitasse platea dictumst quisque sagittis. Integer quis auctor elit sed vulputate mi. Dictumst quisque sagittis purus sit amet. 14 | 15 | Morbi tristique senectus et netus. Id semper risus in hendrerit gravida rutrum quisque non tellus. Habitasse platea dictumst quisque sagittis purus sit amet. Tellus molestie nunc non blandit massa. Cursus vitae congue mauris rhoncus. Accumsan tortor posuere ac ut. Fringilla urna porttitor rhoncus dolor. Elit ullamcorper dignissim cras tincidunt lobortis. In cursus turpis massa tincidunt dui ut ornare lectus. Integer feugiat scelerisque varius morbi enim nunc. Bibendum neque egestas congue quisque egestas diam. Cras ornare arcu dui vivamus arcu felis bibendum. Dignissim suspendisse in est ante in nibh mauris. Sed tempus urna et pharetra pharetra massa massa ultricies mi. -------------------------------------------------------------------------------- /src/content/store/item3.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Demo Item 3" 3 | description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua." 4 | custom_link_label: "Custom Btn" 5 | custom_link: "https://customurl.com/" 6 | updatedDate: "Sep 11 2022" 7 | pricing: "$10" 8 | oldPricing: "$25.5" 9 | checkoutUrl: "https://checkouturl.com/" 10 | heroImage: "/itemPreview.webp" 11 | --- 12 | 13 | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Vitae ultricies leo integer malesuada nunc vel risus commodo viverra. Adipiscing enim eu turpis egestas pretium. Euismod elementum nisi quis eleifend quam adipiscing. In hac habitasse platea dictumst vestibulum. Sagittis purus sit amet volutpat. Netus et malesuada fames ac turpis egestas. Eget magna fermentum iaculis eu non diam phasellus vestibulum lorem. Varius sit amet mattis vulputate enim. Habitasse platea dictumst quisque sagittis. Integer quis auctor elit sed vulputate mi. Dictumst quisque sagittis purus sit amet. 14 | 15 | Morbi tristique senectus et netus. Id semper risus in hendrerit gravida rutrum quisque non tellus. Habitasse platea dictumst quisque sagittis purus sit amet. Tellus molestie nunc non blandit massa. Cursus vitae congue mauris rhoncus. Accumsan tortor posuere ac ut. Fringilla urna porttitor rhoncus dolor. Elit ullamcorper dignissim cras tincidunt lobortis. In cursus turpis massa tincidunt dui ut ornare lectus. Integer feugiat scelerisque varius morbi enim nunc. Bibendum neque egestas congue quisque egestas diam. Cras ornare arcu dui vivamus arcu felis bibendum. Dignissim suspendisse in est ante in nibh mauris. Sed tempus urna et pharetra pharetra massa massa ultricies mi. -------------------------------------------------------------------------------- /src/pages/projects.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import BaseLayout from "../layouts/BaseLayout.astro"; 3 | import HorizontalCard from "../components/HorizontalCard.astro"; 4 | --- 5 | 6 | 7 |
8 |
Projects Header
9 |
10 | 11 | 18 |
19 | 25 | 26 |
27 |
Projects Header
28 |
29 | 30 | 37 |
38 | 44 |
45 | 51 |
52 | -------------------------------------------------------------------------------- /src/layouts/StoreItemLayout.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import { type StoreSchema } from "../content/config"; 3 | import BaseLayout from "./BaseLayout.astro"; 4 | import dayjs from "dayjs"; 5 | import localizedFormat from "dayjs/plugin/localizedFormat"; 6 | 7 | export interface Props extends StoreSchema {} 8 | 9 | const { 10 | title, 11 | description, 12 | updatedDate, 13 | heroImage, 14 | pricing, 15 | oldPricing, 16 | checkoutUrl, 17 | badge, 18 | custom_link, 19 | custom_link_label, 20 | } = Astro.props; 21 | 22 | dayjs.extend(localizedFormat); 23 | const displayDate = dayjs(updatedDate).format("ll"); 24 | import { Image } from "astro:assets"; 25 | --- 26 | 27 | 28 |
29 |
30 | { 31 | heroImage && ( 32 | {title} 33 | ) 34 | } 35 |
36 |

37 | {title} 38 | {badge &&
{badge}
} 39 |

40 |
41 |
42 | {pricing} 43 | {oldPricing} 44 |
45 |
46 | { 47 | custom_link && ( 48 | 49 | {custom_link_label} 50 | 51 | ) 52 | } 53 | Buy Now 54 |
55 |
56 |
57 |
58 | 59 |
60 |
61 |
62 | -------------------------------------------------------------------------------- /src/pages/store/[...page].astro: -------------------------------------------------------------------------------- 1 | --- 2 | import BaseLayout from "../../layouts/BaseLayout.astro"; 3 | import HorizontalShopItem from "../../components/HorizontalShopItem.astro"; 4 | import { getCollection } from "astro:content"; 5 | 6 | export async function getStaticPaths({ paginate }) { 7 | const items = await getCollection("store"); 8 | items.sort((a, b) => b.data.updatedDate.valueOf() - a.data.updatedDate.valueOf()); 9 | return paginate(items, { pageSize: 10 }); 10 | } 11 | const { page } = Astro.props; 12 | --- 13 | 14 | 15 |
    16 | { 17 | page.data.map((item) => ( 18 | <> 19 | 33 |
    34 | 35 | )) 36 | } 37 |
38 | 39 |
40 | { 41 | page.url.prev ? ( 42 | 43 | {" "} 44 | 51 | 52 | {" "} 53 | Previous page 54 | 55 | ) : ( 56 |
57 | ) 58 | } 59 | { 60 | page.url.next ? ( 61 | 62 | Next page{" "} 63 | 70 | {" "} 71 | 72 | 73 | 74 | ) : ( 75 |
76 | ) 77 | } 78 |
79 | 80 | -------------------------------------------------------------------------------- /src/pages/blog/[...page].astro: -------------------------------------------------------------------------------- 1 | --- 2 | import BaseLayout from "../../layouts/BaseLayout.astro"; 3 | import HorizontalCard from "../../components/HorizontalCard.astro"; 4 | import { getCollection } from "astro:content"; 5 | import createSlug from "../../lib/createSlug" 6 | 7 | export async function getStaticPaths({ paginate }) { 8 | const posts = await getCollection("blog"); 9 | posts.sort((a, b) => b.data.pubDate.valueOf() - a.data.pubDate.valueOf()); 10 | return paginate(posts, { pageSize: 10 }); 11 | } 12 | 13 | const { page } = Astro.props; 14 | --- 15 | 16 | 17 |
18 |
Blog
19 |
20 | 21 | { 22 | page.data.length === 0 ? ( 23 |
24 |

Sorry!

25 |

There are no blog posts to show at the moment. Check back later!

26 |
27 | ) : ( 28 |
    29 | {page.data.map((post) => ( 30 | <> 31 | 40 |
    41 | 42 | ))} 43 |
44 | ) 45 | } 46 | 47 |
48 | { 49 | page.url.prev ? ( 50 | 51 | {" "} 52 | 59 | 60 | {" "} 61 | Recent posts 62 | 63 | ) : ( 64 |
65 | ) 66 | } 67 | { 68 | page.url.next ? ( 69 | 70 | Older Posts{" "} 71 | 78 | {" "} 79 | 80 | 81 | 82 | ) : ( 83 |
84 | ) 85 | } 86 |
87 | 88 | -------------------------------------------------------------------------------- /src/pages/index.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import BaseLayout from "../layouts/BaseLayout.astro"; 3 | import HorizontalCard from "../components/HorizontalCard.astro"; 4 | import { getCollection } from "astro:content"; 5 | import createSlug from "../lib/createSlug" 6 | 7 | const posts = (await getCollection("blog")).sort((a, b) => b.data.pubDate.valueOf() - a.data.pubDate.valueOf()); 8 | 9 | const last_posts = posts.slice(0, 3); 10 | --- 11 | 12 | 13 |
14 |
Hey there 👋
15 |
I'm Manuel Ernesto
16 |
Software Engineer and Entrepreneur
17 |
18 | 19 | This is Astrofy a free and open-source template for your Personal Portfolio Website built with Astro and TailwindCSS. 20 | Create in minutes a website with Blog, CV, Project Section, Store and RSS Feed. I hope you find 21 | it useful! 22 | 23 |
24 | 30 |
31 | 32 |
33 |
My last projects {""}
34 |
35 | 36 | 43 |
44 | 50 |
51 | 58 | 59 |
60 |
Latest from blog
61 |
62 | 63 | { 64 | last_posts.map((post) => ( 65 | <> 66 | 74 |
75 | 76 | )) 77 | } 78 | 79 | -------------------------------------------------------------------------------- /src/pages/blog/tag/[tag]/[...page].astro: -------------------------------------------------------------------------------- 1 | --- 2 | import BaseLayout from "@layouts/BaseLayout.astro"; 3 | import HorizontalCard from "@components/HorizontalCard.astro"; 4 | import { getCollection } from "astro:content"; 5 | import createSlug from "../../../../lib/createSlug"; 6 | 7 | export async function getStaticPaths({ paginate }) { 8 | const all_posts = await getCollection("blog"); 9 | const all_tags = all_posts.flatMap((post) => { 10 | return post.data.tags || []; 11 | }); 12 | 13 | return all_tags.flatMap((tag) => { 14 | const filtred_posts = all_posts.filter((post) => { 15 | return post.data.tags?.includes(tag); 16 | }); 17 | return paginate(filtred_posts, { 18 | params: { tag }, 19 | pageSize: 10, 20 | }); 21 | }); 22 | } 23 | 24 | const { page } = Astro.props; 25 | const params = Astro.params; 26 | --- 27 | 28 | 29 |
30 |
Blog - {params.tag}
31 |
32 | { 33 | page.data.length === 0 ? ( 34 |
35 |

Sorry!

36 |

There are no blog posts to show at the moment. Check back later!

37 |
38 | ) : ( 39 |
    40 | {page.data.map((post) => ( 41 | <> 42 | 51 |
    52 | 53 | ))} 54 |
55 | ) 56 | } 57 | 58 |
59 | { 60 | page.url.prev ? ( 61 | 62 | {" "} 63 | 70 | 71 | {" "} 72 | Recent posts 73 | 74 | ) : ( 75 |
76 | ) 77 | } 78 | { 79 | page.url.next ? ( 80 | 81 | Older Posts{" "} 82 | 89 | {" "} 90 | 91 | 92 | 93 | ) : ( 94 |
95 | ) 96 | } 97 |
98 | 99 | -------------------------------------------------------------------------------- /src/content/blog/post2.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Demo Post 2" 3 | description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua." 4 | pubDate: "Sep 11 2022" 5 | heroImage: "/post_img.webp" 6 | --- 7 | 8 | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Vitae ultricies leo integer malesuada nunc vel risus commodo viverra. Adipiscing enim eu turpis egestas pretium. Euismod elementum nisi quis eleifend quam adipiscing. In hac habitasse platea dictumst vestibulum. Sagittis purus sit amet volutpat. Netus et malesuada fames ac turpis egestas. Eget magna fermentum iaculis eu non diam phasellus vestibulum lorem. Varius sit amet mattis vulputate enim. Habitasse platea dictumst quisque sagittis. Integer quis auctor elit sed vulputate mi. Dictumst quisque sagittis purus sit amet. 9 | 10 | Morbi tristique senectus et netus. Id semper risus in hendrerit gravida rutrum quisque non tellus. Habitasse platea dictumst quisque sagittis purus sit amet. Tellus molestie nunc non blandit massa. Cursus vitae congue mauris rhoncus. Accumsan tortor posuere ac ut. Fringilla urna porttitor rhoncus dolor. Elit ullamcorper dignissim cras tincidunt lobortis. In cursus turpis massa tincidunt dui ut ornare lectus. Integer feugiat scelerisque varius morbi enim nunc. Bibendum neque egestas congue quisque egestas diam. Cras ornare arcu dui vivamus arcu felis bibendum. Dignissim suspendisse in est ante in nibh mauris. Sed tempus urna et pharetra pharetra massa massa ultricies mi. 11 | 12 | Mollis nunc sed id semper risus in. Convallis a cras semper auctor neque. Diam sit amet nisl suscipit. Lacus viverra vitae congue eu consequat ac felis donec. Egestas integer eget aliquet nibh praesent tristique magna sit amet. Eget magna fermentum iaculis eu non diam. In vitae turpis massa sed elementum. Tristique et egestas quis ipsum suspendisse ultrices. Eget lorem dolor sed viverra ipsum. Vel turpis nunc eget lorem dolor sed viverra. Posuere ac ut consequat semper viverra nam. Laoreet suspendisse interdum consectetur libero id faucibus. Diam phasellus vestibulum lorem sed risus ultricies tristique. Rhoncus dolor purus non enim praesent elementum facilisis. Ultrices tincidunt arcu non sodales neque. Tempus egestas sed sed risus pretium quam vulputate. Viverra suspendisse potenti nullam ac tortor vitae purus faucibus ornare. Fringilla urna porttitor rhoncus dolor purus non. Amet dictum sit amet justo donec enim. 13 | 14 | Mattis ullamcorper velit sed ullamcorper morbi tincidunt. Tortor posuere ac ut consequat semper viverra. Tellus mauris a diam maecenas sed enim ut sem viverra. Venenatis urna cursus eget nunc scelerisque viverra mauris in. Arcu ac tortor dignissim convallis aenean et tortor at. Curabitur gravida arcu ac tortor dignissim convallis aenean et tortor. Egestas tellus rutrum tellus pellentesque eu. Fusce ut placerat orci nulla pellentesque dignissim enim sit amet. Ut enim blandit volutpat maecenas volutpat blandit aliquam etiam. Id donec ultrices tincidunt arcu. Id cursus metus aliquam eleifend mi. 15 | 16 | Tempus quam pellentesque nec nam aliquam sem. Risus at ultrices mi tempus imperdiet. Id porta nibh venenatis cras sed felis eget velit. Ipsum a arcu cursus vitae. Facilisis magna etiam tempor orci eu lobortis elementum. Tincidunt dui ut ornare lectus sit. Quisque non tellus orci ac. Blandit libero volutpat sed cras. Nec tincidunt praesent semper feugiat nibh sed pulvinar proin gravida. Egestas integer eget aliquet nibh praesent tristique magna. -------------------------------------------------------------------------------- /src/content/blog/post1.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Demo Post 1" 3 | description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua." 4 | pubDate: "Sep 10 2022" 5 | heroImage: "/post_img.webp" 6 | tags: ["tokio"] 7 | --- 8 | 9 | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor 10 | incididunt ut labore et dolore magna aliqua. Vitae ultricies leo integer 11 | malesuada nunc vel risus commodo viverra. Adipiscing enim eu turpis egestas 12 | pretium. Euismod elementum nisi quis eleifend quam adipiscing. In hac habitasse 13 | platea dictumst vestibulum. Sagittis purus sit amet volutpat. Netus et malesuada 14 | fames ac turpis egestas. Eget magna fermentum iaculis eu non diam phasellus 15 | vestibulum lorem. Varius sit amet mattis vulputate enim. Habitasse platea 16 | dictumst quisque sagittis. Integer quis auctor elit sed vulputate mi. Dictumst 17 | quisque sagittis purus sit amet. 18 | 19 | Morbi tristique senectus et netus. Id semper risus in hendrerit gravida rutrum 20 | quisque non tellus. Habitasse platea dictumst quisque sagittis purus sit amet. 21 | Tellus molestie nunc non blandit massa. Cursus vitae congue mauris rhoncus. 22 | Accumsan tortor posuere ac ut. Fringilla urna porttitor rhoncus dolor. Elit 23 | ullamcorper dignissim cras tincidunt lobortis. In cursus turpis massa tincidunt 24 | dui ut ornare lectus. Integer feugiat scelerisque varius morbi enim nunc. 25 | Bibendum neque egestas congue quisque egestas diam. Cras ornare arcu dui vivamus 26 | arcu felis bibendum. Dignissim suspendisse in est ante in nibh mauris. Sed 27 | tempus urna et pharetra pharetra massa massa ultricies mi. 28 | 29 | Mollis nunc sed id semper risus in. Convallis a cras semper auctor neque. Diam 30 | sit amet nisl suscipit. Lacus viverra vitae congue eu consequat ac felis donec. 31 | Egestas integer eget aliquet nibh praesent tristique magna sit amet. Eget magna 32 | fermentum iaculis eu non diam. In vitae turpis massa sed elementum. Tristique et 33 | egestas quis ipsum suspendisse ultrices. Eget lorem dolor sed viverra ipsum. Vel 34 | turpis nunc eget lorem dolor sed viverra. Posuere ac ut consequat semper viverra 35 | nam. Laoreet suspendisse interdum consectetur libero id faucibus. Diam phasellus 36 | vestibulum lorem sed risus ultricies tristique. Rhoncus dolor purus non enim 37 | praesent elementum facilisis. Ultrices tincidunt arcu non sodales neque. Tempus 38 | egestas sed sed risus pretium quam vulputate. Viverra suspendisse potenti nullam 39 | ac tortor vitae purus faucibus ornare. Fringilla urna porttitor rhoncus dolor 40 | purus non. Amet dictum sit amet justo donec enim. 41 | 42 | Mattis ullamcorper velit sed ullamcorper morbi tincidunt. Tortor posuere ac ut 43 | consequat semper viverra. Tellus mauris a diam maecenas sed enim ut sem viverra. 44 | Venenatis urna cursus eget nunc scelerisque viverra mauris in. Arcu ac tortor 45 | dignissim convallis aenean et tortor at. Curabitur gravida arcu ac tortor 46 | dignissim convallis aenean et tortor. Egestas tellus rutrum tellus pellentesque 47 | eu. Fusce ut placerat orci nulla pellentesque dignissim enim sit amet. Ut enim 48 | blandit volutpat maecenas volutpat blandit aliquam etiam. Id donec ultrices 49 | tincidunt arcu. Id cursus metus aliquam eleifend mi. 50 | 51 | Tempus quam pellentesque nec nam aliquam sem. Risus at ultrices mi tempus 52 | imperdiet. Id porta nibh venenatis cras sed felis eget velit. Ipsum a arcu 53 | cursus vitae. Facilisis magna etiam tempor orci eu lobortis elementum. Tincidunt 54 | dui ut ornare lectus sit. Quisque non tellus orci ac. Blandit libero volutpat 55 | sed cras. Nec tincidunt praesent semper feugiat nibh sed pulvinar proin gravida. 56 | Egestas integer eget aliquet nibh praesent tristique magna. 57 | -------------------------------------------------------------------------------- /src/content/blog/post3.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Demo Post 3" 3 | description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua." 4 | pubDate: "Sep 12 2022" 5 | heroImage: "/post_img.webp" 6 | badge: "Demo badge" 7 | tags: ["rust","tokio"] 8 | --- 9 | 10 | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor 11 | incididunt ut labore et dolore magna aliqua. Vitae ultricies leo integer 12 | malesuada nunc vel risus commodo viverra. Adipiscing enim eu turpis egestas 13 | pretium. Euismod elementum nisi quis eleifend quam adipiscing. In hac habitasse 14 | platea dictumst vestibulum. Sagittis purus sit amet volutpat. Netus et malesuada 15 | fames ac turpis egestas. Eget magna fermentum iaculis eu non diam phasellus 16 | vestibulum lorem. Varius sit amet mattis vulputate enim. Habitasse platea 17 | dictumst quisque sagittis. Integer quis auctor elit sed vulputate mi. Dictumst 18 | quisque sagittis purus sit amet. 19 | 20 | Morbi tristique senectus et netus. Id semper risus in hendrerit gravida rutrum 21 | quisque non tellus. Habitasse platea dictumst quisque sagittis purus sit amet. 22 | Tellus molestie nunc non blandit massa. Cursus vitae congue mauris rhoncus. 23 | Accumsan tortor posuere ac ut. Fringilla urna porttitor rhoncus dolor. Elit 24 | ullamcorper dignissim cras tincidunt lobortis. In cursus turpis massa tincidunt 25 | dui ut ornare lectus. Integer feugiat scelerisque varius morbi enim nunc. 26 | Bibendum neque egestas congue quisque egestas diam. Cras ornare arcu dui vivamus 27 | arcu felis bibendum. Dignissim suspendisse in est ante in nibh mauris. Sed 28 | tempus urna et pharetra pharetra massa massa ultricies mi. 29 | 30 | Mollis nunc sed id semper risus in. Convallis a cras semper auctor neque. Diam 31 | sit amet nisl suscipit. Lacus viverra vitae congue eu consequat ac felis donec. 32 | Egestas integer eget aliquet nibh praesent tristique magna sit amet. Eget magna 33 | fermentum iaculis eu non diam. In vitae turpis massa sed elementum. Tristique et 34 | egestas quis ipsum suspendisse ultrices. Eget lorem dolor sed viverra ipsum. Vel 35 | turpis nunc eget lorem dolor sed viverra. Posuere ac ut consequat semper viverra 36 | nam. Laoreet suspendisse interdum consectetur libero id faucibus. Diam phasellus 37 | vestibulum lorem sed risus ultricies tristique. Rhoncus dolor purus non enim 38 | praesent elementum facilisis. Ultrices tincidunt arcu non sodales neque. Tempus 39 | egestas sed sed risus pretium quam vulputate. Viverra suspendisse potenti nullam 40 | ac tortor vitae purus faucibus ornare. Fringilla urna porttitor rhoncus dolor 41 | purus non. Amet dictum sit amet justo donec enim. 42 | 43 | Mattis ullamcorper velit sed ullamcorper morbi tincidunt. Tortor posuere ac ut 44 | consequat semper viverra. Tellus mauris a diam maecenas sed enim ut sem viverra. 45 | Venenatis urna cursus eget nunc scelerisque viverra mauris in. Arcu ac tortor 46 | dignissim convallis aenean et tortor at. Curabitur gravida arcu ac tortor 47 | dignissim convallis aenean et tortor. Egestas tellus rutrum tellus pellentesque 48 | eu. Fusce ut placerat orci nulla pellentesque dignissim enim sit amet. Ut enim 49 | blandit volutpat maecenas volutpat blandit aliquam etiam. Id donec ultrices 50 | tincidunt arcu. Id cursus metus aliquam eleifend mi. 51 | 52 | Tempus quam pellentesque nec nam aliquam sem. Risus at ultrices mi tempus 53 | imperdiet. Id porta nibh venenatis cras sed felis eget velit. Ipsum a arcu 54 | cursus vitae. Facilisis magna etiam tempor orci eu lobortis elementum. Tincidunt 55 | dui ut ornare lectus sit. Quisque non tellus orci ac. Blandit libero volutpat 56 | sed cras. Nec tincidunt praesent semper feugiat nibh sed pulvinar proin gravida. 57 | Egestas integer eget aliquet nibh praesent tristique magna. 58 | -------------------------------------------------------------------------------- /src/pages/cv.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import BaseLayout from "../layouts/BaseLayout.astro"; 3 | import TimeLineElement from "../components/cv/TimeLine.astro"; 4 | --- 5 | 6 | 7 |
8 |
Profile
9 |
10 | 11 |
12 | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna 13 | aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis 14 | aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat 15 | cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. 16 |
17 | 18 |
19 |
Education
20 |
21 | 22 |
23 | 27 | 31 |
32 | 33 |
34 |
Experience
35 |
36 | 37 |
38 | 42 | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident. 43 | 44 | 48 | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident. 49 | 50 | 54 | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident. 55 | 56 |
57 | 58 |
59 |
Certifications
60 |
61 | 62 | 70 | 71 |
72 |
Skills
73 |
74 | 75 |
    76 |
  • Skill Name
  • 77 |
  • Skill Name
  • 78 |
  • Skill Name
  • 79 |
  • Skill Name
  • 80 |
  • Skill Name
  • 81 |
  • Skill Name
  • 82 |
  • Skill Name
  • 83 |
  • Skill Name
  • 84 |
  • Skill Name
  • 85 |
  • Skill Name
  • 86 |
  • Skill Name
  • 87 |
  • Skill Name
  • 88 |
  • Skill Name
  • 89 |
  • Skill Name
  • 90 |
  • Skill Name
  • 91 |
92 |
93 | -------------------------------------------------------------------------------- /src/components/SideBarFooter.astro: -------------------------------------------------------------------------------- 1 |
4 |
5 | 6 | 85 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Astrofy | Personal Portfolio Website Template 2 | 3 | ![Astrofy | Personal Porfolio Website Template](public/social_img.webp) 4 | 5 | Astrofy is a free and open-source template for your Personal Portfolio Website built with Astro and TailwindCSS. Create in minutes a website with a Blog, CV, Project Section, Store, and RSS Feed. 6 | 7 | ## Demo 8 | 9 | View a live demo of [Astrofy](https://astrofy-template.netlify.app/) 10 | 11 | ## Installation 12 | 13 | Run the following command in your terminal 14 | 15 | ```bash 16 | pnpm install 17 | ``` 18 | 19 | Once the packages are installed you are ready to run astro. Astro comes with a built-in development server that has everything you need for project development. The astro dev command will start the local development server so that you can see your new website in action for the very first time. 20 | 21 | ```bash 22 | pnpm run dev 23 | ``` 24 | 25 | ## Tech Stack 26 | 27 | - [Astro](https://astro.build) 28 | - [tailwindcss](https://tailwindcss.com/) 29 | - [DaisyUI](https://daisyui.com/) 30 | 31 | ## Project Structure 32 | 33 | ```php 34 | ├── src/ 35 | │ ├── components/ 36 | │ │ ├── cv/ 37 | │ │ │ ├── TimeLine 38 | │ │ ├── BaseHead.astro 39 | │ │ ├── Card.astro 40 | │ │ ├── Footer.astro 41 | │ │ ├── Header.astro 42 | │ │ └── HorizontalCard.astro 43 | │ │ └── SideBar.astro 44 | │ │ └── SideBarMenu.astro 45 | │ │ └── SideBarFooter.astro 46 | │ ├── content/ 47 | │ │ ├── blog/ 48 | │ │ │ ├── post1.md 49 | │ │ │ ├── post2.md 50 | │ │ │ └── post3.md 51 | │ │ ├── store/ 52 | │ │ │ ├── item1.md 53 | │ │ │ ├── item2.md 54 | │ ├── layouts/ 55 | │ │ └── BaseLayout.astro 56 | │ │ └── PostLayout.astro 57 | │ └── pages/ 58 | │ │ ├── blog/ 59 | │ │ │ ├── [...page].astro 60 | │ │ │ ├── [slug].astro 61 | │ │ └── cv.astro 62 | │ │ └── index.astro 63 | │ │ └── projects.astro 64 | │ │ └── rss.xml.js 65 | │ ├── styles/ 66 | │ │ └── global.css 67 | │ └── config.ts 68 | ├── public/ 69 | │ ├── favicon.svg 70 | │ └── profile.webp 71 | │ └── social_img.webp 72 | ├── astro.config.mjs 73 | ├── tailwind.config.cjs 74 | ├── package.json 75 | └── tsconfig.json 76 | ``` 77 | 78 | ### Site config 79 | 80 | You can change global site configuration on '/src/config.ts' file: 81 | 82 | - **SITE_TITLE**: Default pages title. 83 | - **SITE_DESCRIPTION**: Default pages title. 84 | - **GENERATE_SLUG_FROM_TITLE**: By default Astrofy will generate the blog slug pages base on the article name. Set this var to false if you want to use the Astro file base (Compatible with Astrofy older versions). 85 | - **TRANSITION_API**: Enable and disable transition API 86 | 87 | ### Components usage 88 | 89 | #### Layout Components 90 | 91 | The `BaseHead`, `Footer`, `Header`, and `SideBar` components are already included in the layout system. To change the website content you can edit the content of these components. 92 | 93 | ##### SideBar 94 | 95 | In the Sidebar you can change your profilePicture, links to all your website pages, and your social icons. 96 | 97 | You can change your avatar shape using [mask classes](https://daisyui.com/components/mask/). 98 | 99 | The used social-icons are SVG form [BoxIcons](https://boxicons.com/) pack. You can replace the icons in the `SideBarFooter` component 100 | 101 | To add a new page in the sidebar go to the `SideBarMenu` component. 102 | 103 | ``` 104 |
  • Home
  • 105 | 106 | ``` 107 | 108 | **Note**: In order to change the sidebar menu's active item, you need to setup the prop `sideBarActiveItemID` in the `BaseLayout` component of your new page and add that id to the link in the `SideBarMenu` 109 | 110 | #### TimeLine 111 | 112 | The timeline components are used to confirm the CV. 113 | 114 | ```html 115 |
    116 | 117 | Content that can contain 118 |
    divs
    119 | and anything else you want. 120 |
    121 | ... 122 |
    123 | ``` 124 | 125 | #### Card & HorizontalCard 126 | 127 | The cards are primarly used for the Project and the Blog components. They include a picture, a title, and a description. 128 | 129 | ```html 130 | 133 | ``` 134 | 135 | #### HorizontalCard Shop Item 136 | 137 | 138 | This component is already included in the Store layout of the template. In case you want to use it in another place these are the props. 139 | 140 | ```html 141 | 154 | ``` 155 | 156 | #### Adding a Custom Component 157 | 158 | To add a custom component, you can create a .astro file in the components folder under the source folder. 159 | 160 | Components must follow this template. The ```---``` represents the code fence and uses Javascript and can be used for imports. 161 | 162 | The HTML component is the actual style of your new component. 163 | 164 | ```html 165 | --- 166 | // Component Script (JavaScript) 167 | --- 168 | 169 | ``` 170 | 171 | For more details, see the [astro components](https://docs.astro.build/en/core-concepts/astro-components/) documentation here. 172 | 173 | ### Layouts 174 | 175 | Include `BaseLayout` in each page you add and `PostLayout` to your post pages. 176 | 177 | The BaseLayout defines a general template for each new webpage you want to add. It imports constants SITE_TITLE and SITE_DESCRIPTION which can be modified in the ```../config``` folder. Data placed there can be imported anywhere using import. 178 | 179 | ### Content 180 | 181 | You can add a [content collection](https://docs.astro.build/en/guides/content-collections/) in `/content/' folder, you will need add it at config.ts. 182 | 183 | #### config.ts 184 | 185 | Where you need to define your content collections, we define our content schemas too. 186 | 187 | #### Blog 188 | 189 | Add your `md` blog post in the `/content/blog/` folder. 190 | 191 | ##### Post format 192 | 193 | Add code with this format in the top of each post file. 194 | 195 | ``` 196 | --- 197 | title: "Post Title" 198 | description: "Description" 199 | pubDate: "Post date format(Sep 10 2022)" 200 | heroImage: "Post Hero Image URL" 201 | --- 202 | ``` 203 | 204 | ### Pages 205 | 206 | #### Blog 207 | 208 | Blog uses Astro's content collection to query post's `md`. 209 | 210 | ##### [page].astro 211 | 212 | The `[page].astro` is the route to work with the paginated post list. You can change there the number of items listed for each page and the pagination button labels. 213 | 214 | ##### [slug].astro 215 | 216 | The `[slug].astro` is the base route for every blog post, you can customize the page layout or behaviour, by default uses `content/blog` for content collection and `PostLayout` as layout. 217 | 218 | #### Shop 219 | 220 | Add your `md` item in the `/pages/shop/` folder. 221 | 222 | ##### [page].astro 223 | 224 | The `[page].astro` is the route to work with the paginated item list. You can change there the number of items listed for each page and the pagination button labels. The shop will render all `.md` files you include inside this folder. 225 | 226 | ##### Item format 227 | 228 | Add code with this format at the top of each item file. 229 | 230 | ```js 231 | --- 232 | title: "Demo Item 1" 233 | description: "Item description" 234 | heroImage: "Item img url" 235 | details: true // show or hide details btn 236 | custom_link_label: "Custom btn link label" 237 | custom_link: "Custom btn link" 238 | pubDate: "Sep 15 2022" 239 | pricing: "$15" 240 | oldPricing: "$25.5" 241 | badge: "Featured" 242 | checkoutUrl: "https://checkouturl.com/" 243 | --- 244 | ``` 245 | 246 | #### Static pages 247 | 248 | The other pages included in the template are static pages. The `index` page belongs to the root page. You can add your pages directly in the `/pages` folder and then add a link to those pages in the `sidebar` component. 249 | 250 | Feel free to modify the content included in the pages that the template contains or add the ones you need. 251 | 252 | ### Theming 253 | 254 | To change the template theme change the `data-theme` attribute of the `` tag in `BaseLayout.astro` file. 255 | 256 | You can choose among 30 themes available or create your custom theme. See themes available [here](https://daisyui.com/docs/themes/). 257 | 258 | ## Sitemap 259 | 260 | The Sitemap is generated automatically when you build your website in the root of the domain. Please update the `robots.txt` file in the public folder with your site name URL for the Sitemap. 261 | 262 | ## Deploy 263 | 264 | You can deploy your site on your favourite static hosting service such as Vercel, Netlify, GitHub Pages, etc. 265 | 266 | The configuration for the deployment varies depending on the platform where you are going to do it. See the [official Astro information](https://docs.astro.build/en/guides/deploy/) to deploy your website. 267 | 268 | > **⚠️ CAUTION**
    269 | > The Blog pagination of this template is implemented using dynamic route parameters in its filename and for now this format is incompatible with SSR deploy configs, so please use the default static deploy options for your deployments. 270 | 271 | ## Contributing 272 | 273 | Suggestions and pull requests are welcomed! Feel free to open a discussion or an issue for a new feature request or bug. 274 | 275 | One of the best ways to contribute is to grab a [bug report or feature suggestion](https://github.com/manuelernestog/astrofy/issues) that has been marked `accepted` and dig in. 276 | 277 | Please be wary of working on issues _not_ marked as `accepted`. Just because someone has created an issue doesn't mean we'll accept a pull request for it. 278 | 279 | ## License 280 | 281 | Astrofy is licensed under the MIT license — see the [LICENSE](https://github.com/manuelernestog/astrofy/blob/main/LICENSE) file for details. 282 | 283 | ## Contributors 284 | 285 | 286 | 287 | 288 | 289 | Made with [contrib.rocks](https://contrib.rocks). 290 | --------------------------------------------------------------------------------