Compare commits

...

44 Commits

Author SHA1 Message Date
e2571880ce Deps (no more beta)
All checks were successful
Docker Deploy / build-and-push (push) Successful in 5m26s
2026-03-03 13:31:12 -07:00
0eafcb9a67 Update bun.lock 2026-03-03 13:23:32 -07:00
9a2e7f65cb Deps
All checks were successful
Docker Deploy / build-and-push (push) Successful in 3m28s
2026-03-01 01:17:06 -07:00
e5110ddd75 Update site.ts
All checks were successful
Docker Deploy / build-and-push (push) Successful in 2m52s
2026-02-25 18:06:59 -07:00
3b2abe7a99 Attempt #3
All checks were successful
Docker Deploy / build-and-push (push) Successful in 3m31s
2026-02-25 16:49:34 -07:00
4cbe911b0c Attempt to fix FOUC
All checks were successful
Docker Deploy / build-and-push (push) Successful in 2m50s
2026-02-25 16:29:29 -07:00
75321034aa The fuckin lock file is pissing me off
All checks were successful
Docker Deploy / build-and-push (push) Successful in 3m30s
2026-02-25 13:02:48 -07:00
174afb6a10 Pls
Some checks failed
Docker Deploy / build-and-push (push) Failing after 1m49s
2026-02-25 10:40:48 -07:00
483e80db79 Small fix to the CSS animation nonsense
All checks were successful
Docker Deploy / build-and-push (push) Successful in 2m41s
2026-02-25 08:22:55 -07:00
a303b8be00 Update ContactSection.vue
All checks were successful
Docker Deploy / build-and-push (push) Successful in 3m47s
2026-02-24 23:48:25 -07:00
bb0b348069 Update bun.lock 2026-02-24 23:24:39 -07:00
cf2195b4f3 Update package.json
All checks were successful
Docker Deploy / build-and-push (push) Successful in 3m28s
2026-02-24 23:14:57 -07:00
6de9c9c83b Update package.json 2026-02-24 23:14:41 -07:00
e3787281fd ???
All checks were successful
Docker Deploy / build-and-push (push) Successful in 5m5s
2026-02-24 18:05:38 -07:00
255abd508d Ok try this
Some checks failed
Docker Deploy / build-and-push (push) Failing after 6m6s
2026-02-24 17:57:25 -07:00
07561a4335 Create bun.lock
Some checks failed
Docker Deploy / build-and-push (push) Has been cancelled
2026-02-24 17:51:22 -07:00
22d3b9d7df Move to Bun 2026-02-24 17:51:12 -07:00
c5fc1cedd7 Fuck it... right now we don't need CSP. I do nothing useful on this
All checks were successful
Docker Deploy / build-and-push (push) Successful in 3m19s
site.
2026-02-24 16:57:18 -07:00
cbdab153da I guess DaisyUI has rotating text now... awesome!
All checks were successful
Docker Deploy / build-and-push (push) Successful in 3m25s
2026-02-24 16:50:00 -07:00
6dea3ac96c Remove partytown
All checks were successful
Docker Deploy / build-and-push (push) Successful in 3m32s
2026-02-24 16:26:11 -07:00
8c5556eb3c Yelling at me to add this
All checks were successful
Docker Deploy / build-and-push (push) Successful in 3m28s
2026-02-24 14:49:22 -07:00
50d8f2a9aa ugh
All checks were successful
Docker Deploy / build-and-push (push) Successful in 3m0s
2026-02-24 12:34:39 -07:00
e9845965d7 Update Layout.astro
All checks were successful
Docker Deploy / build-and-push (push) Successful in 3m12s
2026-02-24 11:46:08 -07:00
737a4dd7e8 Slop-free
All checks were successful
Docker Deploy / build-and-push (push) Successful in 3m49s
2026-02-23 11:54:27 -07:00
c31d0b5589 Docker optimization
All checks were successful
Docker Deploy / build-and-push (push) Successful in 3m10s
2026-02-12 15:09:31 -07:00
58902e081a Cleaned up Icon components
All checks were successful
Docker Deploy / build-and-push (push) Successful in 3m11s
2026-02-12 14:23:33 -07:00
62dcec8202 Moved to keeping the SVGs in repo
Some checks failed
Docker Deploy / build-and-push (push) Failing after 3m7s
2026-02-12 13:15:34 -07:00
b15dce4cd4 deps
All checks were successful
Docker Deploy / build-and-push (push) Successful in 3m34s
2026-02-09 13:12:34 -07:00
25af507805 Added marew
Some checks failed
Docker Deploy / build-and-push (push) Has been cancelled
2026-02-09 13:12:21 -07:00
8b8b60b302 Added links for clients
All checks were successful
Docker Deploy / build-and-push (push) Successful in 3m23s
2026-02-06 00:14:57 -07:00
59577f0e58 Update astro.config.mjs
All checks were successful
Docker Deploy / build-and-push (push) Successful in 3m20s
2026-01-30 14:57:28 -07:00
8bd4ccbafb Switch to auto
All checks were successful
Docker Deploy / build-and-push (push) Successful in 3m15s
2026-01-30 14:54:07 -07:00
beaf088391 Party again
Some checks failed
Docker Deploy / build-and-push (push) Failing after 3m6s
2026-01-30 14:48:24 -07:00
f8555413e1 :(
All checks were successful
Docker Deploy / build-and-push (push) Successful in 3m29s
2026-01-30 14:41:29 -07:00
7c24cf61d5 Security headers
All checks were successful
Docker Deploy / build-and-push (push) Successful in 3m3s
2026-01-30 13:57:41 -07:00
f70ce24bcb Small text update to make it less cringe
All checks were successful
Docker Deploy / build-and-push (push) Successful in 3m34s
2026-01-30 13:51:58 -07:00
a089c9dfc7 PARTY!!!!!
All checks were successful
Docker Deploy / build-and-push (push) Successful in 3m19s
2026-01-30 13:37:58 -07:00
c03128a314 Analytics
Some checks failed
Docker Deploy / build-and-push (push) Has been cancelled
2026-01-30 13:36:50 -07:00
cf4a4827df Moved the scrolling text to Vue since it needs some JS and custom
All checks were successful
Docker Deploy / build-and-push (push) Successful in 3m16s
styling not available in Tailwind
2026-01-30 13:28:37 -07:00
f7fd011660 Duplicate config
All checks were successful
Docker Deploy / build-and-push (push) Successful in 3m31s
2026-01-30 11:53:00 -07:00
3b2fca97aa Fixed button shadow
Some checks failed
Docker Deploy / build-and-push (push) Has been cancelled
2026-01-30 11:50:48 -07:00
1ddd73431b Updated Saikyo Logo
All checks were successful
Docker Deploy / build-and-push (push) Successful in 3m38s
2026-01-30 11:40:30 -07:00
332794d62c Update ClientList.astro
All checks were successful
Docker Deploy / build-and-push (push) Successful in 3m17s
2026-01-30 11:13:33 -07:00
d339e66cf0 Removed rush 2026-01-30 11:04:57 -07:00
26 changed files with 1461 additions and 5335 deletions

View File

@@ -12,20 +12,20 @@ jobs:
packages: write
steps:
- name: Checkout code
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
uses: docker/setup-buildx-action@v3
- name: Login to Container Registry
uses: docker/login-action@v2
uses: docker/login-action@v3
with:
registry: ${{ secrets.REPO_HOST }}
username: ${{ github.repository_owner }}
password: ${{ secrets.DEPLOY_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v4
uses: docker/build-push-action@v6
with:
context: .
platforms: linux/amd64
@@ -33,3 +33,6 @@ jobs:
tags: |
${{ secrets.REPO_HOST }}/${{ github.repository_owner }}/${{ github.event.repository.name }}:${{ github.sha }}
${{ secrets.REPO_HOST }}/${{ github.repository_owner }}/${{ github.event.repository.name }}:latest
provenance: false
cache-from: type=registry,ref=${{ secrets.REPO_HOST }}/${{ github.repository_owner }}/${{ github.event.repository.name }}:buildcache
cache-to: type=registry,ref=${{ secrets.REPO_HOST }}/${{ github.repository_owner }}/${{ github.event.repository.name }}:buildcache,mode=max

View File

@@ -1,27 +1,28 @@
FROM node:lts-alpine AS builder
FROM oven/bun:1.3.9-alpine AS base
WORKDIR /app
RUN npm i -g pnpm
FROM base AS prod-deps
COPY package.json bun.lock ./
RUN --mount=type=cache,id=bun,target=/root/.bun/install/cache \
bun install --production --frozen-lockfile || bun install --production
COPY package.json pnpm-lock.yaml ./
RUN pnpm install
FROM base AS builder
COPY package.json bun.lock ./
RUN --mount=type=cache,id=bun,target=/root/.bun/install/cache \
bun install --frozen-lockfile || bun install
COPY . .
RUN pnpm run build
RUN bun run build
FROM node:lts-alpine AS runtime
FROM base AS runtime
WORKDIR /app
RUN npm i -g pnpm
COPY --from=builder /app/dist ./dist
COPY package.json pnpm-lock.yaml ./
RUN pnpm install --prod
COPY --from=prod-deps /app/node_modules ./node_modules
COPY package.json ./
ENV HOST=0.0.0.0
ENV PORT=4321
EXPOSE 4321
CMD ["node", "./dist/server/entry.mjs"]
CMD ["bun", "run", "./dist/server/entry.mjs"]

View File

@@ -1,22 +1,17 @@
// @ts-check
import { defineConfig } from "astro/config";
import vue from "@astrojs/vue";
import node from "@astrojs/node";
import tailwindcss from "@tailwindcss/vite";
import icon from "astro-icon";
const isDev = process.env.NODE_ENV === "development";
// https://astro.build/config
export default defineConfig({
output: "server",
prefetch: true,
build: {
inlineStylesheets: "always",
inlineStylesheets: "auto",
},
integrations: [vue(), icon()],
integrations: [vue()],
adapter: node({
mode: "standalone",

1146
bun.lock Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -22,14 +22,12 @@
devShells = forAllSystems ({ pkgs }: {
default = pkgs.mkShell {
packages = with pkgs; [
nodejs_24
nodePackages.pnpm
bun
];
shellHook = ''
echo "<atashdotdev dev shell>"
echo "Node version: $(node --version)"
echo "pnpm version: $(pnpm --version)"
echo "Bun version: $(bun --version)"
'';
};
});

View File

@@ -1,7 +1,7 @@
{
"name": "atashdotdev",
"type": "module",
"version": "1.3.0",
"version": "2.0.0",
"scripts": {
"dev": "astro dev",
"build": "astro build",
@@ -9,22 +9,17 @@
"astro": "astro"
},
"dependencies": {
"@astrojs/node": "^9.5.2",
"@astrojs/vue": "^5.1.4",
"@fontsource-variable/inter": "^5.2.8",
"@fontsource-variable/roboto-slab": "^5.2.8",
"@heroicons/vue": "^2.2.0",
"@tailwindcss/vite": "^4.1.18",
"astro": "^5.17.1",
"astro-icon": "^1.1.5",
"nodemailer": "^7.0.13",
"tailwindcss": "^4.1.18",
"vue": "^3.5.27"
"@astrojs/node": "9.5.4",
"@astrojs/vue": "5.1.4",
"@tailwindcss/vite": "^4.2.1",
"astro": "5.18.0",
"nodemailer": "^8.0.1",
"tailwindcss": "^4.2.1",
"vue": "^3.5.29"
},
"devDependencies": {
"@iconify-json/heroicons": "^1.2.3",
"@types/node": "^25.1.0",
"@types/nodemailer": "^7.0.9",
"daisyui": "^5.5.14"
"@types/node": "^25.3.3",
"@types/nodemailer": "^7.0.11",
"daisyui": "^5.5.19"
}
}

5193
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 291 KiB

BIN
public/fonts/roboto.woff2 Normal file

Binary file not shown.

View File

@@ -1,6 +1,6 @@
---
import { siteConfig } from "../config/site";
import { Icon } from "astro-icon/components";
import Icon from "./Icon.astro";
import { Image } from "astro:assets";
---
@@ -17,19 +17,18 @@ import { Image } from "astro:assets";
class="btn btn-ghost btn-circle lg:hidden"
aria-label="Open menu"
>
<Icon name="heroicons:bars-3-bottom-left" class="h-5 w-5" />
<Icon name="bars-3-bottom-left" class="h-5 w-5" />
</div>
<ul
tabindex="0"
class="menu menu-sm dropdown-content bg-base-100 rounded-xl z-50 mt-3 w-56 p-3 shadow-xl border border-base-200"
role="menu"
aria-label="Navigation Button"
>
{
siteConfig.header.nav.map(({ text, href }) => (
<li role="none">
<li>
<a
href={href}
role="menuitem"
class="py-3 px-4 rounded-lg font-medium hover:bg-primary/10 hover:text-primary transition-colors"
>
{text}
@@ -60,13 +59,12 @@ import { Image } from "astro:assets";
</a>
</div>
<nav class="navbar-center hidden lg:flex" aria-label="Main navigation">
<ul class="menu menu-horizontal gap-1" role="menubar">
<ul class="menu menu-horizontal gap-1">
{
siteConfig.header.nav.map(({ text, href }) => (
<li role="none">
<li>
<a
href={href}
role="menuitem"
class="font-medium px-4 py-2 rounded-lg hover:bg-primary/10 hover:text-primary transition-colors"
>
{text}
@@ -80,7 +78,7 @@ import { Image } from "astro:assets";
<a
href={siteConfig.header.cta.href}
class="btn btn-primary btn-sm lg:btn-md shadow-md hover:shadow-lg transition-all"
role="button"
aria-label={siteConfig.header.cta.text}
>
{siteConfig.header.cta.text}
</a>

27
src/components/Icon.astro Normal file
View File

@@ -0,0 +1,27 @@
---
import { icons, type IconName } from "../config/icons";
interface Props {
name: IconName;
class?: string;
"class:list"?: any;
}
const { name, class: className, "class:list": classList } = Astro.props;
const svg = icons[name];
if (!svg) {
throw new Error(`Icon "${name}" not found in icon registry`);
}
---
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
width="1em"
height="1em"
fill="none"
class:list={[className, classList]}
aria-hidden="true"
set:html={svg}
/>

30
src/components/Icon.vue Normal file
View File

@@ -0,0 +1,30 @@
<script setup lang="ts">
import { computed } from "vue";
import { icons, type IconName } from "../config/icons";
const props = defineProps<{
name: IconName;
class?: string;
}>();
const svg = computed(() => {
const content = icons[props.name];
if (!content) {
console.error(`Icon "${props.name}" not found in icon registry`);
}
return content;
});
</script>
<template>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
width="1em"
height="1em"
fill="none"
:class="props.class"
aria-hidden="true"
v-html="svg"
/>
</template>

View File

@@ -1,22 +0,0 @@
---
interface Props {
items: {
text: string;
className: string;
}[];
}
const { items } = Astro.props;
---
<span class="block w-full my-2">
<span class="text-rotate">
<span class="justify-items-center">
{
items.map((item) => (
<span class={item.className}>{item.text}</span>
))
}
</span>
</span>
</span>

View File

@@ -0,0 +1,33 @@
<template>
<span class="block w-full my-2">
<span class="text-rotate">
<span class="justify-items-center">
<span
v-for="(item, index) in items"
:key="index"
:class="item.className"
>
{{ item.text }}
</span>
</span>
</span>
</span>
</template>
<script setup lang="ts">
interface RotatingTextItem {
text: string;
className: string;
}
defineProps<{
items: RotatingTextItem[];
}>();
</script>
<style scoped>
.text-rotate:hover,
.text-rotate:hover * {
animation-play-state: running !important;
}
</style>

View File

@@ -1,19 +1,25 @@
---
import { Icon } from "astro-icon/components";
import Icon from "../Icon.astro";
import { type IconName } from "../../config/icons";
import { siteConfig } from "../../config/site";
import Section from "../Section.astro";
const features = [
const features: {
icon: IconName;
variant: string;
title: string;
content: string;
}[] = [
{
icon: "heroicons:bolt",
icon: "bolt",
...siteConfig.whyUs.cards[0],
},
{
icon: "heroicons:check-circle",
icon: "slopfree",
...siteConfig.whyUs.cards[1],
},
{
icon: "heroicons:users",
icon: "users",
...siteConfig.whyUs.cards[2],
},
];

View File

@@ -18,11 +18,11 @@ import { siteConfig } from "../../config/site";
speed={40}
direction="left"
logoHeight={128}
gap={160}
gap={200}
pauseOnHover={false}
scaleOnHover={true}
fadeOut={true}
ariaLabel="Scrolling list of client logos"
ariaLabel="Scrolling list of client logos."
/>
</div>
</Section>

View File

@@ -1,11 +1,6 @@
<script setup lang="ts">
import { ref } from "vue";
import {
XCircleIcon,
CheckCircleIcon,
PaperAirplaneIcon,
EnvelopeIcon,
} from "@heroicons/vue/24/outline";
import Icon from "../Icon.vue";
import { siteConfig } from "../../config/site";
const firstName = ref("");
@@ -82,7 +77,9 @@ ${message.value}`,
</legend>
<input
type="text"
id="firstName"
name="firstName"
:aria-label="siteConfig.contact.form.firstName"
class="input input-bordered w-full bg-base-100 focus:border-primary focus:outline-primary"
required
v-model="firstName"
@@ -101,7 +98,9 @@ ${message.value}`,
</legend>
<input
type="text"
id="lastName"
name="lastName"
:aria-label="siteConfig.contact.form.lastName"
class="input input-bordered w-full bg-base-100 focus:border-primary focus:outline-primary"
required
v-model="lastName"
@@ -122,7 +121,9 @@ ${message.value}`,
</legend>
<input
type="email"
id="email"
name="email"
:aria-label="siteConfig.contact.form.email"
class="input input-bordered w-full bg-base-100 focus:border-primary focus:outline-primary"
required
v-model="email"
@@ -141,7 +142,9 @@ ${message.value}`,
</legend>
<input
type="text"
id="company"
name="company"
:aria-label="siteConfig.contact.form.company"
class="input input-bordered w-full bg-base-100 focus:border-primary focus:outline-primary"
v-model="company"
:disabled="status === 'sending'"
@@ -220,6 +223,7 @@ ${message.value}`,
<textarea
id="project-details"
name="message"
:aria-label="siteConfig.contact.form.message"
class="textarea textarea-bordered h-36 w-full resize-none bg-base-100 focus:border-primary focus:outline-primary"
:placeholder="
siteConfig.contact.form.placeholders.message
@@ -235,12 +239,12 @@ ${message.value}`,
class="btn btn-lg w-full shadow-lg transition-all duration-300"
:class="[
status === 'success'
? 'btn-success text-white shadow-success/25'
? 'btn-success text-white pointer-events-none'
: status === 'error'
? 'btn-error text-white shadow-error/25'
: 'btn-primary shadow-primary/25 hover:shadow-xl hover:shadow-primary/30',
? 'btn-error text-white pointer-events-none'
: 'btn-primary',
]"
:disabled="status === 'sending' || status === 'success'"
:disabled="status === 'sending'"
>
<template v-if="status === 'sending'">
<span
@@ -249,15 +253,15 @@ ${message.value}`,
{{ siteConfig.contact.form.sending }}
</template>
<template v-else-if="status === 'success'">
<CheckCircleIcon class="w-5 h-5" />
<Icon name="check-circle" class="w-5 h-5" />
{{ siteConfig.contact.form.success }}
</template>
<template v-else-if="status === 'error'">
<XCircleIcon class="w-5 h-5" />
<Icon name="x-circle" class="w-5 h-5" />
{{ errorMessage || siteConfig.contact.form.error }}
</template>
<template v-else>
<PaperAirplaneIcon class="w-5 h-5" />
<Icon name="paper-airplane" class="w-5 h-5" />
{{ siteConfig.contact.form.submit }}
</template>
</button>
@@ -273,7 +277,7 @@ ${message.value}`,
:href="`mailto:${siteConfig.contact.direct.email}`"
class="link font-medium inline-flex items-center gap-2 text-base-content hover:text-primary"
>
<EnvelopeIcon class="w-5 h-5" />
<Icon name="envelope" class="w-5 h-5" />
{{ siteConfig.contact.direct.email }}
</a>
</div>

View File

@@ -1,8 +1,8 @@
---
import { siteConfig } from "../../config/site";
import { Icon } from "astro-icon/components";
import Icon from "../Icon.astro";
import Section from "../Section.astro";
import RotatingText from "../RotatingText.astro";
import RotatingText from "../RotatingText.vue";
import StatusIndicator from "../StatusIndicator.vue";
const rotatingText = (siteConfig.hero as any).rotatingText as
@@ -22,29 +22,31 @@ const rotatingText = (siteConfig.hero as any).rotatingText as
<div class="relative max-w-7xl mx-auto px-6">
<div class="text-center max-w-4xl mx-auto">
<StatusIndicator client:load />
<StatusIndicator client:idle />
<h1
class="text-4xl sm:text-5xl lg:text-6xl xl:text-7xl font-extrabold text-white leading-tight tracking-tight mb-6"
>
{
siteConfig.hero.mainTitle
.split("{rotating}")
.map((part, index, array) => (
rotatingText ? (
<>
{part}
{index < array.length - 1 && rotatingText && (
<RotatingText items={rotatingText} />
)}
<RotatingText items={rotatingText} client:idle />
<span class="block">
{siteConfig.hero.mainTitle
.replace("{rotating}", "")
.trim()}
</span>
</>
))
) : (
siteConfig.hero.mainTitle
)
}
</h1>
<p
class="text-lg sm:text-xl text-white max-w-2xl mx-auto mb-10 leading-relaxed"
>
{siteConfig.hero.description}.
{siteConfig.description}.
</p>
<div
@@ -54,14 +56,14 @@ const rotatingText = (siteConfig.hero as any).rotatingText as
href="#contact"
class="btn btn-accent btn-lg shadow-lg shadow-accent/25 hover:shadow-xl hover:shadow-accent/30"
>
<Icon name="heroicons:bolt" class="w-5 h-5" />
<Icon name="bolt" class="w-5 h-5" />
{siteConfig.hero.cta}
</a>
<a
href="#services"
class="btn btn-outline btn-lg border-white text-white hover:bg-white hover:text-neutral hover:border-white transition-all duration-300"
>
<Icon name="heroicons:chevron-down" class="w-5 h-5" />
<Icon name="chevron-down" class="w-5 h-5" />
{siteConfig.hero.secondaryCta}
</a>
</div>

View File

@@ -1,6 +1,6 @@
---
import { siteConfig } from "../../config/site";
import { Icon } from "astro-icon/components";
import Icon from "../Icon.astro";
import Section from "../Section.astro";
const variantStyles: Record<string, string> = {

29
src/config/icons.ts Normal file
View File

@@ -0,0 +1,29 @@
export const icons = {
bolt: `<path d="M3.75 13.5L14.25 2.25L12 10.5H20.25L9.75 21.75L12 13.5H3.75Z" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>`,
"chevron-down": `<path d="M19.5 8.25L12 15.75L4.5 8.25" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>`,
"bars-3-bottom-left": `<path d="M3.75 6.75H20.25M3.75 12H20.25M3.75 17.25H12" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>`,
"computer-desktop": `<path d="M9 17.25V18.2574C9 19.053 8.68393 19.8161 8.12132 20.3787L7.5 21H16.5L15.8787 20.3787C15.3161 19.8161 15 19.053 15 18.2574V17.25M21 5.25V15C21 16.2426 19.9926 17.25 18.75 17.25H5.25C4.00736 17.25 3 16.2426 3 15V5.25M21 5.25C21 4.00736 19.9926 3 18.75 3H5.25C4.00736 3 3 4.00736 3 5.25M21 5.25V12C21 13.2426 19.9926 14.25 18.75 14.25H5.25C4.00736 14.25 3 13.2426 3 12V5.25" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>`,
"device-phone-mobile": `<path d="M10.5 1.5H8.25C7.00736 1.5 6 2.50736 6 3.75V20.25C6 21.4926 7.00736 22.5 8.25 22.5H15.75C16.9926 22.5 18 21.4926 18 20.25V3.75C18 2.50736 16.9926 1.5 15.75 1.5H13.5M10.5 1.5V3H13.5V1.5M10.5 1.5H13.5M10.5 20.25H13.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>`,
"cog-6-tooth": `<path d="M9.59356 3.94014C9.68397 3.39768 10.1533 3.00009 10.7033 3.00009H13.2972C13.8472 3.00009 14.3165 3.39768 14.4069 3.94014L14.6204 5.22119C14.6828 5.59523 14.9327 5.9068 15.2645 6.09045C15.3387 6.13151 15.412 6.17393 15.4844 6.21766C15.8095 6.41393 16.2048 6.47495 16.5604 6.34175L17.7772 5.88587C18.2922 5.69293 18.8712 5.9006 19.1462 6.37687L20.4432 8.6233C20.7181 9.09957 20.6085 9.70482 20.1839 10.0544L19.1795 10.8812C18.887 11.122 18.742 11.4938 18.7491 11.8726C18.7498 11.915 18.7502 11.9575 18.7502 12.0001C18.7502 12.0427 18.7498 12.0852 18.7491 12.1275C18.742 12.5064 18.887 12.8782 19.1795 13.119L20.1839 13.9458C20.6085 14.2953 20.7181 14.9006 20.4432 15.3769L19.1462 17.6233C18.8712 18.0996 18.2922 18.3072 17.7772 18.1143L16.5604 17.6584C16.2048 17.5252 15.8095 17.5862 15.4844 17.7825C15.412 17.8263 15.3387 17.8687 15.2645 17.9097C14.9327 18.0934 14.6828 18.4049 14.6204 18.779L14.4069 20.06C14.3165 20.6025 13.8472 21.0001 13.2972 21.0001H10.7033C10.1533 21.0001 9.68397 20.6025 9.59356 20.06L9.38005 18.779C9.31771 18.4049 9.06774 18.0934 8.73597 17.9097C8.66179 17.8687 8.58847 17.8263 8.51604 17.7825C8.19101 17.5863 7.79568 17.5252 7.44011 17.6584L6.22325 18.1143C5.70826 18.3072 5.12926 18.0996 4.85429 17.6233L3.55731 15.3769C3.28234 14.9006 3.39199 14.2954 3.81657 13.9458L4.82092 13.119C5.11343 12.8782 5.25843 12.5064 5.25141 12.1276C5.25063 12.0852 5.25023 12.0427 5.25023 12.0001C5.25023 11.9575 5.25063 11.915 5.25141 11.8726C5.25843 11.4938 5.11343 11.122 4.82092 10.8812L3.81657 10.0544C3.39199 9.70484 3.28234 9.09958 3.55731 8.62332L4.85429 6.37688C5.12926 5.90061 5.70825 5.69295 6.22325 5.88588L7.4401 6.34176C7.79566 6.47496 8.19099 6.41394 8.51603 6.21767C8.58846 6.17393 8.66179 6.13151 8.73597 6.09045C9.06774 5.9068 9.31771 5.59523 9.38005 5.22119L9.59356 3.94014Z" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/><path d="M15 12C15 13.6569 13.6569 15 12 15C10.3431 15 9 13.6569 9 12C9 10.3432 10.3431 9.00001 12 9.00001C13.6569 9.00001 15 10.3432 15 12Z" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>`,
lifebuoy: `<path d="M16.7124 4.3299C17.2999 4.69153 17.8548 5.12691 18.364 5.63604C18.8731 6.14517 19.3085 6.70012 19.6701 7.28763M16.7124 4.3299L13.2636 8.46838M16.7124 4.3299C13.8316 2.5567 10.1684 2.5567 7.28763 4.3299M19.6701 7.28763L15.5316 10.7364M19.6701 7.28763C21.4433 10.1684 21.4433 13.8316 19.6701 16.7124M15.5316 10.7364C15.3507 10.2297 15.0574 9.75408 14.6517 9.34835C14.2459 8.94262 13.7703 8.6493 13.2636 8.46838M15.5316 10.7364C15.8228 11.5519 15.8228 12.4481 15.5316 13.2636M13.2636 8.46838C12.4481 8.17721 11.5519 8.17721 10.7364 8.46838M15.5316 13.2636C15.3507 13.7703 15.0574 14.2459 14.6517 14.6517C14.2459 15.0574 13.7703 15.3507 13.2636 15.5316M15.5316 13.2636L19.6701 16.7124M19.6701 16.7124C19.3085 17.2999 18.8731 17.8548 18.364 18.364C17.8548 18.8731 17.2999 19.3085 16.7124 19.6701M16.7124 19.6701L13.2636 15.5316M16.7124 19.6701C13.8316 21.4433 10.1684 21.4433 7.28763 19.6701M13.2636 15.5316C12.4481 15.8228 11.5519 15.8228 10.7364 15.5316M10.7364 15.5316C10.2297 15.3507 9.75408 15.0574 9.34835 14.6517C8.94262 14.2459 8.6493 13.7703 8.46838 13.2636M10.7364 15.5316L7.28763 19.6701M7.28763 19.6701C6.70012 19.3085 6.14517 18.8731 5.63604 18.364C5.12691 17.8548 4.69153 17.2999 4.3299 16.7124M4.3299 16.7124L8.46838 13.2636M4.3299 16.7124C2.5567 13.8316 2.5567 10.1684 4.3299 7.28763M8.46838 13.2636C8.17721 12.4481 8.17721 11.5519 8.46838 10.7364M8.46838 10.7364C8.6493 10.2297 8.94262 9.75408 9.34835 9.34835C9.75408 8.94262 10.2297 8.6493 10.7364 8.46838M8.46838 10.7364L4.3299 7.28763M10.7364 8.46838L7.28763 4.3299M7.28763 4.3299C6.70012 4.69153 6.14517 5.12691 5.63604 5.63604C5.12691 6.14517 4.69153 6.70013 4.3299 7.28763" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>`,
"check-circle": `<path d="M9 12.75L11.25 15L15 9.75M21 12C21 16.9706 16.9706 21 12 21C7.02944 21 3 16.9706 3 12C3 7.02944 7.02944 3 12 3C16.9706 3 21 7.02944 21 12Z" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>`,
users: `<path d="M15 19.1276C15.8329 19.37 16.7138 19.5 17.625 19.5C19.1037 19.5 20.5025 19.1576 21.7464 18.5478C21.7488 18.4905 21.75 18.4329 21.75 18.375C21.75 16.0968 19.9031 14.25 17.625 14.25C16.2069 14.25 14.956 14.9655 14.2136 16.0552M15 19.1276V19.125C15 18.0121 14.7148 16.9658 14.2136 16.0552M15 19.1276C15 19.1632 14.9997 19.1988 14.9991 19.2343C13.1374 20.3552 10.9565 21 8.625 21C6.29353 21 4.11264 20.3552 2.25092 19.2343C2.25031 19.198 2.25 19.1615 2.25 19.125C2.25 15.6042 5.10418 12.75 8.625 12.75C11.0329 12.75 13.129 14.085 14.2136 16.0552M12 6.375C12 8.23896 10.489 9.75 8.625 9.75C6.76104 9.75 5.25 8.23896 5.25 6.375C5.25 4.51104 6.76104 3 8.625 3C10.489 3 12 4.51104 12 6.375ZM20.25 8.625C20.25 10.0747 19.0747 11.25 17.625 11.25C16.1753 11.25 15 10.0747 15 8.625C15 7.17525 16.1753 6 17.625 6C19.0747 6 20.25 7.17525 20.25 8.625Z" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>`,
"x-circle": `<path d="M9.75 9.75L14.25 14.25M14.25 9.75L9.75 14.25M21 12C21 16.9706 16.9706 21 12 21C7.02944 21 3 16.9706 3 12C3 7.02944 7.02944 3 12 3C16.9706 3 21 7.02944 21 12Z" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>`,
"paper-airplane": `<path d="M5.99972 12L3.2688 3.12451C9.88393 5.04617 16.0276 8.07601 21.4855 11.9997C16.0276 15.9235 9.884 18.9535 3.26889 20.8752L5.99972 12ZM5.99972 12L13.5 12" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>`,
envelope: `<path d="M21.75 6.75V17.25C21.75 18.4926 20.7426 19.5 19.5 19.5H4.5C3.25736 19.5 2.25 18.4926 2.25 17.25V6.75M21.75 6.75C21.75 5.50736 20.7426 4.5 19.5 4.5H4.5C3.25736 4.5 2.25 5.50736 2.25 6.75M21.75 6.75V6.99271C21.75 7.77405 21.3447 8.49945 20.6792 8.90894L13.1792 13.5243C12.4561 13.9694 11.5439 13.9694 10.8208 13.5243L3.32078 8.90894C2.65535 8.49945 2.25 7.77405 2.25 6.99271V6.75" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>`,
slopfree: `<path d="M23 15V18C23 18.5 22.64 18.88 22.17 18.97L20.2 17H21V16H19.2L19 15.8V14C19 11.24 16.76 9 14 9H12.2L10.2 7H11V5.73C10.4 5.39 10 4.74 10 4C10 2.9 10.9 2 12 2S14 2.9 14 4C14 4.74 13.6 5.39 13 5.73V7H14C17.87 7 21 10.13 21 14H22C22.55 14 23 14.45 23 15M8.5 13.5C7.4 13.5 6.5 14.4 6.5 15.5S7.4 17.5 8.5 17.5 10.5 16.61 10.5 15.5 9.61 13.5 8.5 13.5M22.11 21.46L20.84 22.73L19.89 21.78C19.62 21.92 19.32 22 19 22H5C3.9 22 3 21.11 3 20V19H2C1.45 19 1 18.55 1 18V15C1 14.45 1.45 14 2 14H3C3 11.53 4.29 9.36 6.22 8.11L1.11 3L2.39 1.73L22.11 21.46M18.11 20L15.6 17.5C15.57 17.5 15.53 17.5 15.5 17.5C14.4 17.5 13.5 16.61 13.5 15.5C13.5 15.47 13.5 15.43 13.5 15.4L7.7 9.59C6.1 10.42 5 12.08 5 14V16H3V17H5V20H18.11Z" fill="currentColor"/>`,
} as const;
export type IconName = keyof typeof icons;

View File

@@ -1,3 +1,5 @@
import type { IconName } from "./icons";
type Card = {
title: string;
content: string;
@@ -5,6 +7,7 @@ type Card = {
};
export const siteConfig = {
siteUrl: "https://atash.dev",
name: "Atash Consulting",
description: "Independent Software Consulting based in Edmonton, Alberta",
@@ -55,14 +58,13 @@ export const siteConfig = {
className: "bg-accent text-accent-content px-2",
},
],
description: "Independent Software Consulting based in Edmonton, Alberta",
cta: "Discuss Your Project",
secondaryCta: "View Services",
trustedText: "Trusted expertise in",
features: [
{ icon: "heroicons:computer-desktop", text: "Web Development" },
{ icon: "heroicons:device-phone-mobile", text: "Mobile Apps" },
{ icon: "heroicons:cog-6-tooth", text: "DevOps" },
{ icon: "computer-desktop", text: "Web Development" },
{ icon: "device-phone-mobile", text: "Mobile Apps" },
{ icon: "cog-6-tooth", text: "DevOps" },
],
},
@@ -73,28 +75,28 @@ export const siteConfig = {
title: "Web Development",
content: "Functional, accessible, and beautiful websites.",
variant: "primary",
icon: "heroicons:computer-desktop",
icon: "computer-desktop",
},
{
title: "Mobile App Development",
content: "iOS, Android, and cross-platform mobile applications.",
variant: "secondary",
icon: "heroicons:device-phone-mobile",
icon: "device-phone-mobile",
},
{
title: "DevOps",
content: "From CI/CD pipelines to end-to-end automation.",
content: "CI/CD pipelines end-to-end automation.",
variant: "secondary",
icon: "heroicons:cog-6-tooth",
icon: "cog-6-tooth",
},
{
title: "IT Support Processes",
content:
"Expert technical guidance backed by over a decade of experience.",
variant: "primary",
icon: "heroicons:lifebuoy",
icon: "lifebuoy",
},
] as (Card & { icon: string })[],
] as (Card & { icon: IconName })[],
},
whyUs: {
@@ -106,8 +108,8 @@ export const siteConfig = {
variant: "primary",
},
{
title: "Built With Care",
content: "Built with rigorous testing and attention to detail",
title: "Slop-free Guarantee",
content: "Hand-crafted code built with care",
variant: "secondary",
},
{
@@ -125,21 +127,24 @@ export const siteConfig = {
clients: [
{
name: "SAIKYO Softworks",
name: "Saikyo Softworks",
logo: "/clients/SaikyoSoftworks.webp",
href: "https://saikyosoft.works",
},
{
name: "Royer Mortgages",
logo: "/clients/RoyerMortgages.webp",
href: "https://royermortgages.com",
},
{
name: "Marew Consulting",
name: "Marew Consulting Ltd",
logo: "/clients/MarewConsulting.webp",
href: "https://marewconsulting.ca",
},
{
name: "Hutch Mortgages",
logo: "/clients/HutchMortgages.webp",
},
{
name: "Rush Home Mortgages",
href: "https://hutchmortgages.com",
},
],

View File

@@ -2,19 +2,41 @@
import Header from "../components/Header.astro";
import Footer from "../components/Footer.astro";
import { siteConfig } from "../config/site";
import "@fontsource-variable/roboto-slab";
import "../styles/global.css";
interface Props {
title?: string;
description?: string;
ogImage?: {
url: string;
width: number;
height: number;
type: string;
alt: string;
};
}
const { title = siteConfig.name, description = siteConfig.description } =
Astro.props;
const {
title = siteConfig.name,
description = siteConfig.description,
ogImage,
} = Astro.props;
const metaTitle =
title === siteConfig.name ? title : `${title} | ${siteConfig.name}`;
const resolvedOgImage = ogImage || {
url: "/logo.webp",
width: 1024,
height: 1024,
type: "image/webp",
alt: "Atash Consulting",
};
const siteUrl = siteConfig.siteUrl || Astro.url.href;
const resolvedOgImageUrl = new URL(resolvedOgImage.url, siteUrl).href;
const isProd = import.meta.env.PROD;
---
<!doctype html>
@@ -25,9 +47,53 @@ const metaTitle =
<link rel="icon" type="image/x-icon" href="favicon.ico" />
<meta name="generator" content={Astro.generator} />
<meta name="description" content={description} />
<meta property="og:title" content={metaTitle} />
<meta property="og:description" content={description} />
<meta property="og:type" content="website" />
<meta property="og:url" content={siteUrl} />
<meta property="og:image" content={resolvedOgImageUrl} />
<meta
property="og:image:width"
content={String(resolvedOgImage.width)}
/>
<meta
property="og:image:height"
content={String(resolvedOgImage.height)}
/>
<meta property="og:image:type" content={resolvedOgImage.type} />
<meta property="og:image:alt" content={resolvedOgImage.alt} />
<meta name="theme-color" content="#ffffff" />
<link rel="canonical" href={siteUrl} />
<link
rel="preload"
href="/fonts/roboto.woff2"
as="font"
type="font/woff2"
crossorigin="anonymous"
/>
<title>{metaTitle}</title>
{
isProd && (
<script>
(function() {
function loadAnalytics() {
var script = document.createElement('script');
script.src = "https://analytics.atri.dad/script.js";
script.defer = true;
script.setAttribute('data-website-id', 'c7e24af4-5f14-4881-9c25-85a97abda9f1');
document.head.appendChild(script);
}
if ('requestIdleCallback' in window) {
requestIdleCallback(loadAnalytics, { timeout: 2000 });
} else {
setTimeout(loadAnalytics, 2000);
}
})();
</script>
)
}
</head>
<body class="min-h-screen flex flex-col bg-base-100 font-sans antialiased">
<body class="min-h-screen flex flex-col bg-base-100 antialiased">
<Header />
<main class="grow flex flex-col">
<slot />

View File

@@ -19,7 +19,7 @@ export const GET: APIRoute = async () => {
status: 200,
headers: {
"Content-Type": "application/json",
"Cache-Control": "no-cache, no-store, must-revalidate",
"Cache-Control": "public, max-age=60, stale-while-revalidate=300",
},
},
);

View File

@@ -12,7 +12,7 @@ import Section from "../components/Section.astro";
const pageMetaInfo = {
title: siteConfig.name,
description: `Welcome to ${siteConfig.name} - ${siteConfig.description}`,
description: `${siteConfig.name} - ${siteConfig.description}`,
};
---

View File

@@ -40,11 +40,14 @@ html {
scroll-behavior: smooth;
}
body {
font-family: "Roboto Slab Variable", serif;
@font-face {
font-family: "Roboto Slab";
src: url("/fonts/roboto.woff2") format("woff2");
font-weight: 100 900;
font-style: normal;
font-display: block;
}
.text-rotate:hover,
.text-rotate:hover * {
animation-play-state: running !important;
body {
font-family: "Roboto Slab", serif;
}