Skip to content

Commit

Permalink
chore: 🎉 first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
dubem-design committed Dec 19, 2024
0 parents commit 5b9984e
Show file tree
Hide file tree
Showing 11 changed files with 5,949 additions and 0 deletions.
24 changes: 24 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Nuxt dev/build outputs
.output
.data
.nuxt
.nitro
.cache
dist

# Node dependencies
node_modules

# Logs
logs
*.log

# Misc
.DS_Store
.fleet
.idea

# Local env files
.env
.env.*
!.env.example
75 changes: 75 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# Nuxt 3 Minimal Starter

Look at the [Nuxt 3 documentation](https://nuxt.com/docs/getting-started/introduction) to learn more.

## Setup

Make sure to install the dependencies:

```bash
# npm
npm install

# pnpm
pnpm install

# yarn
yarn install

# bun
bun install
```

## Development Server

Start the development server on `http://localhost:3000`:

```bash
# npm
npm run dev

# pnpm
pnpm run dev

# yarn
yarn dev

# bun
bun run dev
```

## Production

Build the application for production:

```bash
# npm
npm run build

# pnpm
pnpm run build

# yarn
yarn build

# bun
bun run build
```

Locally preview production build:

```bash
# npm
npm run preview

# pnpm
pnpm run preview

# yarn
yarn preview

# bun
bun run preview
```

Check out the [deployment documentation](https://nuxt.com/docs/getting-started/deployment) for more information.
89 changes: 89 additions & 0 deletions app.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<template>
<div class="flex justify-center h-screen items-start bg-gray-100 pt-20">
<div class="border p-8 w-96 bg-white flex flex-col gap-8">
<h1 class="text-xl font-medium">Christmas greeting card maker</h1>
<div class="border aspect-square banner-here relative" v-html="svg"></div>
<form class="flex flex-col gap-4">
<input type="text" v-model="form.name" class="px-4 py-1 border w-full" placeholder="Enter name" />
<input type="text" v-model="form.greeting" class="px-4 py-1 border w-full" placeholder="Enter greeting" />
<input type="file" accept=".png, .jpg, .jpeg" @change="handleFileChange" class="px-4 py-1 border w-full" />
<small class="text-gray-400">Must be an image below 100kb, png, jpeg and jpg formats only.</small>
<button class="bg-indigo-500 text-white px-4 py-2" @click.prevent="downloadSvgAsJpeg(svg)">Download</button>
</form>
</div>
</div>
</template>

<script setup lang="ts">
import { createSSRApp } from "vue";
import { renderToString } from "@vue/server-renderer";
import { useLocalStorage, watchDebounced } from "@vueuse/core";
import satori from "satori";
import { html } from "satori-html";
import ChristmasCard from "./components/ChristmasCard.vue";
const form = useLocalStorage("app-form", { name: "", greeting: "Merry Christmas", photo: '' });
const svg = ref("");
const fonts = ref([]);
onMounted(async () => {
fonts.value = await loadFonts([{ name: "InstrumentSans", url: "/fonts/InstrumentSans-Regular.ttf" }]);
refreshGraphics();
});
watchDebounced(form, refreshGraphics, { deep: true, debounce: 500, maxWait: 1000 });
async function loadFonts(fonts) {
return Promise.all(
fonts.map(async (font) => ({
...font,
data: await (await fetch(font.url)).arrayBuffer(),
}))
);
}
async function refreshGraphics() {
const content = await renderToHTML(ChristmasCard, form.value);
const markup = html(content);
svg.value = await satori(markup, { width: 1080, height: 1080, fonts: fonts.value });
}
async function handleFileChange(event: Event) {
const file = (event.target as HTMLInputElement)?.files?.[0];
if (file && file.size > 100 * 1024) throw new Error("File size must be below 100kb");
const reader = new FileReader();
reader.onload = () => (form.value.photo = reader.result as string);
reader.readAsDataURL(file);
}
async function renderToHTML(Component, props = {}) {
return await renderToString(createSSRApp(Component, props));
}
function downloadSvgAsJpeg(svgString, filename = "image.jpeg") {
const blob = new Blob([svgString], { type: "image/svg+xml" });
const url = URL.createObjectURL(blob);
const img = new Image();
img.onload = () => {
const canvas = document.createElement("canvas");
canvas.width = canvas.height = 1080;
canvas.getContext("2d")?.drawImage(img, 0, 0, 1080, 1080);
const link = document.createElement("a");
link.href = canvas.toDataURL("image/jpeg");
link.download = filename;
link.click();
URL.revokeObjectURL(url);
};
img.src = url;
}
</script>

<style>
.banner-here svg {
width: 100%;
height: 100%;
}
</style>
13 changes: 13 additions & 0 deletions components/ChristmasCard.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<template>
<div class="w-full bg-red-500 h-full flex flex-col text-white text-7xl font-bold p-10 items-center justify-center"
style="background-image: url(/img/sincerely-media-8EhZobADF8M-unsplash.jpg);">
<div class="font-bold mb-8 " style="font-size: 100px;"> {{ greeting }}</div>
<img v-if="photo" :src="photo" class="rounded-full border-4 border-red-900 mb-8" style="width:400px;height:400px">
<div class="bg-red-500 px-2 py-2">From</div>
<div> {{ name || 'Add your name here' }}</div>
</div>
</template>

<script setup lang="ts">
defineProps(['name', 'greeting', 'photo'])
</script>
5 changes: 5 additions & 0 deletions nuxt.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export default defineNuxtConfig({
ssr: false,
devtools: { enabled: true },
modules: ["@nuxtjs/tailwindcss"],
});
22 changes: 22 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"name": "build-a-greeting-card-maker-with-vue-3-and-satori",
"private": true,
"type": "module",
"scripts": {
"build": "nuxt build",
"dev": "nuxt dev",
"generate": "nuxt generate",
"preview": "nuxt preview",
"postinstall": "nuxt prepare"
},
"dependencies": {
"@vue/server-renderer": "^3.5.13",
"@vueuse/core": "^12.0.0",
"nuxt": "^3.14.1592",
"satori": "^0.12.0",
"satori-html": "^0.3.2"
},
"devDependencies": {
"@nuxtjs/tailwindcss": "^6.12.2"
}
}
Binary file added public/favicon.ico
Binary file not shown.
Binary file added public/fonts/InstrumentSans-Regular.ttf
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
// https://nuxt.com/docs/guide/concepts/typescript
"extends": "./.nuxt/tsconfig.json"
}
Loading

0 comments on commit 5b9984e

Please sign in to comment.