diff --git a/routes/__init__.py b/routes/__init__.py index c10f5eb..eadcf0b 100644 --- a/routes/__init__.py +++ b/routes/__init__.py @@ -8,6 +8,7 @@ def init_app(app: Flask): main_bp = Blueprint('main', __name__) auth_bp = Blueprint('auth', __name__, url_prefix='/auth') rooms_bp = Blueprint('rooms', __name__) + public_bp = Blueprint('public', __name__) # Import and initialize routes from .main import init_routes as init_main_routes @@ -18,10 +19,12 @@ def init_app(app: Flask): from .admin import admin as admin_routes from .email_templates import email_templates as email_templates_routes from .user import user_bp as user_routes + from .public import init_public_routes # Initialize routes init_main_routes(main_bp) init_auth_routes(auth_bp) + init_public_routes(public_bp) # Add site_settings context processor to all blueprints @app.context_processor @@ -37,6 +40,7 @@ def init_app(app: Flask): # Register blueprints app.register_blueprint(main_bp) app.register_blueprint(auth_bp) + app.register_blueprint(public_bp) app.register_blueprint(rooms_routes) app.register_blueprint(contacts_routes) app.register_blueprint(conversations_routes) diff --git a/routes/__pycache__/__init__.cpython-313.pyc b/routes/__pycache__/__init__.cpython-313.pyc index 94ae9da..fac3e56 100644 Binary files a/routes/__pycache__/__init__.cpython-313.pyc and b/routes/__pycache__/__init__.cpython-313.pyc differ diff --git a/routes/__pycache__/main.cpython-313.pyc b/routes/__pycache__/main.cpython-313.pyc index 218c737..69281a0 100644 Binary files a/routes/__pycache__/main.cpython-313.pyc and b/routes/__pycache__/main.cpython-313.pyc differ diff --git a/routes/main.py b/routes/main.py index dc63037..321c58a 100644 --- a/routes/main.py +++ b/routes/main.py @@ -44,10 +44,20 @@ def init_routes(main_bp): return {'unread_notifications': 0} @main_bp.route('/') - @login_required - @require_password_change - def home(): - return redirect(url_for('main.dashboard')) + def public_home(): + """Public homepage for the master instance - client-facing website""" + # Check if this is a master instance + is_master = os.environ.get('MASTER', 'false').lower() == 'true' + + if is_master: + # For master instance, show the public homepage + return render_template('home.html') + else: + # For child instances, redirect to login if not authenticated, otherwise dashboard + if current_user.is_authenticated: + return redirect(url_for('main.dashboard')) + else: + return redirect(url_for('auth.login')) @main_bp.route('/dashboard') @login_required diff --git a/routes/public.py b/routes/public.py new file mode 100644 index 0000000..743095e --- /dev/null +++ b/routes/public.py @@ -0,0 +1,79 @@ +from flask import Blueprint, render_template, redirect, url_for +from models import SiteSettings +import os + +def init_public_routes(public_bp): + @public_bp.context_processor + def inject_site_settings(): + site_settings = SiteSettings.query.first() + return dict(site_settings=site_settings) + + @public_bp.route('/features') + def features(): + """Features page""" + return render_template('public/features.html') + + @public_bp.route('/pricing') + def pricing(): + """Pricing page""" + return render_template('public/pricing.html') + + @public_bp.route('/about') + def about(): + """About page""" + return render_template('public/about.html') + + @public_bp.route('/blog') + def blog(): + """Blog page""" + return render_template('public/blog.html') + + @public_bp.route('/careers') + def careers(): + """Careers page""" + return render_template('public/careers.html') + + @public_bp.route('/press') + def press(): + """Press page""" + return render_template('public/press.html') + + @public_bp.route('/help') + def help_center(): + """Help Center page""" + return render_template('public/help.html') + + @public_bp.route('/contact') + def contact(): + """Contact page""" + return render_template('public/contact.html') + + @public_bp.route('/status') + def status(): + """Status page""" + return render_template('public/status.html') + + @public_bp.route('/security') + def security(): + """Security page""" + return render_template('public/security.html') + + @public_bp.route('/privacy') + def privacy(): + """Privacy Policy page""" + return render_template('public/privacy.html') + + @public_bp.route('/terms') + def terms(): + """Terms of Service page""" + return render_template('public/terms.html') + + @public_bp.route('/gdpr') + def gdpr(): + """GDPR page""" + return render_template('public/gdpr.html') + + @public_bp.route('/compliance') + def compliance(): + """Compliance page""" + return render_template('public/compliance.html') \ No newline at end of file diff --git a/static/css/home.css b/static/css/home.css index 07d1a2f..97db8ff 100644 --- a/static/css/home.css +++ b/static/css/home.css @@ -1,22 +1,48 @@ +/* Enhanced Homepage Styles */ .navbar { - background-color: var(--primary-color) !important; + background: var(--white) !important; + transition: all 0.3s ease; +} + +.navbar.scrolled { + background: var(--white) !important; } .hero-section { background: linear-gradient(135deg, var(--primary-color) 0%, var(--secondary-color) 100%); color: white; - padding: 100px 0; + padding: 120px 0 100px 0; + position: relative; + overflow: hidden; +} + +.hero-section::before { + content: ''; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: url('data:image/svg+xml,'); + opacity: 0.3; +} + +.stats-section { + background-color: var(--bg-color); + padding: 80px 0; } .feature-card { border: none; - border-radius: 10px; - transition: transform 0.3s; - box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); + border-radius: 15px; + transition: all 0.3s ease; + box-shadow: 0 5px 15px var(--shadow-color); + background: var(--white); } .feature-card:hover { transform: translateY(-5px); + box-shadow: 0 15px 35px var(--shadow-color-light); } .feature-icon { @@ -25,30 +51,222 @@ margin-bottom: 1rem; } +.testimonial-card { + background: var(--white); + border-radius: 15px; + padding: 30px; + box-shadow: 0 5px 15px var(--shadow-color); + margin: 20px 0; + transition: transform 0.3s ease; +} + +.testimonial-card:hover { + transform: translateY(-3px); +} + +.pricing-card { + border: none; + border-radius: 15px; + transition: all 0.3s ease; + box-shadow: 0 5px 15px var(--shadow-color); +} + +.pricing-card:hover { + transform: translateY(-10px); + box-shadow: 0 20px 40px var(--shadow-color-light); +} + +.pricing-card.border-primary { + border: 2px solid var(--primary-color) !important; + transform: scale(1.05); +} + .btn-primary { - background-color: var(--primary-color); - border-color: var(--primary-color); + background: linear-gradient(135deg, var(--primary-color) 0%, var(--secondary-color) 100%); + border: none; + border-radius: 25px; + padding: 12px 30px; + font-weight: 600; + transition: all 0.3s ease; } .btn-primary:hover { - background-color: var(--primary-light); - border-color: var(--primary-light); + background: linear-gradient(135deg, var(--primary-light) 0%, var(--secondary-light) 100%); + transform: translateY(-2px); + box-shadow: 0 5px 15px var(--primary-opacity-15); } .btn-outline-primary { + border: 2px solid var(--primary-color); color: var(--primary-color); - border-color: var(--primary-color); + border-radius: 25px; + padding: 12px 30px; + font-weight: 600; + transition: all 0.3s ease; } .btn-outline-primary:hover { - background-color: var(--primary-color); + background: linear-gradient(135deg, var(--primary-color) 0%, var(--secondary-color) 100%); border-color: var(--primary-color); + transform: translateY(-2px); } -footer { - background-color: var(--primary-color) !important; +.btn-light { + background: rgba(255, 255, 255, 0.9); + border: none; + border-radius: 25px; + padding: 12px 30px; + font-weight: 600; + transition: all 0.3s ease; +} + +.btn-light:hover { + background: white; + transform: translateY(-2px); + box-shadow: 0 5px 15px rgba(255, 255, 255, 0.3); +} + +.btn-outline-light { + border: 2px solid rgba(255, 255, 255, 0.8); + color: white; + border-radius: 25px; + padding: 12px 30px; + font-weight: 600; + transition: all 0.3s ease; +} + +.btn-outline-light:hover { + background: rgba(255, 255, 255, 0.1); + border-color: white; + transform: translateY(-2px); +} + +.admin-link { + position: fixed; + bottom: 20px; + right: 20px; + opacity: 0.3; + transition: opacity 0.3s ease; + z-index: 1000; +} + +.admin-link:hover { + opacity: 1; +} + +.admin-link a { + color: var(--text-muted); + text-decoration: none; + font-size: 12px; + background: rgba(255, 255, 255, 0.9); + padding: 8px; + border-radius: 50%; + display: block; + width: 40px; + height: 40px; + text-align: center; + line-height: 24px; + box-shadow: 0 2px 10px var(--shadow-color); +} + +.nav-link { + font-weight: 500; + transition: all 0.3s ease; } .nav-link:hover { - color: var(--secondary-color) !important; + color: rgba(255, 255, 255, 0.8) !important; + transform: translateY(-1px); +} + +.navbar-brand { + font-weight: 700; + font-size: 1.5rem; +} + +/* Smooth scrolling */ +html { + scroll-behavior: smooth; +} + +/* Responsive adjustments */ +@media (max-width: 768px) { + .hero-section { + padding: 100px 0 80px 0; + } + + .display-3 { + font-size: 2.5rem; + } + + .display-5 { + font-size: 2rem; + } + + .pricing-card.border-primary { + transform: none; + } +} + +/* Feature icon backgrounds */ +.feature-icon-bg { + background: linear-gradient(135deg, var(--primary-color) 0%, var(--secondary-color) 100%); + color: white; + border-radius: 50%; + width: 60px; + height: 60px; + display: inline-flex; + align-items: center; + justify-content: center; + margin-bottom: 1rem; +} + +/* Stats section text colors */ +.stats-section .h2 { + color: var(--primary-color) !important; +} + +.stats-section .text-muted { + color: var(--text-muted) !important; +} + +/* Pricing card highlights */ +.pricing-card.border-primary { + border: 2px solid var(--primary-color) !important; +} + +.pricing-card .card-header { + background: linear-gradient(135deg, var(--primary-color) 0%, var(--secondary-color) 100%); + color: white; + border-radius: 15px 15px 0 0 !important; +} + +/* Fade in animations */ +.fade-in { + opacity: 0; + transform: translateY(30px); + transition: all 0.6s ease; +} + +.fade-in.visible { + opacity: 1; + transform: translateY(0); +} + +/* Custom scrollbar */ +::-webkit-scrollbar { + width: 8px; +} + +::-webkit-scrollbar-track { + background: var(--bg-color); +} + +::-webkit-scrollbar-thumb { + background: var(--primary-color); + border-radius: 4px; +} + +::-webkit-scrollbar-thumb:hover { + background: var(--primary-light); } \ No newline at end of file diff --git a/templates/components/footer_nav.html b/templates/components/footer_nav.html new file mode 100644 index 0000000..5ead2ed --- /dev/null +++ b/templates/components/footer_nav.html @@ -0,0 +1,58 @@ + + \ No newline at end of file diff --git a/templates/components/header_nav.html b/templates/components/header_nav.html new file mode 100644 index 0000000..5debf42 --- /dev/null +++ b/templates/components/header_nav.html @@ -0,0 +1,60 @@ + + + + +
\ No newline at end of file diff --git a/templates/home.html b/templates/home.html index 4131cfd..d42a57f 100644 --- a/templates/home.html +++ b/templates/home.html @@ -3,70 +3,196 @@ -Secure, efficient, and intelligent document handling for modern law practices
- Get Started +Secure, intelligent, and scalable document management platform designed for modern enterprises. Streamline workflows, enhance collaboration, and protect your data.
+Everything you need to manage documents efficiently and securely
+Bank-level encryption and secure cloud storage for your sensitive legal documents
+ +Create isolated collaboration environments with granular permissions, file storage, and real-time messaging for teams and projects.
Advanced search capabilities to find any document in seconds
+ +Advanced chat system with file attachments, member management, conversation history, and instant notifications.
Seamless collaboration tools for legal teams and clients
+ +Upload, organize, search, and manage files with hierarchical folders, version control, and comprehensive metadata tracking.
+Comprehensive notification system with customizable email templates, SMTP integration, and real-time alerts.
+Granular permission system with user roles, access controls, and comprehensive audit logging for security compliance.
+Customizable color system with CSS custom properties, allowing instant theme changes and brand customization.