Skip to content

Commit 7ca0335

Browse files
committed
Added some SEO stuff
1 parent 51b9e06 commit 7ca0335

File tree

10 files changed

+179
-17
lines changed

10 files changed

+179
-17
lines changed

README.md

+11-9
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,23 @@
11
# Codeshare.app
22

3-
[Codeshare.app](https://codeshare.app) A mininal code bin sharing app, I wanted a simple but powerful for devs pastebin so, I created this small tool to share code snippets
4-
5-
## Stack
6-
7-
- Nuxt 3
8-
- Tailwindcss
9-
- Nuxt UI
10-
- Turso Database
11-
- Monaco editor
3+
[Codeshare.app](https://codeshare.app) A mininal code bin sharing app, I wanted a simple but powerful for devs pastebin so, I created this small tool using monaco editor, I've made is as frictionless as possible, kept the UI similar to VS Code.
124

135
## Pending tasks
146

157
1. Keyboard shortcuts
168
2. Diff editor
179
3. Refactor (lot of code repeated, didn't think it through) - make common and reuse components and composables
1810
4. Sharable diff editor
11+
5. File icons (feels like a lot of work)
12+
6. Password protected bins (simple password based middleware)
13+
14+
## Stack
15+
16+
- [Nuxt 3](https://nuxt.com)
17+
- [Tailwindcss](https://tailwindcss.com)
18+
- [Nuxt UI](https://ui.nuxt.com)
19+
- [Turso Database](https://turso.tech)
20+
- [Monaco editor](https://microsoft.github.io/monaco-editor/)
1921

2022
## ENV Vars
2123

app.vue

+19-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,25 @@
33
<NuxtPage />
44
<UNotifications />
55
</template>
6-
6+
<script setup>
7+
useSeoMeta({
8+
ogTitle: 'Codeshare - Pastebin for developers',
9+
description: 'Codeshare allows you to share code with other developers. Create and share code snippets without signing up.',
10+
ogDescription: 'Codeshare allows you to share code with other developers. Create and share code snippets without signing up.',
11+
ogImage: 'https://codeshare.app/social-card.png',
12+
ogImageWidth: "1600",
13+
ogImageHeight: "900",
14+
ogUrl: 'https://codeshare.app',
15+
ogImageType: 'image/png',
16+
ogImageAlt: 'Image describing Codeshare.apps functionality, a code editor with syntax highlighting and its features.',
17+
twitterTitle: 'Codeshare - Pastebin for developers',
18+
ogType: 'website',
19+
ogLocale: 'en_US',
20+
twitterDescription: 'Codeshare allows you to share code with other developers. Create and share code snippets without signing up.',
21+
twitterCard: 'summary_large_image',
22+
themeColor: '#111827',
23+
})
24+
</script>
725
<style>
826
html,
927
body {

components/App/Navbar/index.vue

+7-2
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,14 @@
1010
<UInput
1111
v-if="publishEnabled"
1212
v-model="snippet.title"
13-
placeholder="file.txt"
13+
placeholder="untitled.txt"
1414
size="2xs"
1515
/>
16+
<span v-else class="text-xs">{{ title }}</span>
1617
<div
1718
class="border-l divide-x divide-white/10 border-white/10 flex items-center"
1819
>
19-
<UTooltip text="Download file">
20+
<UTooltip text="Download file" @click="$emit('download')">
2021
<button class="border-white/10 h-9 px-3 text-sm hover:bg-gray-950">
2122
<Icon name="i-lucide-download" class="h-4 w-4" />
2223
</button>
@@ -47,6 +48,10 @@ defineProps({
4748
type: Boolean,
4849
required: true,
4950
},
51+
title: {
52+
type: String,
53+
required: true,
54+
},
5055
});
5156
const { snippet } = useEditor();
5257
</script>

composables/editor.js

+20-4
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ export const useEditor = () => {
1313
autoSurround: "languageDefined",
1414
scrollBeyondLastLine: false,
1515
fontLigatures: true,
16-
fontFamily: "Cascadia Code",
16+
fontFamily: "Cascadia Code, Fira Code, monospace",
1717
minimap: {
1818
enabled: false,
1919
},
@@ -89,7 +89,7 @@ export const useEditor = () => {
8989
const confirmPublish = async () => {
9090
try {
9191
loading.value = true;
92-
confirmationModal.value = false;
92+
9393
const data = await $fetch("/api/codebin", {
9494
method: "POST",
9595
body: snippet.value,
@@ -104,19 +104,34 @@ export const useEditor = () => {
104104
icon: "i-heroicons-check-circle",
105105
});
106106
copy(`${window.location.origin}/${data.uid}`);
107+
confirmationModal.value = false;
107108
navigateTo(`/${data.uid}`);
108109
} catch (error) {
110+
loading.value = false;
109111
toast.add({
110112
title: "Error",
111113
description: error.message,
112114
color: "red",
113115
icon: "i-heroicons-x-circle",
114116
});
115-
} finally {
116-
loading.value = false;
117117
}
118118
};
119119

120+
const downloadSnippet = () => {
121+
const blob = new Blob([snippet.value.body], {
122+
type: "text/plain;charset=utf-8",
123+
});
124+
saveAs(blob, snippet.value.title || "untitled.txt");
125+
}
126+
127+
function saveAs(blob, fileName) {
128+
const link = document.createElement("a");
129+
link.href = window.URL.createObjectURL(blob);
130+
link.download = fileName;
131+
link.click();
132+
link.remove();
133+
}
134+
120135
return {
121136
MONACO_EDITOR_OPTIONS,
122137
selectedLanguage,
@@ -135,5 +150,6 @@ export const useEditor = () => {
135150
publishSnippet,
136151
confirmPublish,
137152
copySnippet,
153+
downloadSnippet
138154
};
139155
};

nuxt.config.ts

+6
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,16 @@ export default defineNuxtConfig({
77
"@nuxtjs/google-fonts",
88
"@nuxtjs/fontaine",
99
"@vueuse/nuxt",
10+
"nuxt-security"
1011
],
1112
ui: {
1213
icons: ["heroicons", "lucide"],
1314
},
15+
security: {
16+
headers: {
17+
crossOriginEmbedderPolicy: process.env.NODE_ENV === 'development' ? 'unsafe-none' : 'require-corp',
18+
},
19+
},
1420
colorMode: {
1521
preference: "dark",
1622
},

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
"drizzle-kit": "^0.20.13",
2020
"nuxt": "^3.9.1",
2121
"nuxt-icon": "^0.6.8",
22+
"nuxt-security": "^1.0.1",
2223
"vue": "^3.4.13",
2324
"vue-router": "^4.2.5"
2425
},

pages/[id].vue

+3
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
<AppNavbar
44
@publish="publishSnippet"
55
@copy="copySnippet"
6+
@download="downloadSnippet"
67
:publish-enabled="false"
8+
:title="snippet.title"
79
/>
810
<div class="flex-1 flex">
911
<AppSidebar />
@@ -119,6 +121,7 @@ const {
119121
publishSnippet,
120122
confirmPublish,
121123
copySnippet,
124+
downloadSnippet,
122125
} = useEditor();
123126
const route = useRoute();
124127
const { data: snippet } = await useFetch(`/api/codebin/${route.params.id}`);

pages/index.vue

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<template>
22
<main class="h-screen flex flex-col text-white">
3-
<AppNavbar @publish="publishSnippet" @copy="copySnippet" publishEnabled />
3+
<AppNavbar @publish="publishSnippet" @copy="copySnippet" @download="downloadSnippet" publishEnabled />
44
<div class="flex-1 flex">
55
<AppSidebar />
66
<ClientOnly>
@@ -125,6 +125,7 @@ const {
125125
publishSnippet,
126126
confirmPublish,
127127
copySnippet,
128+
downloadSnippet
128129
} = useEditor();
129130
130131
useHead({

pnpm-lock.yaml

+110
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

public/social-card.png

1 MB
Loading

0 commit comments

Comments
 (0)