Skip to content

Commit 5ca98c5

Browse files
committed
chore: wip
1 parent 607f080 commit 5ca98c5

File tree

20 files changed

+1318
-991
lines changed

20 files changed

+1318
-991
lines changed
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import type { SubscriberEmailRequestType } from '@stacksjs/orm'
2+
import { Action } from '@stacksjs/actions'
3+
import { SubscriberEmail } from '@stacksjs/orm'
4+
5+
export default new Action({
6+
name: 'SubscriberEmailAction',
7+
description: 'Save emails from subscribe page',
8+
method: 'POST',
9+
10+
async handle(request: SubscriberEmailRequestType) {
11+
const email = request.get('email')
12+
13+
// Check if email already exists
14+
const existing = await SubscriberEmail.where('email', email).first()
15+
if (existing) {
16+
return { success: true, message: 'Already subscribed' }
17+
}
18+
19+
const model = await SubscriberEmail.create({ email })
20+
21+
return { success: true, subscriber: model }
22+
},
23+
})

config/database.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ export default {
3939
postgres: {
4040
name: envVars.DB_DATABASE || 'stacks',
4141
host: envVars.DB_HOST || '127.0.0.1',
42-
port: Number(envVars.DB_PORT) || 3306,
42+
port: Number(envVars.DB_PORT) || 5432,
4343
username: envVars.DB_USERNAME || '',
4444
password: envVars.DB_PASSWORD || '',
4545
prefix: '',

config/docs.ts

Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
import type { BunPressOptions } from '@stacksjs/bunpress'
2+
3+
const config: BunPressOptions = {
4+
verbose: true,
5+
docsDir: './docs',
6+
outDir: './dist/docs',
7+
8+
// Navigation
9+
nav: [
10+
{
11+
text: 'Changelog',
12+
link: 'https://github.com/stacksjs/stacks/blob/main/CHANGELOG.md',
13+
},
14+
{
15+
text: 'Resources',
16+
items: [
17+
{ text: 'Team', link: '/team' },
18+
{ text: 'Sponsors', link: '/sponsors' },
19+
{ text: 'Partners', link: '/partners' },
20+
{ text: 'Postcardware', link: '/postcardware' },
21+
{ text: 'Awesome Stacks', link: 'https://github.com/stacksjs/awesome-stacks' },
22+
{ text: 'Contributing', link: 'https://github.com/stacksjs/stacks/blob/main/.github/CONTRIBUTING.md' },
23+
],
24+
},
25+
],
26+
27+
// Markdown configuration
28+
markdown: {
29+
title: 'Stacks Documentation',
30+
meta: {
31+
description: 'Rapid application, cloud & library development framework.',
32+
author: 'Stacks.js',
33+
},
34+
syntaxHighlightTheme: 'github-dark',
35+
toc: {
36+
enabled: true,
37+
minDepth: 2,
38+
maxDepth: 3,
39+
},
40+
sidebar: {
41+
'/': [
42+
{
43+
text: 'Prologue',
44+
collapsed: true,
45+
items: [
46+
{ text: 'Release Notes', link: '/release-notes' },
47+
{ text: 'Upgrade Guide', link: '/upgrade-guide' },
48+
{ text: 'Contribution Guide', link: '/contribution-guide' },
49+
{ text: 'Sponsors', link: '/sponsors' },
50+
],
51+
},
52+
{
53+
text: 'Getting Started',
54+
collapsed: true,
55+
items: [
56+
{ text: 'Introduction', link: '/guide/intro' },
57+
{ text: 'Quick Start', link: '/guide/get-started' },
58+
],
59+
},
60+
{
61+
text: 'Basics',
62+
collapsed: true,
63+
items: [
64+
{ text: 'Routing', link: '/basics/routing' },
65+
{ text: 'Middleware', link: '/basics/middleware' },
66+
{ text: 'Models', link: '/basics/models' },
67+
{ text: 'Views', link: '/basics/views' },
68+
{ text: 'Actions', link: '/basics/actions' },
69+
{ text: 'Commands', link: '/basics/commands' },
70+
{ text: 'Jobs', link: '/basics/jobs' },
71+
{ text: 'Components', link: '/basics/components' },
72+
{ text: 'Functions', link: '/basics/functions' },
73+
{ text: 'Validation', link: '/packages/validation' },
74+
{ text: 'Error Handling', link: '/basics/error-handling' },
75+
{ text: 'Logging', link: '/basics/logging' },
76+
],
77+
},
78+
{
79+
text: 'Digging Deeper',
80+
collapsed: true,
81+
items: [
82+
{ text: 'Authentication', link: '/guide/auth' },
83+
{ text: 'Database', link: '/packages/database' },
84+
{ text: 'Cache', link: '/packages/cache' },
85+
{ text: 'Events', link: '/packages/events' },
86+
{ text: 'Queue', link: '/packages/queue' },
87+
{ text: 'Notifications', link: '/packages/notifications' },
88+
{ text: 'Payments', link: '/packages/payments' },
89+
{ text: 'Realtime', link: '/packages/realtime' },
90+
{ text: 'Search Engine', link: '/packages/search-engine' },
91+
{ text: 'Storage', link: '/packages/storage' },
92+
],
93+
},
94+
{
95+
text: 'Cloud',
96+
collapsed: true,
97+
items: [
98+
{ text: 'Deploy', link: '/guide/cloud/deployment' },
99+
{ text: 'Extend Cloud', link: '/guide/cloud/extend' },
100+
],
101+
},
102+
{
103+
text: 'CLI (Buddy)',
104+
collapsed: true,
105+
items: [
106+
{ text: 'Introduction', link: '/guide/buddy/intro' },
107+
{ text: 'Dev', link: '/guide/buddy/dev' },
108+
{ text: 'Build', link: '/guide/buddy/build' },
109+
{ text: 'Deploy', link: '/guide/buddy/deploy' },
110+
{ text: 'Make', link: '/guide/buddy/make' },
111+
{ text: 'Migrate', link: '/guide/buddy/migrate' },
112+
{ text: 'Test', link: '/guide/buddy/test' },
113+
],
114+
},
115+
{
116+
text: 'Packages',
117+
collapsed: true,
118+
items: [
119+
{ text: 'Actions', link: '/packages/actions' },
120+
{ text: 'AI', link: '/packages/ai' },
121+
{ text: 'Auth', link: '/packages/auth' },
122+
{ text: 'Cache', link: '/packages/cache' },
123+
{ text: 'CLI', link: '/packages/cli' },
124+
{ text: 'Cloud', link: '/packages/cloud' },
125+
{ text: 'Database', link: '/packages/database' },
126+
{ text: 'ORM', link: '/packages/orm' },
127+
{ text: 'Query Builder', link: '/packages/query-builder' },
128+
{ text: 'Router', link: '/packages/router' },
129+
{ text: 'Testing', link: '/packages/testing' },
130+
{ text: 'Validation', link: '/packages/validation' },
131+
],
132+
},
133+
{
134+
text: 'Testing',
135+
collapsed: true,
136+
items: [
137+
{ text: 'Getting Started', link: '/testing/getting-started' },
138+
{ text: 'Unit Tests', link: '/testing/unit-tests' },
139+
{ text: 'Feature Tests', link: '/testing/feature-tests' },
140+
{ text: 'Http Tests', link: '/testing/http-tests' },
141+
{ text: 'Browser Tests', link: '/testing/browser-tests' },
142+
],
143+
},
144+
{
145+
text: 'Project',
146+
collapsed: true,
147+
items: [
148+
{ text: 'Roadmap', link: '/project/roadmap' },
149+
{ text: 'Contributing', link: '/project/contributing' },
150+
{ text: 'License', link: '/project/license' },
151+
],
152+
},
153+
],
154+
},
155+
themeConfig: {
156+
logo: '/images/logos/logo-transparent.svg',
157+
footer: {
158+
message: 'Released under the MIT License.',
159+
copyright: 'Copyright 2024-present Stacks.js, Inc.',
160+
},
161+
socialLinks: [
162+
{ icon: 'twitter', link: 'https://twitter.com/stacksjs' },
163+
{ icon: 'github', link: 'https://github.com/stacksjs/stacks' },
164+
{ icon: 'discord', link: 'https://discord.gg/stacksjs' },
165+
],
166+
},
167+
},
168+
169+
// SEO Configuration
170+
sitemap: {
171+
enabled: true,
172+
baseUrl: 'https://stacksjs.com/docs',
173+
},
174+
175+
robots: {
176+
enabled: true,
177+
},
178+
}
179+
180+
export default config

docs/config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -693,7 +693,7 @@ export default {
693693
description: 'Rapid application, cloud & library development framework.',
694694
lastUpdated: true,
695695
deploy: true,
696-
base: '/',
696+
base: '/docs/',
697697

698698
metaChunk: true,
699699

resources/assets/scripts/main.ts

Lines changed: 59 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1187,31 +1187,75 @@ function showNotification() {
11871187
}
11881188
}
11891189

1190-
// Email signup
1190+
// Email signup helper
1191+
async function subscribeEmail(email: string): Promise<{ success: boolean, message?: string }> {
1192+
const response = await fetch('/api/email/subscribe', {
1193+
method: 'POST',
1194+
headers: {
1195+
'Content-Type': 'application/json',
1196+
},
1197+
body: JSON.stringify({ email }),
1198+
})
1199+
1200+
if (response.ok) {
1201+
return { success: true }
1202+
}
1203+
else {
1204+
const data = await response.json().catch(() => ({}))
1205+
return { success: false, message: data.message || 'Failed to subscribe. Please try again later.' }
1206+
}
1207+
}
1208+
1209+
// Email signup (notification popup)
11911210
async function handleEmailSignup() {
1192-
const emailInput = document.getElementById('notification-email')
1193-
const email = emailInput.value.trim()
1211+
const emailInput = document.getElementById('notification-email') as HTMLInputElement
1212+
const email = emailInput?.value.trim()
11941213

11951214
if (!email || !email.includes('@')) {
11961215
alert('Please enter a valid email address')
11971216
return
11981217
}
11991218

12001219
try {
1201-
const response = await fetch('https://stacksjs.org/api/newsletter/subscribe', {
1202-
method: 'POST',
1203-
headers: {
1204-
'Content-Type': 'application/json',
1205-
},
1206-
body: JSON.stringify({ email }),
1207-
})
1220+
const result = await subscribeEmail(email)
1221+
1222+
if (result.success) {
1223+
const signupEl = document.getElementById('notification-signup')
1224+
const successEl = document.getElementById('notification-success')
1225+
if (signupEl) signupEl.style.display = 'none'
1226+
if (successEl) successEl.style.display = 'block'
1227+
}
1228+
else {
1229+
alert(result.message)
1230+
}
1231+
}
1232+
catch (error) {
1233+
console.error('Subscription error:', error)
1234+
alert('Failed to subscribe. Please try again later.')
1235+
}
1236+
}
1237+
1238+
// Blog newsletter signup
1239+
async function handleBlogNewsletterSignup() {
1240+
const emailInput = document.getElementById('blog-newsletter-email') as HTMLInputElement
1241+
const email = emailInput?.value.trim()
1242+
1243+
if (!email || !email.includes('@')) {
1244+
alert('Please enter a valid email address')
1245+
return
1246+
}
1247+
1248+
try {
1249+
const result = await subscribeEmail(email)
12081250

1209-
if (response.ok) {
1210-
document.getElementById('notification-signup').style.display = 'none'
1211-
document.getElementById('notification-success').style.display = 'block'
1251+
if (result.success) {
1252+
const formEl = document.getElementById('blog-newsletter-form')
1253+
const successEl = document.getElementById('blog-newsletter-success')
1254+
if (formEl) formEl.style.display = 'none'
1255+
if (successEl) successEl.style.display = 'block'
12121256
}
12131257
else {
1214-
alert('Failed to subscribe. Please try again later.')
1258+
alert(result.message)
12151259
}
12161260
}
12171261
catch (error) {
@@ -2081,6 +2125,7 @@ window.showFeature = showFeature
20812125
window.closeNotification = closeNotification
20822126
window.showNotification = showNotification
20832127
window.handleEmailSignup = handleEmailSignup
2128+
window.handleBlogNewsletterSignup = handleBlogNewsletterSignup
20842129
window.shareVia = shareVia
20852130
window.copyLogoSVG = copyLogoSVG
20862131
window.copyWordmarkSVG = copyWordmarkSVG

resources/views/index.stx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1277,21 +1277,25 @@ export default {
12771277
</article>
12781278

12791279
<!-- Newsletter Signup -->
1280-
<div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 24px; border-radius: 8px; border: 2px solid #5a67d8; text-align: center;">
1280+
<div id="blog-newsletter" style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 24px; border-radius: 8px; border: 2px solid #5a67d8; text-align: center;">
12811281
<h3 style="margin: 0 0 8px 0; font-size: 20px;">Stay Updated</h3>
12821282
<p style="margin: 0 0 16px 0; font-size: 13px; opacity: 0.95;">
12831283
Subscribe to our newsletter for the latest updates, tutorials, and community highlights.
12841284
</p>
1285-
<div style="display: flex; gap: 8px; max-width: 400px; margin: 0 auto;">
1285+
<div id="blog-newsletter-form" style="display: flex; gap: 8px; max-width: 400px; margin: 0 auto;">
12861286
<input
1287+
id="blog-newsletter-email"
12871288
type="email"
12881289
placeholder="your@email.com"
12891290
style="flex: 1; padding: 10px 14px; border: 2px inset #999; border-radius: 4px; font-size: 13px;"
12901291
/>
1291-
<button style="padding: 10px 20px; background: white; color: #667eea; border: 2px outset #999; border-radius: 4px; font-weight: bold; cursor: pointer; font-size: 13px;">
1292+
<button onclick="handleBlogNewsletterSignup()" style="padding: 10px 20px; background: white; color: #667eea; border: 2px outset #999; border-radius: 4px; font-weight: bold; cursor: pointer; font-size: 13px;">
12921293
Subscribe
12931294
</button>
12941295
</div>
1296+
<div id="blog-newsletter-success" style="display: none; padding: 12px; background: rgba(255,255,255,0.2); border-radius: 4px;">
1297+
Thanks for subscribing! We'll keep you updated.
1298+
</div>
12951299
</div>
12961300
</div>
12971301
</div>

0 commit comments

Comments
 (0)