diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..4471e67 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,11 @@ +node_modules +dist +.git +.vscode +.idea +.astro +.DS_Store +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..0887fbf --- /dev/null +++ b/Dockerfile @@ -0,0 +1,18 @@ +# Stage 1: Build +FROM node:22-alpine AS build + +WORKDIR /app + +COPY package*.json ./ +RUN npm ci + +COPY . . +RUN npm run build + +# Stage 2: Serve +FROM joseluisq/static-web-server:2-alpine + +ENV SERVER_ROOT=/public +ENV SERVER_PORT=80 + +COPY --from=build /app/dist /public diff --git a/astro.config.mjs b/astro.config.mjs index 00add51..5054c42 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -1,13 +1,14 @@ // @ts-check +import tailwindcss from "@tailwindcss/vite"; import { defineConfig } from "astro/config"; -import tailwindcss from "@tailwindcss/vite"; +import expressiveCode from "astro-expressive-code"; import pagefind from "astro-pagefind"; // https://astro.build/config export default defineConfig({ - integrations: [pagefind()], vite: { plugins: [tailwindcss()], }, + integrations: [expressiveCode(), pagefind()], }); diff --git a/compose.yml b/compose.yml new file mode 100644 index 0000000..261f481 --- /dev/null +++ b/compose.yml @@ -0,0 +1,10 @@ +services: + site-server: + build: . + restart: unless-stopped + networks: + - traefik-proxy + +networks: + traefik-proxy: + external: true \ No newline at end of file diff --git a/deploy.ps1 b/deploy.ps1 deleted file mode 100644 index c377267..0000000 --- a/deploy.ps1 +++ /dev/null @@ -1,33 +0,0 @@ -# Variables -$remoteUser = "dhemas" -$remoteHost = "dhemasnurjaya.com" -$remoteDir = "/home/dhemas/apps/blog/public/" -$localDir = "dist/" -$keyPath = "D:\Secrets\giocloud-default.ppk" -$winscpExecutable = "C:\Users\dhemas\AppData\Local\Programs\WinSCP\WinSCP.com" # Update this if needed - -# Build astro site -npm run build -if ($LASTEXITCODE -ne 0) { - Write-Host "Build failed!" -ForegroundColor Red - exit 1 -} - -# Generate WinSCP sync commands -$scriptContent = @" -open sftp://$remoteUser@$remoteHost -privatekey=$keyPath -synchronize remote -delete -criteria=checksum $localDir $remoteDir -exit -"@ - -# Save the script to a temporary file -$tempScript = [System.IO.Path]::GetTempFileName() -Set-Content -Path $tempScript -Value $scriptContent - -# Execute the WinSCP command -& $winscpExecutable /script=$tempScript - -# Clean up -Remove-Item $tempScript - -Write-Host "Deployed to $remoteHost!" diff --git a/ec.config.mjs b/ec.config.mjs new file mode 100644 index 0000000..1517dd4 --- /dev/null +++ b/ec.config.mjs @@ -0,0 +1,11 @@ +import { defineEcConfig } from "astro-expressive-code"; + +export default defineEcConfig({ + themes: ["dark-plus"], + styleOverrides: { + borderRadius: "0rem", + frames: { + shadowColor: "transparent", + }, + }, +}); diff --git a/package-lock.json b/package-lock.json index 84931f2..d335857 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,12 +8,11 @@ "name": "site-astro", "version": "0.0.1", "dependencies": { - "@fontsource-variable/noto-sans": "^5.2.10", "@fontsource/jetbrains-mono": "^5.2.8", "@tailwindcss/vite": "^4.1.18", "astro": "^5.16.10", + "astro-expressive-code": "^0.41.6", "astro-pagefind": "^1.8.5", - "lucide-astro": "^0.556.0", "tailwindcss": "^4.1.18" }, "devDependencies": { @@ -152,6 +151,15 @@ "node": ">=18" } }, + "node_modules/@ctrl/tinycolor": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-4.2.0.tgz", + "integrity": "sha512-kzyuwOAQnXJNLS9PSyrk0CWk35nWJW/zl/6KvnTBMFK65gm7U1/Z5BqjxeapjZCIhQcM/DsrEmcbRwDyXyXK4A==", + "license": "MIT", + "engines": { + "node": ">=14" + } + }, "node_modules/@emnapi/runtime": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.8.1.tgz", @@ -578,13 +586,49 @@ "node": ">=18" } }, - "node_modules/@fontsource-variable/noto-sans": { - "version": "5.2.10", - "resolved": "https://registry.npmjs.org/@fontsource-variable/noto-sans/-/noto-sans-5.2.10.tgz", - "integrity": "sha512-wyFgKkFu7jki5kEL8qv7avjQ8rxHX0J/nhLWvbR9T0hOH1HRKZEvb9EW9lMjZfWHHfEzKkYf5J+NadwgCS7TXA==", - "license": "OFL-1.1", - "funding": { - "url": "https://github.com/sponsors/ayuhito" + "node_modules/@expressive-code/core": { + "version": "0.41.6", + "resolved": "https://registry.npmjs.org/@expressive-code/core/-/core-0.41.6.tgz", + "integrity": "sha512-FvJQP+hG0jWi/FLBSmvHInDqWR7jNANp9PUDjdMqSshHb0y7sxx3vHuoOr6SgXjWw+MGLqorZyPQ0aAlHEok6g==", + "license": "MIT", + "dependencies": { + "@ctrl/tinycolor": "^4.0.4", + "hast-util-select": "^6.0.2", + "hast-util-to-html": "^9.0.1", + "hast-util-to-text": "^4.0.1", + "hastscript": "^9.0.0", + "postcss": "^8.4.38", + "postcss-nested": "^6.0.1", + "unist-util-visit": "^5.0.0", + "unist-util-visit-parents": "^6.0.1" + } + }, + "node_modules/@expressive-code/plugin-frames": { + "version": "0.41.6", + "resolved": "https://registry.npmjs.org/@expressive-code/plugin-frames/-/plugin-frames-0.41.6.tgz", + "integrity": "sha512-d+hkSYXIQot6fmYnOmWAM+7TNWRv/dhfjMsNq+mIZz8Tb4mPHOcgcfZeEM5dV9TDL0ioQNvtcqQNuzA1sRPjxg==", + "license": "MIT", + "dependencies": { + "@expressive-code/core": "^0.41.6" + } + }, + "node_modules/@expressive-code/plugin-shiki": { + "version": "0.41.6", + "resolved": "https://registry.npmjs.org/@expressive-code/plugin-shiki/-/plugin-shiki-0.41.6.tgz", + "integrity": "sha512-Y6zmKBmsIUtWTzdefqlzm/h9Zz0Rc4gNdt2GTIH7fhHH2I9+lDYCa27BDwuBhjqcos6uK81Aca9dLUC4wzN+ng==", + "license": "MIT", + "dependencies": { + "@expressive-code/core": "^0.41.6", + "shiki": "^3.2.2" + } + }, + "node_modules/@expressive-code/plugin-text-markers": { + "version": "0.41.6", + "resolved": "https://registry.npmjs.org/@expressive-code/plugin-text-markers/-/plugin-text-markers-0.41.6.tgz", + "integrity": "sha512-PBFa1wGyYzRExMDzBmAWC6/kdfG1oLn4pLpBeTfIRrALPjcGA/59HP3e7q9J0Smk4pC7U+lWkA2LHR8FYV8U7Q==", + "license": "MIT", + "dependencies": { + "@expressive-code/core": "^0.41.6" } }, "node_modules/@fontsource/jetbrains-mono": { @@ -2176,6 +2220,18 @@ "sharp": "^0.34.0" } }, + "node_modules/astro-expressive-code": { + "version": "0.41.6", + "resolved": "https://registry.npmjs.org/astro-expressive-code/-/astro-expressive-code-0.41.6.tgz", + "integrity": "sha512-l47tb1uhmVIebHUkw+HEPtU/av0G4O8Q34g2cbkPvC7/e9ZhANcjUUciKt9Hp6gSVDdIuXBBLwJQn2LkeGMOAw==", + "license": "MIT", + "dependencies": { + "rehype-expressive-code": "^0.41.6" + }, + "peerDependencies": { + "astro": "^4.0.0-beta || ^5.0.0-beta || ^3.3.0 || ^6.0.0-beta" + } + }, "node_modules/astro-pagefind": { "version": "1.8.5", "resolved": "https://registry.npmjs.org/astro-pagefind/-/astro-pagefind-1.8.5.tgz", @@ -2215,6 +2271,16 @@ "integrity": "sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==", "license": "MIT" }, + "node_modules/bcp-47-match": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/bcp-47-match/-/bcp-47-match-2.0.3.tgz", + "integrity": "sha512-JtTezzbAibu8G0R9op9zb3vcWZd9JF6M0xOYGPn0fNCd7wOpRB1mU2mH9T8gaBGbAAyIIVgB2G7xG0GP98zMAQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/boolbase": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", @@ -2427,6 +2493,22 @@ "url": "https://github.com/sponsors/fb55" } }, + "node_modules/css-selector-parser": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/css-selector-parser/-/css-selector-parser-3.3.0.tgz", + "integrity": "sha512-Y2asgMGFqJKF4fq4xHDSlFYIkeVfRsm69lQC1q9kbEsH5XtnINTMrweLkjYMeaUgiXBy/uvKeO/a1JHTNnmB2g==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/mdevils" + }, + { + "type": "patreon", + "url": "https://patreon.com/mdevils" + } + ], + "license": "MIT" + }, "node_modules/css-tree": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.1.0.tgz", @@ -2597,6 +2679,19 @@ "node": ">=0.3.1" } }, + "node_modules/direction": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/direction/-/direction-2.0.1.tgz", + "integrity": "sha512-9S6m9Sukh1cZNknO1CWAr2QAWsbKLafQiyM5gZ7VgXHeuaoUwffKN4q6NC4A/Mf9iiPlOXQEKW/Mv/mh9/3YFA==", + "license": "MIT", + "bin": { + "direction": "cli.js" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/dlv": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", @@ -2784,6 +2879,18 @@ "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", "license": "MIT" }, + "node_modules/expressive-code": { + "version": "0.41.6", + "resolved": "https://registry.npmjs.org/expressive-code/-/expressive-code-0.41.6.tgz", + "integrity": "sha512-W/5+IQbrpCIM5KGLjO35wlp1NCwDOOVQb+PAvzEoGkW1xjGM807ZGfBKptNWH6UECvt6qgmLyWolCMYKh7eQmA==", + "license": "MIT", + "dependencies": { + "@expressive-code/core": "^0.41.6", + "@expressive-code/plugin-frames": "^0.41.6", + "@expressive-code/plugin-shiki": "^0.41.6", + "@expressive-code/plugin-text-markers": "^0.41.6" + } + }, "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -2930,6 +3037,19 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/hast-util-has-property": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-has-property/-/hast-util-has-property-3.0.0.tgz", + "integrity": "sha512-MNilsvEKLFpV604hwfhVStK0usFY/QmM5zX16bo7EjnAEGofr5YyI37kzopBlZJkHD4t887i+q/C8/tr5Q94cA==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/hast-util-is-element": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-3.0.0.tgz", @@ -2981,6 +3101,33 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/hast-util-select": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/hast-util-select/-/hast-util-select-6.0.4.tgz", + "integrity": "sha512-RqGS1ZgI0MwxLaKLDxjprynNzINEkRHY2i8ln4DDjgv9ZhcYVIHN9rlpiYsqtFwrgpYU361SyWDQcGNIBVu3lw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "bcp-47-match": "^2.0.0", + "comma-separated-tokens": "^2.0.0", + "css-selector-parser": "^3.0.0", + "devlop": "^1.0.0", + "direction": "^2.0.0", + "hast-util-has-property": "^3.0.0", + "hast-util-to-string": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "nth-check": "^2.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "unist-util-visit": "^5.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/hast-util-to-html": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.5.tgz", @@ -3023,6 +3170,19 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/hast-util-to-string": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/hast-util-to-string/-/hast-util-to-string-3.0.1.tgz", + "integrity": "sha512-XelQVTDWvqcl3axRfI0xSeoVKzyIFPwsAGSLIsKdJKQMXDYJS4WYrBNF/8J7RdhIcFI2BOHgAifggsvsxp/3+A==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/hast-util-to-text": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/hast-util-to-text/-/hast-util-to-text-4.0.2.tgz", @@ -3477,16 +3637,6 @@ "node": "20 || >=22" } }, - "node_modules/lucide-astro": { - "version": "0.556.0", - "resolved": "https://registry.npmjs.org/lucide-astro/-/lucide-astro-0.556.0.tgz", - "integrity": "sha512-ugMjPb45AMfkLCaduNSbyy5NQEKvB1TxVVMmUS4S6L807PMESnX0Qp+DIKHjbyjJmPXOyLRbrzvR3YikTK7brg==", - "deprecated": "Deprecated: Use `@lucide/astro`", - "license": "MIT", - "peerDependencies": { - "astro": ">=2.7.1" - } - }, "node_modules/magic-string": { "version": "0.30.21", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", @@ -4572,6 +4722,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", @@ -4581,6 +4732,44 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/postcss-nested": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", + "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "^6.1.1" + }, + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, + "node_modules/postcss-nested/node_modules/postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/postcss-selector-parser": { "version": "6.0.10", "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz", @@ -4735,6 +4924,15 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/rehype-expressive-code": { + "version": "0.41.6", + "resolved": "https://registry.npmjs.org/rehype-expressive-code/-/rehype-expressive-code-0.41.6.tgz", + "integrity": "sha512-aBMX8kxPtjmDSFUdZlAWJkMvsQ4ZMASfee90JWIAV8tweltXLzkWC3q++43ToTelI8ac5iC0B3/S/Cl4Ql1y2g==", + "license": "MIT", + "dependencies": { + "expressive-code": "^0.41.6" + } + }, "node_modules/rehype-parse": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/rehype-parse/-/rehype-parse-9.0.1.tgz", @@ -5602,7 +5800,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true, "license": "MIT" }, "node_modules/vfile": { diff --git a/package.json b/package.json index 499acb4..c67cbda 100644 --- a/package.json +++ b/package.json @@ -10,12 +10,11 @@ "format": "prettier --write ." }, "dependencies": { - "@fontsource-variable/noto-sans": "^5.2.10", "@fontsource/jetbrains-mono": "^5.2.8", "@tailwindcss/vite": "^4.1.18", "astro": "^5.16.10", + "astro-expressive-code": "^0.41.6", "astro-pagefind": "^1.8.5", - "lucide-astro": "^0.556.0", "tailwindcss": "^4.1.18" }, "devDependencies": { diff --git a/src/assets/images/at-sign.svg b/src/assets/images/at-sign.svg new file mode 100644 index 0000000..7aa366f --- /dev/null +++ b/src/assets/images/at-sign.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/images/facebook.svg b/src/assets/images/facebook.svg new file mode 100644 index 0000000..2e36b2c --- /dev/null +++ b/src/assets/images/facebook.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/images/github.svg b/src/assets/images/github.svg new file mode 100644 index 0000000..605f6ac --- /dev/null +++ b/src/assets/images/github.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/images/linkedin.svg b/src/assets/images/linkedin.svg new file mode 100644 index 0000000..d48939b --- /dev/null +++ b/src/assets/images/linkedin.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/images/profile.webp b/src/assets/images/profile.webp deleted file mode 100644 index 7c8cf8f..0000000 Binary files a/src/assets/images/profile.webp and /dev/null differ diff --git a/src/assets/images/twitter.svg b/src/assets/images/twitter.svg new file mode 100644 index 0000000..201f44b --- /dev/null +++ b/src/assets/images/twitter.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/components/BlogPost.astro b/src/components/BlogPost.astro deleted file mode 100644 index 76adbe2..0000000 --- a/src/components/BlogPost.astro +++ /dev/null @@ -1,51 +0,0 @@ ---- -import Tag from "@/components/Tag.astro"; - -interface Props { - title: string; - description: string; - date: Date; - tags?: string[]; -} - -const { title, description, date, tags } = Astro.props; ---- - -
-
-

{title}

-

{description}

-
- -
-
- -
- -
- - -
diff --git a/src/components/BlogPostCard.astro b/src/components/BlogPostCard.astro deleted file mode 100644 index c3ae70f..0000000 --- a/src/components/BlogPostCard.astro +++ /dev/null @@ -1,26 +0,0 @@ ---- -interface Props { - id: string; - date: Date; - title: string; - description: string; -} - -const { id, date, title, description } = Astro.props; ---- - - -
-
- { - date.toLocaleDateString("en-US", { - year: "numeric", - month: "long", - day: "numeric", - }) - } -
-

{title}

-

{description}

-
-
diff --git a/src/components/BlogPostEntry.astro b/src/components/BlogPostEntry.astro new file mode 100644 index 0000000..f1f50b2 --- /dev/null +++ b/src/components/BlogPostEntry.astro @@ -0,0 +1,28 @@ +--- +import Link from "@/components/Link.astro"; + +interface Props { + id: string; + date: Date; + title: string; + description: string; +} + +const { id, date, title, description } = Astro.props; +--- + +
+ +

{title}

+ +
+ { + date.toLocaleDateString("en-US", { + year: "numeric", + month: "long", + day: "numeric", + }) + } +
+

{description}

+
diff --git a/src/components/EmptyState.astro b/src/components/EmptyState.astro index 5221dfa..6fb355d 100644 --- a/src/components/EmptyState.astro +++ b/src/components/EmptyState.astro @@ -6,4 +6,4 @@ interface Props { const { message } = Astro.props; --- -

{message}

+

{message}

diff --git a/src/components/Footer.astro b/src/components/Footer.astro index 3dc71dd..3800838 100644 --- a/src/components/Footer.astro +++ b/src/components/Footer.astro @@ -1,5 +1,6 @@ -