diff --git a/frontend/src/components/admin/DomainSetupGuide.tsx b/frontend/src/components/admin/DomainSetupGuide.tsx new file mode 100644 index 0000000..75ad7cd --- /dev/null +++ b/frontend/src/components/admin/DomainSetupGuide.tsx @@ -0,0 +1,168 @@ +import { useState } from 'react'; + +interface DomainSetupGuideProps { + siteDomain?: string; +} + +export default function DomainSetupGuide({ siteDomain }: DomainSetupGuideProps) { + const [activeStep, setActiveStep] = useState(0); + const [verifying, setVerifying] = useState(false); + const [verificationStatus, setVerificationStatus] = useState<'pending' | 'success' | 'error'>('pending'); + + const steps = [ + { + title: '1. Get Your Domain', + content: ( +
+

Purchase a domain from any registrar:

+ +
+ ) + }, + { + title: '2. Configure DNS Records', + content: ( +
+

Add these DNS records at your registrar:

+
+
+
Type: CNAME
+
Name: www
+
Target: launch.jumpstartscaling.com
+
+
+
Type: A
+
Name: @ (root)
+
Value: 72.61.15.216
+
+
+

DNS propagation can take 5-60 minutes

+
+ ) + }, + { + title: '3. Update Site Settings', + content: ( +
+

Add your domain to Spark:

+
    +
  1. Go to Sites & Deployments
  2. +
  3. Edit your site
  4. +
  5. Set the "URL" field to your domain
  6. +
  7. Save changes
  8. +
+ {siteDomain && ( +
+

+ Current domain: {siteDomain} +

+
+ )} +
+ ) + }, + { + title: '4. Verify Connection', + content: ( +
+

Test if your domain is connected:

+ + + {verificationStatus === 'success' && ( +
+

✅ Domain connected successfully!

+
+ )} + + {verificationStatus === 'error' && ( +
+

❌ Domain not reachable yet

+

DNS may still be propagating. Wait a few minutes and try again.

+
+ )} +
+ ) + } + ]; + + return ( +
+ {/* Header */} +
+

🌐 Connect Your Domain

+

Follow these steps to point your domain to Spark

+
+ + {/* Steps */} +
+ {/* Step Navigator */} +
+ {steps.map((step, index) => ( + + ))} +
+ + {/* Active Step Content */} +
+

+ {steps[activeStep].title} +

+ {steps[activeStep].content} +
+ + {/* Navigation Buttons */} +
+ + +
+
+
+ ); +} diff --git a/frontend/src/components/admin/sites/SiteEditor.tsx b/frontend/src/components/admin/sites/SiteEditor.tsx index b49f870..66a2abf 100644 --- a/frontend/src/components/admin/sites/SiteEditor.tsx +++ b/frontend/src/components/admin/sites/SiteEditor.tsx @@ -7,6 +7,7 @@ import { Label } from '@/components/ui/label'; import { Switch } from '@/components/ui/switch'; import { Badge } from '@/components/ui/badge'; import { Site } from '@/types/schema'; +import DomainSetupGuide from '@/components/admin/DomainSetupGuide'; interface SiteEditorProps { id: string; // Astro passes string params @@ -199,6 +200,9 @@ export default function SiteEditor({ id }: SiteEditorProps) { + {/* Domain Setup Guide */} + +
+
diff --git a/frontend/src/pages/preview/page/[pageId].astro b/frontend/src/pages/preview/page/[pageId].astro new file mode 100644 index 0000000..5d5cce5 --- /dev/null +++ b/frontend/src/pages/preview/page/[pageId].astro @@ -0,0 +1,132 @@ +--- +/** + * Preview Page Route + * Shows a single page in preview mode + */ + +import { getDirectusClient, readItem } from '@/lib/directus/client'; +import type { Page } from '@/types/schema'; + +const { pageId } = Astro.params; + +if (!pageId) { + return Astro.redirect('/admin/pages'); +} + +let page: Page | null = null; +let error: string | null = null; + +try { + const client = getDirectusClient(); + const result = await client.request(readItem('pages', pageId)); + page = result as Page; +} catch (err) { + error = err instanceof Error ? err.message : 'Failed to load page'; + console.error('Preview error:', err); +} + +if (!page) { + return Astro.redirect('/admin/pages'); +} +--- + + + + + + + Preview: {page.title} + + + + +
+
+ + + + + PREVIEW MODE + Draft +
+
+ {page.title} + +
+
+ + +
+ {error ? ( +
+

Error Loading Preview

+

{error}

+
+ ) : ( + <> +

+ {page.title} +

+ + {page.content && ( +
+ +
+ )} + + {!page.content && ( +

No content yet

+ )} + + )} +
+ + diff --git a/frontend/src/pages/preview/post/[postId].astro b/frontend/src/pages/preview/post/[postId].astro new file mode 100644 index 0000000..2c240de --- /dev/null +++ b/frontend/src/pages/preview/post/[postId].astro @@ -0,0 +1,156 @@ +--- +/** + * Preview Post/Article Route + * Shows a single generated article in preview mode + */ + +import { getDirectusClient, readItem } from '@/lib/directus/client'; +import type { GeneratedArticle } from '@/types/schema'; + +const { postId } = Astro.params; + +if (!postId) { + return Astro.redirect('/admin/seo/articles'); +} + +let article: GeneratedArticle | null = null; +let error: string | null = null; + +try { + const client = getDirectusClient(); + const result = await client.request(readItem('generated_articles', postId)); + article = result as GeneratedArticle; +} catch (err) { + error = err instanceof Error ? err.message : 'Failed to load article'; + console.error('Preview error:', err); +} + +if (!article) { + return Astro.redirect('/admin/seo/articles'); +} +--- + + + + + + + Preview: {article.title} + {article.meta_desc && } + + + + +
+
+ + + + + PREVIEW MODE + {article.is_published ? 'Published' : 'Draft'} +
+
+ + +
+
+ + +
+ {error ? ( +
+

Error Loading Preview

+

{error}

+
+ ) : ( +
+

{article.title}

+ + {article.meta_desc && ( +

+ {article.meta_desc} +

+ )} + + {article.html_content && ( +
+ +
+ )} + + {!article.html_content && ( +

No content generated yet

+ )} +
+ )} +
+ +