@geenius/seo 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +16 -3
- package/packages/convex/dist/index.d.ts +56 -0
- package/packages/convex/dist/index.js +133 -0
- package/packages/convex/dist/index.js.map +1 -0
- package/packages/react/README.md +1 -1
- package/packages/react/dist/index.d.ts +156 -0
- package/packages/react/dist/index.js +567 -0
- package/packages/react/dist/index.js.map +1 -0
- package/packages/react-css/README.md +1 -1
- package/packages/react-css/dist/index.cjs +571 -0
- package/packages/react-css/dist/index.cjs.map +1 -0
- package/packages/react-css/{src/seo.css → dist/index.css} +7 -153
- package/packages/react-css/dist/index.css.map +1 -0
- package/packages/react-css/dist/index.d.cts +53 -0
- package/packages/react-css/dist/index.d.ts +53 -0
- package/packages/react-css/dist/index.js +539 -0
- package/packages/react-css/dist/index.js.map +1 -0
- package/packages/shared/README.md +1 -1
- package/packages/shared/dist/index.d.ts +262 -0
- package/packages/shared/dist/index.js +381 -0
- package/packages/shared/dist/index.js.map +1 -0
- package/packages/solidjs/README.md +1 -1
- package/packages/solidjs/dist/index.d.ts +133 -0
- package/packages/solidjs/dist/index.js +416 -0
- package/packages/solidjs/dist/index.js.map +1 -0
- package/packages/solidjs-css/README.md +1 -1
- package/packages/solidjs-css/dist/index.cjs +399 -0
- package/packages/solidjs-css/dist/index.cjs.map +1 -0
- package/packages/solidjs-css/{src/seo.css → dist/index.css} +7 -153
- package/packages/solidjs-css/dist/index.css.map +1 -0
- package/packages/solidjs-css/dist/index.d.cts +53 -0
- package/packages/solidjs-css/dist/index.d.ts +53 -0
- package/packages/solidjs-css/dist/index.js +367 -0
- package/packages/solidjs-css/dist/index.js.map +1 -0
- package/.changeset/config.json +0 -11
- package/.github/CODEOWNERS +0 -1
- package/.github/ISSUE_TEMPLATE/bug_report.md +0 -16
- package/.github/ISSUE_TEMPLATE/feature_request.md +0 -11
- package/.github/PULL_REQUEST_TEMPLATE.md +0 -10
- package/.github/dependabot.yml +0 -11
- package/.github/workflows/ci.yml +0 -23
- package/.github/workflows/release.yml +0 -29
- package/.nvmrc +0 -1
- package/.project/ACCOUNT.yaml +0 -4
- package/.project/IDEAS.yaml +0 -7
- package/.project/PROJECT.yaml +0 -11
- package/.project/ROADMAP.yaml +0 -15
- package/CODE_OF_CONDUCT.md +0 -16
- package/CONTRIBUTING.md +0 -26
- package/SECURITY.md +0 -15
- package/SUPPORT.md +0 -8
- package/packages/convex/package.json +0 -42
- package/packages/convex/src/functions.ts +0 -5
- package/packages/convex/src/mutations.ts +0 -83
- package/packages/convex/src/queries.ts +0 -57
- package/packages/convex/src/schema.ts +0 -23
- package/packages/convex/tsconfig.json +0 -19
- package/packages/convex/tsup.config.ts +0 -18
- package/packages/react/package.json +0 -49
- package/packages/react/src/components/ArticleJsonLd.tsx +0 -42
- package/packages/react/src/components/BreadcrumbsJsonLd.tsx +0 -24
- package/packages/react/src/components/MetaEditor.tsx +0 -147
- package/packages/react/src/components/SEOHead.tsx +0 -107
- package/packages/react/src/components/SEOPreview.tsx +0 -42
- package/packages/react/src/components/SEOScoreCard.tsx +0 -51
- package/packages/react/src/components/SitemapViewer.tsx +0 -36
- package/packages/react/src/components/index.ts +0 -7
- package/packages/react/src/hooks/index.ts +0 -4
- package/packages/react/src/hooks/useSEO.ts +0 -27
- package/packages/react/src/hooks/useSEOAdmin.ts +0 -42
- package/packages/react/src/hooks/useSEOScore.ts +0 -7
- package/packages/react/src/hooks/useSitemap.ts +0 -8
- package/packages/react/src/index.ts +0 -51
- package/packages/react/src/index.tsx +0 -11
- package/packages/react/src/pages/SEOAdminPage.tsx +0 -101
- package/packages/react/src/pages/SEOAnalyticsPage.tsx +0 -96
- package/packages/react/src/pages/index.ts +0 -2
- package/packages/react/tsconfig.json +0 -19
- package/packages/react/tsup.config.ts +0 -12
- package/packages/react-css/package.json +0 -36
- package/packages/react-css/src/components/ArticleJsonLd.tsx +0 -42
- package/packages/react-css/src/components/BreadcrumbsJsonLd.tsx +0 -24
- package/packages/react-css/src/components/MetaEditor.tsx +0 -147
- package/packages/react-css/src/components/SEOHead.tsx +0 -95
- package/packages/react-css/src/components/SEOPreview.tsx +0 -42
- package/packages/react-css/src/components/SEOScoreCard.tsx +0 -42
- package/packages/react-css/src/components/SitemapViewer.tsx +0 -36
- package/packages/react-css/src/components/index.ts +0 -7
- package/packages/react-css/src/index.ts +0 -9
- package/packages/react-css/src/pages/SEOAdminPage.tsx +0 -88
- package/packages/react-css/src/pages/SEOAnalyticsPage.tsx +0 -82
- package/packages/react-css/src/pages/index.ts +0 -2
- package/packages/react-css/tsup.config.ts +0 -2
- package/packages/shared/package.json +0 -42
- package/packages/shared/src/__tests__/seo.test.ts +0 -70
- package/packages/shared/src/config.ts +0 -297
- package/packages/shared/src/index.ts +0 -207
- package/packages/shared/tsconfig.json +0 -18
- package/packages/shared/tsup.config.ts +0 -11
- package/packages/shared/vitest.config.ts +0 -4
- package/packages/solidjs/package.json +0 -45
- package/packages/solidjs/src/components/ArticleJsonLd.tsx +0 -35
- package/packages/solidjs/src/components/BreadcrumbsJsonLd.tsx +0 -24
- package/packages/solidjs/src/components/MetaEditor.tsx +0 -155
- package/packages/solidjs/src/components/SEOHead.tsx +0 -109
- package/packages/solidjs/src/components/SEOPreview.tsx +0 -42
- package/packages/solidjs/src/components/SEOScoreCard.tsx +0 -57
- package/packages/solidjs/src/components/SitemapViewer.tsx +0 -44
- package/packages/solidjs/src/components/index.ts +0 -7
- package/packages/solidjs/src/index.ts +0 -11
- package/packages/solidjs/src/pages/SEOAdminPage.tsx +0 -104
- package/packages/solidjs/src/pages/SEOAnalyticsPage.tsx +0 -102
- package/packages/solidjs/src/pages/index.ts +0 -2
- package/packages/solidjs/src/primitives/index.ts +0 -4
- package/packages/solidjs/src/primitives/useSEO.ts +0 -27
- package/packages/solidjs/src/primitives/useSEOAdmin.ts +0 -42
- package/packages/solidjs/src/primitives/useSEOScore.ts +0 -7
- package/packages/solidjs/src/primitives/useSitemap.ts +0 -8
- package/packages/solidjs/tsconfig.json +0 -20
- package/packages/solidjs/tsup.config.ts +0 -12
- package/packages/solidjs-css/package.json +0 -35
- package/packages/solidjs-css/src/index.ts +0 -5
- package/packages/solidjs-css/src/primitives/index.ts +0 -1
- package/packages/solidjs-css/tsup.config.ts +0 -2
- package/pnpm-workspace.yaml +0 -2
- package/tsconfig.json +0 -23
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import { createMemo } from 'solid-js'
|
|
2
|
-
import { useSEOScore } from '../primitives/useSEOScore'
|
|
3
|
-
import type { SEOMeta } from '@geenius-seo/shared'
|
|
4
|
-
|
|
5
|
-
interface SEOScoreCardProps {
|
|
6
|
-
meta: SEOMeta
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export function SEOScoreCard(props: SEOScoreCardProps) {
|
|
10
|
-
const scoreResult = useSEOScore(() => props.meta)
|
|
11
|
-
|
|
12
|
-
const getScoreColor = createMemo(() => {
|
|
13
|
-
const score = scoreResult().score
|
|
14
|
-
if (score >= 80) return 'text-green-600'
|
|
15
|
-
if (score >= 50) return 'text-yellow-600'
|
|
16
|
-
return 'text-red-600'
|
|
17
|
-
})
|
|
18
|
-
|
|
19
|
-
const getBarColor = createMemo(() => {
|
|
20
|
-
const score = scoreResult().score
|
|
21
|
-
if (score >= 80) return 'bg-green-500'
|
|
22
|
-
if (score >= 50) return 'bg-yellow-500'
|
|
23
|
-
return 'bg-red-500'
|
|
24
|
-
})
|
|
25
|
-
|
|
26
|
-
return (
|
|
27
|
-
<div class="space-y-4 p-4 border border-gray-200 rounded">
|
|
28
|
-
<div class="flex items-center justify-between">
|
|
29
|
-
<h3 class="font-semibold text-gray-900">SEO Score</h3>
|
|
30
|
-
<span class={`text-2xl font-bold ${getScoreColor()}`}>{scoreResult().score}/100</span>
|
|
31
|
-
</div>
|
|
32
|
-
|
|
33
|
-
<div class="space-y-2">
|
|
34
|
-
<div class="h-2 bg-gray-200 rounded overflow-hidden">
|
|
35
|
-
<div
|
|
36
|
-
class={`h-full ${getBarColor()} transition-all`}
|
|
37
|
-
style={{ width: `${scoreResult().score}%` }}
|
|
38
|
-
/>
|
|
39
|
-
</div>
|
|
40
|
-
</div>
|
|
41
|
-
|
|
42
|
-
{scoreResult().issues.length > 0 && (
|
|
43
|
-
<div class="space-y-2">
|
|
44
|
-
<h4 class="text-sm font-semibold text-gray-700">Issues Found</h4>
|
|
45
|
-
<ul class="space-y-1">
|
|
46
|
-
{scoreResult().issues.map((issue, i) => (
|
|
47
|
-
<li key={i} class="text-sm text-red-600 flex items-start">
|
|
48
|
-
<span class="mr-2">•</span>
|
|
49
|
-
{issue}
|
|
50
|
-
</li>
|
|
51
|
-
))}
|
|
52
|
-
</ul>
|
|
53
|
-
</div>
|
|
54
|
-
)}
|
|
55
|
-
</div>
|
|
56
|
-
)
|
|
57
|
-
}
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import { For } from 'solid-js'
|
|
2
|
-
import type { SitemapEntry } from '@geenius-seo/shared'
|
|
3
|
-
|
|
4
|
-
interface SitemapViewerProps {
|
|
5
|
-
entries: SitemapEntry[]
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
export function SitemapViewer(props: SitemapViewerProps) {
|
|
9
|
-
return (
|
|
10
|
-
<div class="overflow-x-auto">
|
|
11
|
-
<table class="w-full text-sm">
|
|
12
|
-
<thead class="bg-gray-100 border-b">
|
|
13
|
-
<tr>
|
|
14
|
-
<th class="text-left p-3">URL</th>
|
|
15
|
-
<th class="text-left p-3">Last Modified</th>
|
|
16
|
-
<th class="text-left p-3">Change Frequency</th>
|
|
17
|
-
<th class="text-left p-3">Priority</th>
|
|
18
|
-
</tr>
|
|
19
|
-
</thead>
|
|
20
|
-
<tbody>
|
|
21
|
-
<For each={props.entries}>
|
|
22
|
-
{(entry, i) => (
|
|
23
|
-
<tr class="border-b hover:bg-gray-50">
|
|
24
|
-
<td class="p-3 font-mono text-xs text-blue-600 break-all">
|
|
25
|
-
<a
|
|
26
|
-
href={entry.url}
|
|
27
|
-
target="_blank"
|
|
28
|
-
rel="noopener noreferrer"
|
|
29
|
-
class="hover:underline"
|
|
30
|
-
>
|
|
31
|
-
{entry.url}
|
|
32
|
-
</a>
|
|
33
|
-
</td>
|
|
34
|
-
<td class="p-3 text-gray-600">{entry.lastmod || '-'}</td>
|
|
35
|
-
<td class="p-3 text-gray-600">{entry.changefreq || '-'}</td>
|
|
36
|
-
<td class="p-3 text-gray-600">{entry.priority || '-'}</td>
|
|
37
|
-
</tr>
|
|
38
|
-
)}
|
|
39
|
-
</For>
|
|
40
|
-
</tbody>
|
|
41
|
-
</table>
|
|
42
|
-
</div>
|
|
43
|
-
)
|
|
44
|
-
}
|
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
import { createSignal, For, Show } from 'solid-js'
|
|
2
|
-
import { useSEOAdmin } from '../primitives/useSEOAdmin'
|
|
3
|
-
import { MetaEditor } from '../components/MetaEditor'
|
|
4
|
-
import { SEOPreview } from '../components/SEOPreview'
|
|
5
|
-
import { SEOScoreCard } from '../components/SEOScoreCard'
|
|
6
|
-
import type { SEOMeta } from '@geenius-seo/shared'
|
|
7
|
-
|
|
8
|
-
export function SEOAdminPage() {
|
|
9
|
-
const { pages, upsertMeta, deleteMeta, isLoading } = useSEOAdmin()
|
|
10
|
-
const [selectedPath, setSelectedPath] = createSignal<string | null>(null)
|
|
11
|
-
const [editingMeta, setEditingMeta] = createSignal<SEOMeta | null>(null)
|
|
12
|
-
|
|
13
|
-
const currentPage = () => pages().find((p) => p.path === selectedPath())
|
|
14
|
-
|
|
15
|
-
const handleSave = async () => {
|
|
16
|
-
const path = selectedPath()
|
|
17
|
-
const meta = editingMeta()
|
|
18
|
-
if (path && meta) {
|
|
19
|
-
await upsertMeta(path, meta)
|
|
20
|
-
setEditingMeta(null)
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
const handleDelete = async () => {
|
|
25
|
-
const path = selectedPath()
|
|
26
|
-
if (path) {
|
|
27
|
-
await deleteMeta(path)
|
|
28
|
-
setSelectedPath(null)
|
|
29
|
-
setEditingMeta(null)
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
return (
|
|
34
|
-
<Show fallback={<div class="p-4">Loading...</div>} when={!isLoading()}>
|
|
35
|
-
<div class="max-w-6xl mx-auto p-6">
|
|
36
|
-
<h1 class="text-3xl font-bold mb-6">SEO Admin</h1>
|
|
37
|
-
|
|
38
|
-
<div class="grid grid-cols-1 lg:grid-cols-4 gap-6">
|
|
39
|
-
{/* Pages List */}
|
|
40
|
-
<div class="lg:col-span-1 border border-gray-200 rounded p-4">
|
|
41
|
-
<h2 class="font-semibold mb-4">Pages</h2>
|
|
42
|
-
<div class="space-y-2">
|
|
43
|
-
<For each={pages()}>
|
|
44
|
-
{(page) => (
|
|
45
|
-
<button
|
|
46
|
-
onClick={() => {
|
|
47
|
-
setSelectedPath(page.path)
|
|
48
|
-
setEditingMeta(page.meta)
|
|
49
|
-
}}
|
|
50
|
-
class={`w-full text-left p-2 rounded text-sm transition ${
|
|
51
|
-
selectedPath() === page.path
|
|
52
|
-
? 'bg-blue-100 text-blue-900'
|
|
53
|
-
: 'hover:bg-gray-100'
|
|
54
|
-
}`}
|
|
55
|
-
>
|
|
56
|
-
{page.path || '/'}
|
|
57
|
-
</button>
|
|
58
|
-
)}
|
|
59
|
-
</For>
|
|
60
|
-
</div>
|
|
61
|
-
</div>
|
|
62
|
-
|
|
63
|
-
{/* Editor and Preview */}
|
|
64
|
-
<Show when={currentPage() && editingMeta()}>
|
|
65
|
-
{(page) => (
|
|
66
|
-
<div class="lg:col-span-3 space-y-6">
|
|
67
|
-
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
|
68
|
-
<div>
|
|
69
|
-
<h2 class="font-semibold mb-4">Edit Metadata</h2>
|
|
70
|
-
<MetaEditor meta={editingMeta()!} onChange={setEditingMeta} />
|
|
71
|
-
</div>
|
|
72
|
-
|
|
73
|
-
<div class="space-y-6">
|
|
74
|
-
<div>
|
|
75
|
-
<h2 class="font-semibold mb-4">Preview</h2>
|
|
76
|
-
<SEOPreview meta={editingMeta()!} />
|
|
77
|
-
</div>
|
|
78
|
-
|
|
79
|
-
<SEOScoreCard meta={editingMeta()!} />
|
|
80
|
-
</div>
|
|
81
|
-
</div>
|
|
82
|
-
|
|
83
|
-
<div class="flex gap-2">
|
|
84
|
-
<button
|
|
85
|
-
onClick={handleSave}
|
|
86
|
-
class="px-4 py-2 bg-green-600 text-white rounded hover:bg-green-700"
|
|
87
|
-
>
|
|
88
|
-
Save
|
|
89
|
-
</button>
|
|
90
|
-
<button
|
|
91
|
-
onClick={handleDelete}
|
|
92
|
-
class="px-4 py-2 bg-red-600 text-white rounded hover:bg-red-700"
|
|
93
|
-
>
|
|
94
|
-
Delete
|
|
95
|
-
</button>
|
|
96
|
-
</div>
|
|
97
|
-
</div>
|
|
98
|
-
)}
|
|
99
|
-
</Show>
|
|
100
|
-
</div>
|
|
101
|
-
</div>
|
|
102
|
-
</Show>
|
|
103
|
-
)
|
|
104
|
-
}
|
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
import { createSignal, createEffect, For, Show } from 'solid-js'
|
|
2
|
-
|
|
3
|
-
interface AnalyticsSummary {
|
|
4
|
-
path: string
|
|
5
|
-
views: number
|
|
6
|
-
avgTimeOnPage: number
|
|
7
|
-
bounceRate: number
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export function SEOAnalyticsPage() {
|
|
11
|
-
const [topPages, setTopPages] = createSignal<AnalyticsSummary[]>([])
|
|
12
|
-
const [isLoading, setIsLoading] = createSignal(false)
|
|
13
|
-
|
|
14
|
-
createEffect(() => {
|
|
15
|
-
setIsLoading(true)
|
|
16
|
-
// Placeholder for Convex query integration
|
|
17
|
-
// const result = await client.query(api.queries.getTopPages, { limit: 10 })
|
|
18
|
-
// setTopPages(result)
|
|
19
|
-
setIsLoading(false)
|
|
20
|
-
})
|
|
21
|
-
|
|
22
|
-
return (
|
|
23
|
-
<Show fallback={<div class="p-4">Loading...</div>} when={!isLoading()}>
|
|
24
|
-
<div class="max-w-6xl mx-auto p-6">
|
|
25
|
-
<h1 class="text-3xl font-bold mb-6">SEO Analytics</h1>
|
|
26
|
-
|
|
27
|
-
<div class="space-y-6">
|
|
28
|
-
{/* Top Pages */}
|
|
29
|
-
<div class="border border-gray-200 rounded p-4">
|
|
30
|
-
<h2 class="font-semibold mb-4">Top Pages by Views</h2>
|
|
31
|
-
|
|
32
|
-
<div class="overflow-x-auto">
|
|
33
|
-
<table class="w-full text-sm">
|
|
34
|
-
<thead class="bg-gray-100 border-b">
|
|
35
|
-
<tr>
|
|
36
|
-
<th class="text-left p-3">Page</th>
|
|
37
|
-
<th class="text-right p-3">Views</th>
|
|
38
|
-
<th class="text-right p-3">Avg Time (s)</th>
|
|
39
|
-
<th class="text-right p-3">Bounce Rate</th>
|
|
40
|
-
</tr>
|
|
41
|
-
</thead>
|
|
42
|
-
<tbody>
|
|
43
|
-
<For each={topPages()}>
|
|
44
|
-
{(page, i) => (
|
|
45
|
-
<tr class="border-b hover:bg-gray-50">
|
|
46
|
-
<td class="p-3 font-mono text-xs">{page.path}</td>
|
|
47
|
-
<td class="p-3 text-right">{page.views.toLocaleString()}</td>
|
|
48
|
-
<td class="p-3 text-right">{page.avgTimeOnPage.toFixed(1)}</td>
|
|
49
|
-
<td class="p-3 text-right">{(page.bounceRate * 100).toFixed(1)}%</td>
|
|
50
|
-
</tr>
|
|
51
|
-
)}
|
|
52
|
-
</For>
|
|
53
|
-
</tbody>
|
|
54
|
-
</table>
|
|
55
|
-
</div>
|
|
56
|
-
|
|
57
|
-
<Show when={topPages().length === 0}>
|
|
58
|
-
<p class="text-center text-gray-500 py-8">No analytics data available</p>
|
|
59
|
-
</Show>
|
|
60
|
-
</div>
|
|
61
|
-
|
|
62
|
-
{/* Analytics Summary */}
|
|
63
|
-
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
|
|
64
|
-
<div class="border border-gray-200 rounded p-4">
|
|
65
|
-
<h3 class="text-sm text-gray-600 mb-1">Total Views</h3>
|
|
66
|
-
<p class="text-2xl font-bold">
|
|
67
|
-
{topPages()
|
|
68
|
-
.reduce((sum, p) => sum + p.views, 0)
|
|
69
|
-
.toLocaleString()}
|
|
70
|
-
</p>
|
|
71
|
-
</div>
|
|
72
|
-
|
|
73
|
-
<div class="border border-gray-200 rounded p-4">
|
|
74
|
-
<h3 class="text-sm text-gray-600 mb-1">Average Time on Page</h3>
|
|
75
|
-
<p class="text-2xl font-bold">
|
|
76
|
-
{topPages().length > 0
|
|
77
|
-
? (
|
|
78
|
-
topPages().reduce((sum, p) => sum + p.avgTimeOnPage, 0) / topPages().length
|
|
79
|
-
).toFixed(1)
|
|
80
|
-
: '0'}
|
|
81
|
-
s
|
|
82
|
-
</p>
|
|
83
|
-
</div>
|
|
84
|
-
|
|
85
|
-
<div class="border border-gray-200 rounded p-4">
|
|
86
|
-
<h3 class="text-sm text-gray-600 mb-1">Average Bounce Rate</h3>
|
|
87
|
-
<p class="text-2xl font-bold">
|
|
88
|
-
{topPages().length > 0
|
|
89
|
-
? (
|
|
90
|
-
(topPages().reduce((sum, p) => sum + p.bounceRate, 0) / topPages().length) *
|
|
91
|
-
100
|
|
92
|
-
).toFixed(1)
|
|
93
|
-
: '0'}
|
|
94
|
-
%
|
|
95
|
-
</p>
|
|
96
|
-
</div>
|
|
97
|
-
</div>
|
|
98
|
-
</div>
|
|
99
|
-
</div>
|
|
100
|
-
</Show>
|
|
101
|
-
)
|
|
102
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { createSignal, createEffect } from 'solid-js'
|
|
2
|
-
import type { SEOMeta } from '@geenius-seo/shared'
|
|
3
|
-
|
|
4
|
-
interface UseSEOOptions {
|
|
5
|
-
path?: string
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
export function useSEO(options?: UseSEOOptions) {
|
|
9
|
-
const [meta, setMeta] = createSignal<SEOMeta | null>(null)
|
|
10
|
-
const [isLoading, setIsLoading] = createSignal(false)
|
|
11
|
-
|
|
12
|
-
const updateMeta = (newMeta: SEOMeta) => {
|
|
13
|
-
setMeta(newMeta)
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
createEffect(() => {
|
|
17
|
-
if (!options?.path) return
|
|
18
|
-
|
|
19
|
-
setIsLoading(true)
|
|
20
|
-
// Placeholder for Convex query integration
|
|
21
|
-
// const meta = await client.query(api.queries.getSEOMeta, { path: options.path })
|
|
22
|
-
// setMeta(meta)
|
|
23
|
-
setIsLoading(false)
|
|
24
|
-
})
|
|
25
|
-
|
|
26
|
-
return { meta, updateMeta, isLoading }
|
|
27
|
-
}
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import { createSignal, createEffect } from 'solid-js'
|
|
2
|
-
import type { SEOMeta } from '@geenius-seo/shared'
|
|
3
|
-
|
|
4
|
-
interface PageEntry {
|
|
5
|
-
path: string
|
|
6
|
-
meta: SEOMeta
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export function useSEOAdmin() {
|
|
10
|
-
const [pages, setPages] = createSignal<PageEntry[]>([])
|
|
11
|
-
const [isLoading, setIsLoading] = createSignal(false)
|
|
12
|
-
|
|
13
|
-
const upsertMeta = async (path: string, meta: SEOMeta) => {
|
|
14
|
-
// Placeholder for Convex mutation integration
|
|
15
|
-
// await client.mutation(api.mutations.upsertSEOMeta, { path, meta })
|
|
16
|
-
setPages((prev) => {
|
|
17
|
-
const existing = prev.findIndex((p) => p.path === path)
|
|
18
|
-
if (existing >= 0) {
|
|
19
|
-
const next = [...prev]
|
|
20
|
-
next[existing] = { path, meta }
|
|
21
|
-
return next
|
|
22
|
-
}
|
|
23
|
-
return [...prev, { path, meta }]
|
|
24
|
-
})
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
const deleteMeta = async (path: string) => {
|
|
28
|
-
// Placeholder for Convex mutation integration
|
|
29
|
-
// await client.mutation(api.mutations.deleteSEOMeta, { path })
|
|
30
|
-
setPages((prev) => prev.filter((p) => p.path !== path))
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
createEffect(() => {
|
|
34
|
-
setIsLoading(true)
|
|
35
|
-
// Placeholder for Convex query integration
|
|
36
|
-
// const result = await client.query(api.queries.listPages, { limit: 100 })
|
|
37
|
-
// setPages(result)
|
|
38
|
-
setIsLoading(false)
|
|
39
|
-
})
|
|
40
|
-
|
|
41
|
-
return { pages, upsertMeta, deleteMeta, isLoading }
|
|
42
|
-
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { createMemo } from 'solid-js'
|
|
2
|
-
import { generateSitemapXml } from '@geenius-seo/shared'
|
|
3
|
-
import type { SitemapEntry } from '@geenius-seo/shared'
|
|
4
|
-
|
|
5
|
-
export function useSitemap(entries: () => SitemapEntry[]) {
|
|
6
|
-
const xml = createMemo(() => generateSitemapXml(entries()))
|
|
7
|
-
return { xml }
|
|
8
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"extends": "../../tsconfig.json",
|
|
3
|
-
"compilerOptions": {
|
|
4
|
-
"outDir": "dist",
|
|
5
|
-
"rootDir": "src",
|
|
6
|
-
"jsx": "preserve",
|
|
7
|
-
"jsxImportSource": "solid-js",
|
|
8
|
-
"strict": true,
|
|
9
|
-
"skipLibCheck": true,
|
|
10
|
-
"forceConsistentCasingInFileNames": true,
|
|
11
|
-
"resolveJsonModule": true,
|
|
12
|
-
"isolatedModules": true,
|
|
13
|
-
"target": "ES2022",
|
|
14
|
-
"module": "ESNext",
|
|
15
|
-
"moduleResolution": "bundler"
|
|
16
|
-
},
|
|
17
|
-
"include": [
|
|
18
|
-
"src"
|
|
19
|
-
]
|
|
20
|
-
}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@geenius-seo/solidjs-css",
|
|
3
|
-
"version": "0.1.0",
|
|
4
|
-
"description": "Geenius SEO — solidjs components with vanilla CSS",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"main": "./dist/index.js",
|
|
7
|
-
"module": "./dist/index.mjs",
|
|
8
|
-
"types": "./dist/index.d.ts",
|
|
9
|
-
"exports": {
|
|
10
|
-
".": {
|
|
11
|
-
"import": "./dist/index.mjs",
|
|
12
|
-
"require": "./dist/index.js",
|
|
13
|
-
"types": "./dist/index.d.ts"
|
|
14
|
-
}
|
|
15
|
-
},
|
|
16
|
-
"scripts": {
|
|
17
|
-
"build": "tsup",
|
|
18
|
-
"lint": "tsc --noEmit",
|
|
19
|
-
"clean": "rm -rf dist"
|
|
20
|
-
},
|
|
21
|
-
"files": ["dist"],
|
|
22
|
-
"publishConfig": { "access": "public" },
|
|
23
|
-
"peerDependencies": { "solid-js": ">=1.8.0" },
|
|
24
|
-
"dependencies": {
|
|
25
|
-
"@geenius-seo/shared": "workspace:*"
|
|
26
|
-
},
|
|
27
|
-
"devDependencies": {
|
|
28
|
-
"solid-js": "^1.9.0",
|
|
29
|
-
"tsup": "^8.5.1",
|
|
30
|
-
"typescript": "~6.0.2"
|
|
31
|
-
},
|
|
32
|
-
"author": "Antigravity HQ",
|
|
33
|
-
"license": "MIT",
|
|
34
|
-
"engines": { "node": ">=20.0.0" }
|
|
35
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from '@geenius-seo/solidjs';
|
package/pnpm-workspace.yaml
DELETED
package/tsconfig.json
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "ES2022",
|
|
4
|
-
"module": "ESNext",
|
|
5
|
-
"moduleResolution": "bundler",
|
|
6
|
-
"esModuleInterop": true,
|
|
7
|
-
"strict": true,
|
|
8
|
-
"skipLibCheck": true,
|
|
9
|
-
"declaration": true,
|
|
10
|
-
"declarationMap": true,
|
|
11
|
-
"sourceMap": true,
|
|
12
|
-
"outDir": "dist",
|
|
13
|
-
"rootDir": "src",
|
|
14
|
-
"jsx": "react-jsx",
|
|
15
|
-
"forceConsistentCasingInFileNames": true,
|
|
16
|
-
"resolveJsonModule": true,
|
|
17
|
-
"isolatedModules": true
|
|
18
|
-
},
|
|
19
|
-
"exclude": [
|
|
20
|
-
"node_modules",
|
|
21
|
-
"dist"
|
|
22
|
-
]
|
|
23
|
-
}
|