mirror of https://github.com/gabehf/mnrva.dev.git
commit
2b72c1295f
@ -0,0 +1,44 @@
|
||||
{
|
||||
"files": [
|
||||
"README.md"
|
||||
],
|
||||
"imageSize": 100,
|
||||
"commit": false,
|
||||
"commitType": "docs",
|
||||
"commitConvention": "angular",
|
||||
"contributors": [
|
||||
{
|
||||
"login": "SterbenVD",
|
||||
"name": "Vishal Vijay Devadiga",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/90999906?v=4",
|
||||
"profile": "https://github.com/SterbenVD",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "khushChopra",
|
||||
"name": "Khush Chopra",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/43996455?v=4",
|
||||
"profile": "https://github.com/khushChopra",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "javadshoja",
|
||||
"name": "Javad Shoja",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/57140027?v=4",
|
||||
"profile": "http://jbrave.ir",
|
||||
"contributions": [
|
||||
"maintenance"
|
||||
]
|
||||
}
|
||||
],
|
||||
"contributorsPerLine": 7,
|
||||
"skipCi": true,
|
||||
"repoType": "github",
|
||||
"repoHost": "https://github.com",
|
||||
"projectName": "astro-portfolio-template",
|
||||
"projectOwner": "MaeWolff"
|
||||
}
|
||||
@ -0,0 +1,14 @@
|
||||
module.exports = {
|
||||
extends: ["plugin:astro/recommended"],
|
||||
overrides: [
|
||||
{
|
||||
files: ["*.astro"],
|
||||
parser: "astro-eslint-parser",
|
||||
parserOptions: {
|
||||
parser: "@typescript-eslint/parser",
|
||||
extraFileExtensions: [".astro"],
|
||||
},
|
||||
rules: {},
|
||||
},
|
||||
],
|
||||
};
|
||||
@ -0,0 +1,17 @@
|
||||
name: CI
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
check-astro:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: checks
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18.14.1
|
||||
cache: "npm"
|
||||
- run: npm install
|
||||
- run: npm run check
|
||||
@ -0,0 +1,21 @@
|
||||
# build output
|
||||
dist/
|
||||
|
||||
# generated types
|
||||
.astro/
|
||||
|
||||
# dependencies
|
||||
node_modules/
|
||||
|
||||
# logs
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
|
||||
# environment variables
|
||||
.env
|
||||
.env.production
|
||||
|
||||
# macOS-specific files
|
||||
.DS_Store
|
||||
@ -0,0 +1,14 @@
|
||||
module.exports = {
|
||||
plugins: [
|
||||
require.resolve("prettier-plugin-tailwindcss", "prettier-plugin-astro"),
|
||||
],
|
||||
tailwindConfig: "./tailwind.config.js",
|
||||
overrides: [
|
||||
{
|
||||
files: "*.astro",
|
||||
options: {
|
||||
parser: "astro",
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
@ -0,0 +1,4 @@
|
||||
{
|
||||
"recommendations": ["astro-build.astro-vscode"],
|
||||
"unwantedRecommendations": []
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"command": "./node_modules/.bin/astro dev",
|
||||
"name": "Development server",
|
||||
"request": "launch",
|
||||
"type": "node-terminal"
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2023 Maxence WOLFF
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@ -0,0 +1,54 @@
|
||||
# 👨🚀 Astro - Portfolio Template
|
||||
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
|
||||
[](#contributors-)
|
||||
<!-- ALL-CONTRIBUTORS-BADGE:END -->
|
||||
|
||||

|
||||
|
||||
This theme/template is designed and crafted by [me](https://www.maxencewolff.com).
|
||||
NB: Additional color themes can also be configured on the `src/data/theme.ts` file.
|
||||
|
||||
## 🥷 Usage
|
||||
|
||||
- You can modify all the information in the files in the `data` folder (presentation, social links, projects list, colors).
|
||||
- You can write articles in `markdown` format in the `content/posts` folder.
|
||||
|
||||
## 🧞 Commands
|
||||
|
||||
All commands are run from the root of the project, from a terminal:
|
||||
|
||||
| Command | Action |
|
||||
| :------------------------ | :----------------------------------------------- |
|
||||
| `npm install` | Installs dependencies |
|
||||
| `npm run dev` | Starts local dev server at `localhost:4321` |
|
||||
| `npm run build` | Build your production site to `./dist/` |
|
||||
| `npm run preview` | Preview your build locally, before deploying |
|
||||
| `npm run astro ...` | Run CLI commands like `astro add`, `astro check` |
|
||||
| `npm run astro -- --help` | Get help using the Astro CLI |
|
||||
|
||||
## Contributors ✨
|
||||
|
||||
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
|
||||
<!-- prettier-ignore-start -->
|
||||
<!-- markdownlint-disable -->
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/SterbenVD"><img src="https://avatars.githubusercontent.com/u/90999906?v=4?s=100" width="100px;" alt="Vishal Vijay Devadiga"/><br /><sub><b>Vishal Vijay Devadiga</b></sub></a><br /><a href="https://github.com/MaeWolff/astro-portfolio-template/commits?author=SterbenVD" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/khushChopra"><img src="https://avatars.githubusercontent.com/u/43996455?v=4?s=100" width="100px;" alt="Khush Chopra"/><br /><sub><b>Khush Chopra</b></sub></a><br /><a href="https://github.com/MaeWolff/astro-portfolio-template/commits?author=khushChopra" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="http://jbrave.ir"><img src="https://avatars.githubusercontent.com/u/57140027?v=4?s=100" width="100px;" alt="Javad Shoja"/><br /><sub><b>Javad Shoja</b></sub></a><br /><a href="#maintenance-javadshoja" title="Maintenance">🚧</a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- markdownlint-restore -->
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
<!-- ALL-CONTRIBUTORS-LIST:END -->
|
||||
<!-- prettier-ignore-start -->
|
||||
<!-- markdownlint-disable -->
|
||||
|
||||
<!-- markdownlint-restore -->
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
<!-- ALL-CONTRIBUTORS-LIST:END -->
|
||||
@ -0,0 +1,19 @@
|
||||
import { defineConfig } from "astro/config";
|
||||
import tailwind from "@astrojs/tailwind";
|
||||
import sitemap from "@astrojs/sitemap";
|
||||
import robotsTxt from "astro-robots-txt";
|
||||
import { SITE_URL } from "./src/data/config";
|
||||
|
||||
|
||||
// https://astro.build/config
|
||||
export default defineConfig({
|
||||
integrations: [tailwind(), sitemap(), robotsTxt()],
|
||||
site: SITE_URL,
|
||||
markdown: {
|
||||
syntaxHighlight: "shiki",
|
||||
shikiConfig: {
|
||||
theme: "nord",
|
||||
wrap: false
|
||||
}
|
||||
}
|
||||
});
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,30 @@
|
||||
{
|
||||
"name": "astro-template-portfolio",
|
||||
"type": "module",
|
||||
"version": "0.0.1",
|
||||
"scripts": {
|
||||
"dev": "astro dev",
|
||||
"start": "astro dev",
|
||||
"build": "astro build",
|
||||
"preview": "astro preview",
|
||||
"check": "astro check",
|
||||
"astro": "astro"
|
||||
},
|
||||
"dependencies": {
|
||||
"@astrojs/sitemap": "^3.0.0",
|
||||
"@astrojs/tailwind": "^5.0.0",
|
||||
"@fontsource/open-sans": "^5.0.12",
|
||||
"astro": "^3.1.0",
|
||||
"astro-robots-txt": "^1.0.0",
|
||||
"astro-seo": "0.8.0",
|
||||
"tailwindcss": "^3.3.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@typescript-eslint/parser": "5.59.7",
|
||||
"eslint": "8.41.0",
|
||||
"eslint-plugin-astro": "0.27.1",
|
||||
"prettier": "2.8.8",
|
||||
"prettier-plugin-astro": "0.9.0",
|
||||
"prettier-plugin-tailwindcss": "0.3.0"
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 749 B |
|
After Width: | Height: | Size: 159 KiB |
|
After Width: | Height: | Size: 8.0 KiB |
@ -0,0 +1,36 @@
|
||||
---
|
||||
import removeTrailingSlash from "@/utils/removeTrailingSlash";
|
||||
import presentation from "@/data/presentation";
|
||||
|
||||
const pathname = removeTrailingSlash(Astro.url.pathname);
|
||||
---
|
||||
|
||||
<header class="z-40 flex w-full flex-col gap-2 md:flex-row md:justify-between">
|
||||
<a href={`mailto:${presentation.mail}`} class="hover:text-neutral-100"
|
||||
>{presentation.mail}</a
|
||||
>
|
||||
|
||||
<nav role="navigation">
|
||||
<ul role="list" class="flex flex-row gap-2">
|
||||
<li>
|
||||
<a
|
||||
href="/"
|
||||
class:list={{
|
||||
["hover:text-neutral-100"]: true,
|
||||
["text-neutral-100"]: pathname === "/",
|
||||
}}>Home</a
|
||||
>
|
||||
</li>
|
||||
<li>/</li>
|
||||
<li>
|
||||
<a
|
||||
href="/posts"
|
||||
class:list={{
|
||||
["hover:text-neutral-100"]: true,
|
||||
["text-neutral-100"]: pathname === "/posts",
|
||||
}}>Posts</a
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</header>
|
||||
@ -0,0 +1,49 @@
|
||||
---
|
||||
import formatDate from "@/utils/formatDate";
|
||||
|
||||
type Props = {
|
||||
title: string;
|
||||
publishedAt: Date;
|
||||
description: string;
|
||||
slug: string;
|
||||
};
|
||||
|
||||
const { title, publishedAt, description, slug } = Astro.props;
|
||||
---
|
||||
|
||||
<a
|
||||
class="group flex max-w-sm cursor-pointer flex-col gap-2 rounded-md border border-neutral-700 p-4 transition-all duration-300 hover:-translate-y-2 hover:border-neutral-400"
|
||||
href={`/posts/${slug}`}
|
||||
>
|
||||
<div
|
||||
class="flex w-full flex-col justify-between gap-2 md:flex-row md:items-center"
|
||||
>
|
||||
<p class="text-neutral-100">{title}</p>
|
||||
<div class="flex flex-row items-center gap-4">
|
||||
<p>{formatDate(publishedAt)}</p>
|
||||
|
||||
<svg
|
||||
width="18"
|
||||
height="18"
|
||||
viewBox="0 0 18 18"
|
||||
fill="none"
|
||||
class="transition-all duration-300 group-hover:translate-x-1"
|
||||
>
|
||||
<path
|
||||
d="M5.25 12.75L12.75 5.25"
|
||||
stroke="#999999"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"></path>
|
||||
<path
|
||||
d="M5.25 5.25H12.75V12.75"
|
||||
stroke="#999999"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"></path>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p class="truncate">
|
||||
{description}
|
||||
</p>
|
||||
</a>
|
||||
@ -0,0 +1,62 @@
|
||||
---
|
||||
import type { Project } from "@/data/projects";
|
||||
|
||||
type Props = Project;
|
||||
|
||||
const { title, techs, link, isComingSoon } = Astro.props;
|
||||
|
||||
const formatTechs = (values: string[]) =>
|
||||
values.toString().replaceAll(",", " • ");
|
||||
---
|
||||
|
||||
<>
|
||||
{
|
||||
isComingSoon && (
|
||||
<div class="t group flex w-full flex-col justify-between gap-2 rounded-md border border-neutral-700 p-4 md:flex-row md:items-center">
|
||||
<div class="flex flex-col gap-2 md:flex-row md:items-center md:gap-4">
|
||||
<p class="text-neutral-100">{title}</p>
|
||||
<p>{formatTechs(techs)}</p>
|
||||
</div>
|
||||
|
||||
<p class="w-fit rounded-md bg-neutral-900 px-4 py-1">Soon</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
{
|
||||
!isComingSoon && (
|
||||
<a
|
||||
class="group flex w-full cursor-pointer flex-col justify-between gap-2 rounded-md border border-neutral-700 p-4 transition-all duration-300 hover:-translate-y-2 hover:border-neutral-400 md:flex-row md:items-center"
|
||||
href={link}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
<div class="flex flex-col gap-4 md:flex-row md:items-center">
|
||||
<p class="text-neutral-100">{title}</p>
|
||||
<p>{formatTechs(techs)}</p>
|
||||
</div>
|
||||
|
||||
<svg
|
||||
width="18"
|
||||
height="18"
|
||||
viewBox="0 0 18 18"
|
||||
fill="none"
|
||||
class="transition-all duration-300 group-hover:translate-x-1"
|
||||
>
|
||||
<path
|
||||
d="M5.25 12.75L12.75 5.25"
|
||||
stroke="#999999"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M5.25 5.25H12.75V12.75"
|
||||
stroke="#999999"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
</a>
|
||||
)
|
||||
}
|
||||
</>
|
||||
@ -0,0 +1,18 @@
|
||||
---
|
||||
import Link from "./shared/Link.astro";
|
||||
import presentation from "@/data/presentation";
|
||||
---
|
||||
|
||||
<ul role="list" class="flex flex-row gap-2">
|
||||
{
|
||||
presentation.socials.map((social, index) => (
|
||||
<>
|
||||
<li>
|
||||
<Link href={social.link} label={social.label} />
|
||||
</li>
|
||||
|
||||
{presentation.socials.length - 1 !== index && <li>/</li>}
|
||||
</>
|
||||
))
|
||||
}
|
||||
</ul>
|
||||
@ -0,0 +1,63 @@
|
||||
---
|
||||
import { SEO } from "astro-seo";
|
||||
import { SITE_URL } from "@/data/config";
|
||||
import type { HeadTags } from "@/utils/types/HeadTags";
|
||||
|
||||
type Props = HeadTags;
|
||||
|
||||
const { title, description, noindex, og } = Astro.props;
|
||||
|
||||
const DEFAULT_TITLE_PAGE = "Astro - Portfolio template";
|
||||
const DEFAULT_DESCRIPTION_PAGE =
|
||||
"A minimal portfolio template built with Astro and Tailwindcss.";
|
||||
const DEFAULT_URL_SITE = SITE_URL;
|
||||
|
||||
const openGraph = {
|
||||
title: title || og?.title || DEFAULT_TITLE_PAGE,
|
||||
type: og?.type || "website",
|
||||
image: og?.image || "/opengraph-image.jpg",
|
||||
alt: og?.alt || "astro portfolio template image",
|
||||
url: DEFAULT_URL_SITE,
|
||||
description: og?.description || DEFAULT_DESCRIPTION_PAGE,
|
||||
};
|
||||
---
|
||||
|
||||
<head>
|
||||
<SEO
|
||||
charset="UTF-8"
|
||||
title={title || DEFAULT_TITLE_PAGE}
|
||||
description={description || DEFAULT_DESCRIPTION_PAGE}
|
||||
noindex={noindex || false}
|
||||
openGraph={{
|
||||
basic: {
|
||||
title: openGraph.title,
|
||||
type: openGraph.type,
|
||||
image: openGraph.image,
|
||||
},
|
||||
image: {
|
||||
alt: openGraph.alt,
|
||||
},
|
||||
}}
|
||||
twitter={{
|
||||
creator: "@itsstormzz_",
|
||||
}}
|
||||
extend={{
|
||||
link: [
|
||||
{ rel: "icon", href: "/favicon.svg" },
|
||||
{ rel: "sitemap", href: "/sitemap-index.xml" },
|
||||
],
|
||||
meta: [
|
||||
{ name: "viewport", content: "width=device-width, initial-scale=1" },
|
||||
{ name: "generator", content: Astro.generator },
|
||||
{
|
||||
name: "twitter:image",
|
||||
content: openGraph.image,
|
||||
},
|
||||
{ name: "twitter:card", content: "summary_large_image" },
|
||||
{ name: "twitter:title", content: openGraph.title },
|
||||
{ name: "twitter:description", content: openGraph.description },
|
||||
{ name: "twitter:site", content: "@itsstormzz_" },
|
||||
],
|
||||
}}
|
||||
/>
|
||||
</head>
|
||||
@ -0,0 +1,20 @@
|
||||
---
|
||||
import type { TailwindColor } from "@/utils/types/tailwind";
|
||||
import { MAP_COLOR_VARIANT_TO_BG } from "@/utils/mapVariants";
|
||||
|
||||
type Props = {
|
||||
position: "bottom" | "top";
|
||||
color: TailwindColor;
|
||||
};
|
||||
|
||||
const { position, color } = Astro.props;
|
||||
---
|
||||
|
||||
<div
|
||||
class:list={{
|
||||
[`fixed z-0 h-[134px] w-[134px] lg:w-[300px] lg:h-[300px] rounded-full ${MAP_COLOR_VARIANT_TO_BG[color]} blur-[150px] md:blur-[350px] opacity-50`]: true,
|
||||
["left-0 top-0"]: position === "top",
|
||||
["right-0 bottom-0"]: position === "bottom",
|
||||
}}
|
||||
>
|
||||
</div>
|
||||
@ -0,0 +1,24 @@
|
||||
---
|
||||
import type { HTMLAttributes } from "astro/types";
|
||||
|
||||
type Props = HTMLAttributes<"a"> & {
|
||||
label: string;
|
||||
isUnderline?: boolean;
|
||||
};
|
||||
|
||||
const { label, isUnderline, ...props } = Astro.props;
|
||||
---
|
||||
|
||||
<a
|
||||
href={props.href}
|
||||
class:list={{
|
||||
["hover:text-neutral-100 cursor-pointer"]: true,
|
||||
["underline decoration-dashed underline-offset-8"]: isUnderline,
|
||||
}}
|
||||
{...props}
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
{label}
|
||||
<span class="sr-only">{label} link</span>
|
||||
</a>
|
||||
@ -0,0 +1,14 @@
|
||||
import { defineCollection, z } from "astro:content";
|
||||
|
||||
const postsCollection = defineCollection({
|
||||
type: "content",
|
||||
schema: z.object({
|
||||
title: z.string(),
|
||||
publishedAt: z.date(),
|
||||
description: z.string(),
|
||||
isPublish: z.boolean(),
|
||||
isDraft: z.boolean().default(false),
|
||||
}),
|
||||
});
|
||||
|
||||
export const collections = { posts: postsCollection };
|
||||
@ -0,0 +1,54 @@
|
||||
---
|
||||
title: "The Power Of React Hooks"
|
||||
publishedAt: 2023-05-24
|
||||
description: "Lorem ipsum dolor sit amet consectetur et ultrices blandit neque ege"
|
||||
slug: "the-power-of-react-hooks"
|
||||
isPublish: true
|
||||
---
|
||||
|
||||
## Vocesque meum remis est neque Neptunus monte
|
||||
|
||||
Lorem markdownum nunc _adfuit_ fecisse, `quae pectus`, quod seu mortale suo
|
||||
Minerva iussit obortas. Favilla victa; alarum signis barbara, nec _sibi dentes_
|
||||
hostes?
|
||||
|
||||
## Corporibus Leucon
|
||||
|
||||
Quaeque viridis, pariter possit. Velatus Thetis, ab Buten, in et ite positis
|
||||
annis ut Troasque altaque. Ancaeus convertit conscia Phinea petis. Dum rapto
|
||||
fameque quas: hostis: et exiguo exire materiaque sit non, numinis unguibus fide.
|
||||
Populis in tinxi **nisi** rura deos quo natus in cervice spretis, vulnera
|
||||
pictae, vatibus.
|
||||
|
||||
> Illi tenebras si vultum suae. Matrem iam: iniqua adire, tetigere meque,
|
||||
> cessant, gerebat.
|
||||
|
||||
## Montes ignarus precor rogabam primus ridet sanguine
|
||||
|
||||
In vir indefessus et patrios veniam. Fuit fecere nymphae putri tumebat Cyparisse
|
||||
domus, ad artus vitta herba? Et gaudet pressum aeterna animam. Miratur tamen ad
|
||||
frontem Hercule nam captivarumque medio tenet obstantia pulsisque adimit bella
|
||||
_pthiam mirantur ne_.
|
||||
|
||||
> Lacertis et nomenque oracla exstabat: genitor nitor! Fluctus habes extinctum.
|
||||
> Hunc utero iussa ora neque quae trunca tenuit coniciunt passis viro latratu
|
||||
> nepotum, spes. Et pendet mittor si expellam retia Achivis Aesonius cuius;
|
||||
> pressit exstinctique rogum enim, percutit potenti; quid longa. Nostra animaque
|
||||
> genetrice viae, quam virus sermone in videri.
|
||||
|
||||
## Rapit harundine vana
|
||||
|
||||
Noctis et et carpis corpus amplexus; imagine indignanda pedum sospes; cornua
|
||||
super **et simus**. Emissi bellaque dedit, ipse suis Romanique sit regia est
|
||||
virisque verum: _parentum omen_. Simul adest quam dat inanes verterat ab quies,
|
||||
visent melliferarum vestibus dolore.
|
||||
|
||||
Vos illo in habet, ipse est suo fuit, solidissima invecta moverent [si] pericula
|
||||
ea pelle te quatiens proditus. Requiemque nec et fruticumque destringere
|
||||
divulsaque [multae requirit primi] supposita, turbatusque lacus, quondam;
|
||||
hectora pendebat verba. Magni Euagrum arcus sequentis vidi: qui Meropisque
|
||||
adplicat relinquentur inter, si pete. Magna constitit ore rediit et parentis
|
||||
pomaria lumina seque aura.
|
||||
|
||||
[multae requirit primi]: http://heu.io/
|
||||
[si]: http://infelixlucina.net/mutati
|
||||
@ -0,0 +1,9 @@
|
||||
---
|
||||
title: "Untitled"
|
||||
publishedAt: 2023-05-24
|
||||
description: "Lorem ipsum dolor sit amet consectetur et ultrices blandit neque ege"
|
||||
slug: "untitled"
|
||||
isPublish: true
|
||||
---
|
||||
|
||||
## Hello World
|
||||
@ -0,0 +1 @@
|
||||
export const SITE_URL = "https://demo.maxencewolff.com/";
|
||||
@ -0,0 +1,27 @@
|
||||
export type Project = {
|
||||
title: string;
|
||||
techs: string[];
|
||||
link: string;
|
||||
isComingSoon?: boolean;
|
||||
};
|
||||
|
||||
const projects: Project[] = [
|
||||
{
|
||||
title: "Dictionary App",
|
||||
techs: ["ReactJS (NextJS)", "react-query", "zod"],
|
||||
link: "https://github.com/MaeWolff/dictionary-app",
|
||||
},
|
||||
{
|
||||
title: "Portfolio / Lina BLIDI",
|
||||
techs: ["ReactJS (NextJS)", "TypeScript"],
|
||||
link: "https://www.linablidi.fr/",
|
||||
},
|
||||
{
|
||||
title: "Portfolio / Template",
|
||||
techs: ["Astro"],
|
||||
link: "/",
|
||||
isComingSoon: true,
|
||||
},
|
||||
];
|
||||
|
||||
export default projects;
|
||||
@ -0,0 +1,23 @@
|
||||
import type { TailwindColor } from "@/utils/types/tailwind";
|
||||
|
||||
type Theme = {
|
||||
colors: {
|
||||
primary: TailwindColor;
|
||||
blur: {
|
||||
top: TailwindColor;
|
||||
bottom: TailwindColor;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
const theme: Theme = {
|
||||
colors: {
|
||||
primary: "orange",
|
||||
blur: {
|
||||
top: "orange",
|
||||
bottom: "violet",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default theme;
|
||||
@ -0,0 +1,2 @@
|
||||
/// <reference path="../.astro/types.d.ts" />
|
||||
/// <reference types="astro/client" />
|
||||
@ -0,0 +1,34 @@
|
||||
---
|
||||
import Header from "../components/Header.astro";
|
||||
import BlurCircle from "@/components/shared/BlurCircle.astro";
|
||||
import theme from "@/data/theme";
|
||||
import SEOTags from "@/components/seo/SEOTags.astro";
|
||||
import type { HeadTags } from "@/utils/types/HeadTags";
|
||||
|
||||
import "@fontsource/open-sans";
|
||||
import "@/styles/tailwind.css";
|
||||
import "@/styles/post.css";
|
||||
|
||||
export type Props = HeadTags;
|
||||
|
||||
const headTags = Astro.props;
|
||||
---
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<SEOTags {...headTags} />
|
||||
|
||||
<body
|
||||
class="mx-auto flex min-h-screen max-w-[872px] flex-col gap-9 bg-neutral-950 px-10 py-8 text-sm text-neutral-400 md:gap-20 md:py-16"
|
||||
>
|
||||
<Header />
|
||||
<BlurCircle position="top" color={theme.colors.blur.top} />
|
||||
<BlurCircle position="bottom" color={theme.colors.blur.bottom} />
|
||||
<slot />
|
||||
<style is:global>
|
||||
html {
|
||||
font-family: "Open Sans";
|
||||
}
|
||||
</style>
|
||||
</body>
|
||||
</html>
|
||||
@ -0,0 +1,105 @@
|
||||
---
|
||||
import { getCollection } from "astro:content";
|
||||
import { Image } from "astro:assets"
|
||||
|
||||
import Layout from "@/layouts/Layout.astro";
|
||||
import SocialLinks from "@/components/SocialLinks.astro";
|
||||
import PostCard from "@/components/PostCard.astro";
|
||||
import ProjectCard from "@/components/ProjectCard.astro";
|
||||
import Link from "@/components/shared/Link.astro";
|
||||
import convertAsteriskToStrongTag from "@/utils/convertAsteriskToStrongTag";
|
||||
|
||||
import presentation from "@/data/presentation";
|
||||
import projects from "@/data/projects";
|
||||
|
||||
const posts = (await getCollection("posts")).sort(function (first, second) {
|
||||
return second.data.publishedAt.getTime() - first.data.publishedAt.getTime();
|
||||
});
|
||||
---
|
||||
|
||||
<Layout>
|
||||
<main class="flex flex-col gap-20">
|
||||
<article
|
||||
class="flex flex-col gap-8 md:flex-row-reverse md:justify-end md:gap-12"
|
||||
>
|
||||
{
|
||||
presentation.profile && (
|
||||
<Image
|
||||
src={presentation.profile}
|
||||
class="w-1/4 self-center rounded-full"
|
||||
alt="Your Profile"
|
||||
width="200"
|
||||
height="200"
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
<div class="flex flex-col gap-8">
|
||||
<h1 class="text-3xl text-neutral-100">
|
||||
{presentation.title}
|
||||
</h1>
|
||||
|
||||
<h2
|
||||
class="w-auto max-w-[60ch] leading-6"
|
||||
set:html={convertAsteriskToStrongTag(presentation.description)}
|
||||
/>
|
||||
|
||||
<SocialLinks />
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<article class="flex flex-col gap-8">
|
||||
<header class="flex w-full flex-row justify-between gap-2">
|
||||
<h3 class="text-lg text-neutral-100">Latest posts</h3>
|
||||
<Link href="/posts" label="See all posts" isUnderline target="_self" />
|
||||
</header>
|
||||
{posts.length === 0 && <p>Soon, stay connected 👀...</p>}
|
||||
|
||||
<section class="flex flex-col gap-4 md:flex-row md:flex-wrap">
|
||||
{
|
||||
posts.length !== 0 &&
|
||||
posts
|
||||
.slice(0, 2)
|
||||
.map((post) => (
|
||||
<PostCard
|
||||
publishedAt={post.data.publishedAt}
|
||||
title={post.data.title}
|
||||
description={post.data.description}
|
||||
slug={post.slug}
|
||||
/>
|
||||
))
|
||||
}
|
||||
</section>
|
||||
</article>
|
||||
|
||||
<article class="flex flex-col gap-8">
|
||||
<header class="flex w-full flex-row justify-between gap-2">
|
||||
<h3 class="text-lg text-neutral-100">
|
||||
Selected projects ({projects.length})
|
||||
</h3>
|
||||
</header>
|
||||
{projects.length === 0 && <p>Oops, I must work^^^^^</p>}
|
||||
|
||||
<section class="flex flex-col gap-4">
|
||||
{
|
||||
projects.length !== 0 &&
|
||||
projects.map((project) => <ProjectCard {...project} />)
|
||||
}
|
||||
</section>
|
||||
</article>
|
||||
|
||||
<article class="flex flex-col gap-8">
|
||||
<header class="flex w-full flex-row justify-between gap-2">
|
||||
<h3 class="text-lg text-neutral-100">Get in touch</h3>
|
||||
</header>
|
||||
<p>
|
||||
Email me at <Link
|
||||
href={`mailto:${presentation.mail}`}
|
||||
label={presentation.mail}
|
||||
/> or follow me via my social links.
|
||||
</p>
|
||||
|
||||
<SocialLinks />
|
||||
</article>
|
||||
</main>
|
||||
</Layout>
|
||||
@ -0,0 +1,34 @@
|
||||
---
|
||||
import { CollectionEntry, getCollection } from "astro:content";
|
||||
import Layout from "@/layouts/Layout.astro";
|
||||
import formatDate from "@/utils/formatDate";
|
||||
|
||||
export async function getStaticPaths() {
|
||||
const posts = await getCollection("posts");
|
||||
|
||||
return posts.map((post) => ({
|
||||
params: { slug: post.slug },
|
||||
props: { post },
|
||||
}));
|
||||
}
|
||||
|
||||
type Props = {
|
||||
post: CollectionEntry<"posts">;
|
||||
};
|
||||
|
||||
const { post } = Astro.props;
|
||||
const { Content } = await post.render();
|
||||
---
|
||||
|
||||
<Layout title={post.data.title} description={post.data.description}>
|
||||
<main class="post mx-auto flex w-full max-w-prose flex-col gap-4">
|
||||
<header role="presentation">
|
||||
<h1 class="text-md">
|
||||
{post.data.title} - {formatDate(post.data.publishedAt)}
|
||||
</h1>
|
||||
<p class="italic">{post.data.description}</p>
|
||||
</header>
|
||||
|
||||
<Content />
|
||||
</main>
|
||||
</Layout>
|
||||
@ -0,0 +1,55 @@
|
||||
---
|
||||
import { getCollection } from "astro:content";
|
||||
import Layout from "@/layouts/Layout.astro";
|
||||
import formatDate from "@/utils/formatDate";
|
||||
|
||||
const posts = (await getCollection("posts")).sort(function (first, second) {
|
||||
return second.data.publishedAt.getTime() - first.data.publishedAt.getTime();
|
||||
});
|
||||
---
|
||||
|
||||
<Layout title="Template - All Posts">
|
||||
<main class="flex flex-col gap-20">
|
||||
<h1 class="text-2xl text-neutral-100">Posts</h1>
|
||||
|
||||
<article class="flex flex-col gap-4">
|
||||
{
|
||||
posts.map((post) => (
|
||||
<a
|
||||
class="group flex flex-col gap-2 border-t border-neutral-700 py-4 transition-all hover:text-neutral-100"
|
||||
href={`/posts/${post.slug}`}
|
||||
>
|
||||
<div class="flex w-full items-center justify-between">
|
||||
<h2 class="text-lg">{post.data.title}</h2>
|
||||
|
||||
<div class="flex flex-row items-center gap-4">
|
||||
<p>{formatDate(post.data.publishedAt)}</p>
|
||||
<svg
|
||||
width="18"
|
||||
height="18"
|
||||
viewBox="0 0 18 18"
|
||||
fill="none"
|
||||
class="transition-all duration-300 group-hover:translate-x-1"
|
||||
>
|
||||
<path
|
||||
d="M5.25 12.75L12.75 5.25"
|
||||
stroke="#999999"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M5.25 5.25H12.75V12.75"
|
||||
stroke="#999999"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<p>{post.data.description}</p>
|
||||
</a>
|
||||
))
|
||||
}
|
||||
</article>
|
||||
</main>
|
||||
</Layout>
|
||||
@ -0,0 +1,39 @@
|
||||
.post p {
|
||||
@apply leading-7;
|
||||
}
|
||||
|
||||
.post code {
|
||||
@apply rounded-sm bg-neutral-800 px-1 py-[2px] text-orange-500;
|
||||
}
|
||||
|
||||
.post h2 {
|
||||
@apply mt-6 text-3xl text-neutral-100;
|
||||
}
|
||||
|
||||
.post h3 {
|
||||
@apply mt-4 text-xl text-neutral-100;
|
||||
}
|
||||
|
||||
.post code {
|
||||
@apply rounded-sm bg-neutral-800 px-1 py-[2px] text-red-500;
|
||||
}
|
||||
|
||||
.post a {
|
||||
@apply text-neutral-100 underline;
|
||||
}
|
||||
|
||||
.post ul {
|
||||
@apply list-disc;
|
||||
}
|
||||
|
||||
.post blockquote {
|
||||
@apply flex flex-row gap-2 before:block before:h-auto before:w-1 before:max-w-[1px] before:bg-red-400 before:content-[''];
|
||||
}
|
||||
|
||||
.post pre {
|
||||
@apply p-4;
|
||||
}
|
||||
|
||||
.post pre > code {
|
||||
@apply bg-transparent;
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
@ -0,0 +1,11 @@
|
||||
import theme from "@/data/theme";
|
||||
import { MAP_COLOR_VARIANT_TO_TEXT } from "./mapVariants";
|
||||
|
||||
export default function convertAsteriskToStrongTag(str: string) {
|
||||
return str.replace(
|
||||
/\*{1,2}(.*?)\*{1,2}/g,
|
||||
`<strong class="font-normal ${
|
||||
MAP_COLOR_VARIANT_TO_TEXT[theme.colors.primary]
|
||||
}">$1</strong>`
|
||||
);
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
export default function formatDate(date: Date) {
|
||||
return new Intl.DateTimeFormat("en-GB").format(date);
|
||||
}
|
||||
@ -0,0 +1,41 @@
|
||||
import type { TailwindColor } from "./types/tailwind";
|
||||
|
||||
const MAP_COLOR_VARIANT_TO_BG: Record<TailwindColor, string> = {
|
||||
orange: "bg-orange-500",
|
||||
violet: "bg-violet-500",
|
||||
red: "bg-red-500",
|
||||
amber: "bg-amber-500",
|
||||
yellow: "bg-yellow-500",
|
||||
lime: "bg-lime-500",
|
||||
green: "bg-green-500",
|
||||
emerald: "bg-emerald-500",
|
||||
teal: "bg-violet-500",
|
||||
cyan: "bg-cyan-500",
|
||||
blue: "bg-blue-500",
|
||||
indigo: "bg-indigo-500",
|
||||
purple: "bg-purple-500",
|
||||
fushia: "bg-fushia-500",
|
||||
pink: "bg-pink-500",
|
||||
rose: "bg-rose-500",
|
||||
};
|
||||
|
||||
const MAP_COLOR_VARIANT_TO_TEXT: Record<TailwindColor, string> = {
|
||||
orange: "text-orange-500",
|
||||
violet: "text-violet-500",
|
||||
red: "text-red-500",
|
||||
amber: "text-amber-500",
|
||||
yellow: "text-yellow-500",
|
||||
lime: "text-lime-500",
|
||||
green: "text-green-500",
|
||||
emerald: "text-emerald-500",
|
||||
teal: "text-violet-500",
|
||||
cyan: "text-cyan-500",
|
||||
blue: "text-blue-500",
|
||||
indigo: "text-indigo-500",
|
||||
purple: "text-purple-500",
|
||||
fushia: "text-fushia-500",
|
||||
pink: "text-pink-500",
|
||||
rose: "text-rose-500",
|
||||
};
|
||||
|
||||
export { MAP_COLOR_VARIANT_TO_BG, MAP_COLOR_VARIANT_TO_TEXT };
|
||||
@ -0,0 +1,5 @@
|
||||
export default function removeTrailingSlash(pathname: string) {
|
||||
const matchTrailingSlash = /\w+\/$/;
|
||||
if (matchTrailingSlash.test(pathname)) return pathname.slice(0, -1);
|
||||
return pathname;
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
export type HeadTags = {
|
||||
title?: string;
|
||||
description?: string;
|
||||
noindex?: boolean;
|
||||
og?: {
|
||||
title: string;
|
||||
type: string;
|
||||
description: string;
|
||||
image: string;
|
||||
alt: string;
|
||||
};
|
||||
};
|
||||
@ -0,0 +1,17 @@
|
||||
export type TailwindColor =
|
||||
| "orange"
|
||||
| "violet"
|
||||
| "red"
|
||||
| "amber"
|
||||
| "yellow"
|
||||
| "lime"
|
||||
| "green"
|
||||
| "emerald"
|
||||
| "teal"
|
||||
| "cyan"
|
||||
| "blue"
|
||||
| "indigo"
|
||||
| "purple"
|
||||
| "fushia"
|
||||
| "pink"
|
||||
| "rose";
|
||||
@ -0,0 +1,14 @@
|
||||
const defaultTheme = require("tailwindcss/defaultTheme");
|
||||
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
module.exports = {
|
||||
content: ["./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}"],
|
||||
theme: {
|
||||
extend: {
|
||||
fontFamily: {
|
||||
sans: ["Open Sans", ...defaultTheme.fontFamily.sans],
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [],
|
||||
};
|
||||
@ -0,0 +1,9 @@
|
||||
{
|
||||
"extends": "astro/tsconfigs/strict",
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in new issue