Add site builder service to Docker Compose and remove obsolete scripts

- Introduced a new service `igny8_site_builder` in `docker-compose.app.yml` for site building functionality, including environment variables and volume mappings.
- Deleted several outdated scripts: `create_test_users.py`, `test_image_write_access.py`, `update_free_plan.py`, and the database file `db.sqlite3` to clean up the backend.
- Updated Django settings and URL configurations to integrate the new site builder module.
This commit is contained in:
IGNY8 VPS (Salman)
2025-11-17 16:08:51 +00:00
parent e3d4ba2c02
commit 5a36686844
74 changed files with 7217 additions and 374 deletions

View File

@@ -0,0 +1,45 @@
.sb-card {
background: #ffffff;
border-radius: 16px;
border: 1px solid rgba(15, 23, 42, 0.08);
padding: 1.5rem;
box-shadow: 0 8px 24px rgba(15, 23, 42, 0.05);
display: flex;
flex-direction: column;
gap: 1rem;
}
.sb-card__header {
display: flex;
flex-direction: column;
gap: 0.35rem;
}
.sb-card__title {
font-size: 1.1rem;
font-weight: 600;
color: #0f172a;
margin: 0;
}
.sb-card__description {
color: #475569;
margin: 0;
font-size: 0.95rem;
}
.sb-card__body {
display: flex;
flex-direction: column;
gap: 1rem;
}
.sb-card__footer {
border-top: 1px solid rgba(15, 23, 42, 0.06);
padding-top: 1rem;
display: flex;
justify-content: flex-end;
gap: 0.75rem;
}

View File

@@ -0,0 +1,25 @@
import type { PropsWithChildren, ReactNode } from 'react';
import './Card.css';
interface CardProps extends PropsWithChildren {
title?: ReactNode;
description?: ReactNode;
footer?: ReactNode;
}
export function Card({ title, description, footer, children }: CardProps) {
return (
<section className="sb-card">
{(title || description) && (
<header className="sb-card__header">
{title && <h2 className="sb-card__title">{title}</h2>}
{description && <p className="sb-card__description">{description}</p>}
</header>
)}
<div className="sb-card__body">{children}</div>
{footer && <footer className="sb-card__footer">{footer}</footer>}
</section>
);
}

View File

@@ -0,0 +1,28 @@
import './HeroBlock.css';
interface HeroBlockProps {
heading: string;
subheading?: string;
ctaLabel?: string;
secondaryCta?: string;
badge?: string;
}
export function HeroBlock({ heading, subheading, ctaLabel, secondaryCta, badge }: HeroBlockProps) {
return (
<div className="sb-hero-block">
{badge && <span className="sb-hero-block__badge">{badge}</span>}
<h1>{heading}</h1>
{subheading && <p>{subheading}</p>}
<div className="sb-hero-block__ctas">
{ctaLabel && <button>{ctaLabel}</button>}
{secondaryCta && (
<button className="ghost" type="button">
{secondaryCta}
</button>
)}
</div>
</div>
);
}

View File

@@ -0,0 +1,13 @@
.sb-page-canvas {
border-radius: 24px;
padding: 2.5rem;
box-shadow: 0 30px 80px rgba(15, 23, 42, 0.12);
border: 1px solid rgba(15, 23, 42, 0.08);
}
.sb-page-canvas__body {
display: flex;
flex-direction: column;
gap: 2.25rem;
}

View File

@@ -0,0 +1,12 @@
import type { PropsWithChildren } from 'react';
import { palette } from '../theme';
import './PageCanvas.css';
export function PageCanvas({ children }: PropsWithChildren) {
return (
<article className="sb-page-canvas" style={{ background: palette.background }}>
<div className="sb-page-canvas__body">{children}</div>
</article>
);
}

View File

@@ -0,0 +1,39 @@
.sb-section {
border-radius: 20px;
padding: 1.75rem;
border: 1px solid rgba(15, 23, 42, 0.07);
background: #ffffff;
display: flex;
flex-direction: column;
gap: 1.25rem;
}
.sb-section--soft {
background: #f4f6ff;
}
.sb-section__header h3 {
margin: 0.15rem 0;
font-size: 1.8rem;
font-weight: 700;
}
.sb-section__subtitle {
margin: 0;
color: #64748b;
}
.sb-section__overline {
font-size: 0.75rem;
letter-spacing: 0.08em;
text-transform: uppercase;
color: #6366f1;
margin: 0;
}
.sb-section__content {
display: flex;
flex-direction: column;
gap: 1rem;
}

View File

@@ -0,0 +1,25 @@
import type { PropsWithChildren, ReactNode } from 'react';
import './Section.css';
interface SectionProps extends PropsWithChildren {
overline?: string;
title?: ReactNode;
subtitle?: ReactNode;
background?: 'surface' | 'soft';
}
export function Section({ overline, title, subtitle, background = 'surface', children }: SectionProps) {
return (
<section className={`sb-section sb-section--${background}`}>
{(overline || title || subtitle) && (
<header className="sb-section__header">
{overline && <p className="sb-section__overline">{overline}</p>}
{title && <h3>{title}</h3>}
{subtitle && <p className="sb-section__subtitle">{subtitle}</p>}
</header>
)}
<div className="sb-section__content">{children}</div>
</section>
);
}

View File

@@ -0,0 +1,29 @@
export const palette = {
background: '#f8fbff',
surface: '#ffffff',
accent: '#6366f1',
accentSoft: '#eef2ff',
text: '#0f172a',
textMuted: '#64748b',
border: 'rgba(15, 23, 42, 0.08)',
};
export const typography = {
title: {
fontSize: '2.5rem',
fontWeight: 700,
lineHeight: 1.1,
},
subtitle: {
fontSize: '1.15rem',
color: palette.textMuted,
lineHeight: 1.5,
},
label: {
fontSize: '0.75rem',
textTransform: 'uppercase',
letterSpacing: '0.08em',
color: palette.accent,
},
};