Marketing Site Guide
Last Updated: 2026-02-16 Status: Implemented (Phase 1 + SEO + Contact Management + Multi-Domain + Case Studies + Team/Founder) Plan Reference: 113-multi-domain-architecture.md, 114-marketing-site.md, 126-contact-form-submissions.md, 127-import-contact-submissions-from-logs.md, 128-seo-optimization.md, 152-team-founder-page.md
Overview
The marketing site at scopeforged.com serves as the public-facing brand presence, lead generation funnel, and centralized authentication entry point. All users (clients and admins) log in through the marketing site and are redirected to their appropriate subdomain based on role.
Table of Contents
- Domain Architecture
- Pages
- Authentication Flow
- Technical Architecture
- Content Structure
- Related Features
Domain Architecture
| Domain | Purpose | Auth Required |
|---|---|---|
| scopeforged.com | Marketing site + Login | No (public) / Yes (auth routes) |
| portal.scopeforged.com | Client portal | Yes (role: client) |
| admin.scopeforged.com | Admin panel | Yes (role: admin) |
Session Sharing
Sessions are shared across all subdomains via SESSION_DOMAIN=.scopeforged.com. This enables:
- Single login for all domains
- Seamless navigation between subdomains
- Centralized logout
Pages
Public Pages
| Page | Route | Route Name | Purpose |
|---|---|---|---|
| Homepage | / | marketing.home | Hero, value proposition, process overview, CTAs |
| Process | /process | marketing.process | 5-phase development process detail |
| Services | /services | marketing.services | Overview of all services |
| Service Detail | /services/{slug} | marketing.services.show | Individual service pages |
| Audits | /audits | marketing.audits | Audit catalog (19 audits, 7 categories) |
| About | /about | marketing.about | Company story, founder profile, values |
| Contact | /contact | marketing.contact | Contact form |
| Case Studies | /case-studies | marketing.case-studies.index | Portfolio of completed work |
| Case Study Detail | /case-studies/{slug} | marketing.case-studies.show | Individual case study |
| Privacy | /privacy | marketing.privacy | Privacy policy |
| Terms | /terms | marketing.terms | Terms of service |
Authentication Pages
| Page | Route | Route Name | Access |
|---|---|---|---|
| Login | /login | login | Guest only |
| Signup | /signup | marketing.signup | Guest only |
| Forgot Password | /forgot-password | password.request | Guest only |
| Reset Password | /reset-password/{token} | password.reset | Guest only |
| Logout | /logout (POST) | logout | Authenticated |
Service Detail Pages
| Service | URL |
|---|---|
| Technical Audits & Discovery | /services/technical-audits |
| Custom Application Development | /services/custom-development |
| System Modernization & Migration | /services/modernization |
| Production Infrastructure | /services/infrastructure |
| Ongoing Support & Evolution | /services/support |
Authentication Flow
Login Flow
- User visits
scopeforged.com/login - Enters email and password
- On successful authentication:
- Admin users → Redirect to
admin.scopeforged.com - Client users → Redirect to
portal.scopeforged.com
- Admin users → Redirect to
- Session cookie is set for
.scopeforged.comdomain
Signup Flow
- User visits
scopeforged.com/signup - Fills form: name, email, company name, password
- On submission, system creates:
- User record (role: client)
- Client record (company)
- User-Client relationship
- Project record (name: "Discovery", status: draft, stage: questionnaire)
- User is logged in automatically
- Redirect to
portal.scopeforged.com/projects/{id}/questionnaire
Unauthenticated Access Handling
When an unauthenticated user attempts to access protected routes:
- Portal routes → Redirect to
scopeforged.com/login - Admin routes → Redirect to
scopeforged.com/login
Configured in bootstrap/app.php:
$middleware->redirectGuestsTo(fn () => marketing_url('/login'));
Password Reset Flow
- User clicks "Forgot Password" on login page
- Enters email on
/forgot-password - Receives email with reset link
- Clicks link →
/reset-password/{token} - Sets new password
- Redirected to login page
Technical Architecture
Controllers
| Controller | Purpose |
|---|---|
Marketing\AuthController | Login, signup, logout, password reset |
Marketing\HomeController | Homepage (inherited from layout) |
Marketing\ProcessController | Process page |
Marketing\ServicesController | Services index and detail |
Marketing\AuditsController | Audit catalog |
Marketing\AboutController | About page |
Marketing\ContactController | Contact form handling |
Marketing\CaseStudyController | Case studies listing and detail |
Views Structure
resources/views/marketing/
├── layouts/
│ └── app.blade.php # Main marketing layout
├── partials/
│ ├── header.blade.php # Navigation header
│ └── footer.blade.php # Site footer
├── auth/
│ ├── login.blade.php
│ ├── signup.blade.php
│ ├── forgot-password.blade.php
│ └── reset-password.blade.php
├── services/
│ ├── index.blade.php # Services overview
│ ├── show.blade.php # Service detail wrapper
│ └── partials/ # Service-specific content
│ ├── technical-audits.blade.php
│ ├── custom-development.blade.php
│ ├── modernization.blade.php
│ ├── infrastructure.blade.php
│ └── support.blade.php
├── home.blade.php
├── process.blade.php
├── audits.blade.php
├── about.blade.php
├── contact.blade.php
├── privacy.blade.php
└── terms.blade.php
resources/views/components/marketing/
├── founder-profile.blade.php # Founder profile card with photo, bio, credentials
├── team-member-card.blade.php # Compact team member card for future expansion
├── testimonial-card.blade.php # Client testimonial display
├── testimonial-carousel.blade.php # Testimonial carousel component
├── trust-badges.blade.php # Trust signals and badges
├── faq-item.blade.php # FAQ accordion item
├── chatbot-widget.blade.php # AI chatbot widget
├── chat-widget.blade.php # Live chat widget
└── cookie-consent.blade.php # GDPR cookie consent banner
Routes
Routes are defined in routes/marketing.php and loaded via domain-based routing in bootstrap/app.php:
Route::domain(config('domains.marketing'))
->middleware('web')
->group(base_path('routes/marketing.php'));
Helper Functions
Located in app/Helpers/domain_helpers.php:
| Helper | Purpose |
|---|---|
marketing_url($path) | Generate URL for marketing domain |
portal_url($path) | Generate URL for portal domain |
admin_url($path) | Generate URL for admin domain |
current_domain_context() | Get current domain context |
Content Structure
Homepage Sections
- Hero - Primary value proposition with CTAs
- The Problem - Why software projects fail
- The Process - Visual overview of 5 phases
- What Makes Us Different - Key differentiators
- Services Overview - Cards for each service
- Audits Highlight - 19-audit catalog emphasis
- What This Means For You - Client benefits
- Final CTA - "Start Your Discovery"
About Page Sections
- Hero - Page title and introduction
- Our Story (Why We Exist) - Company founding story and mission
- Meet the Founder - Profile card with photo, bio, credentials, and social links
- Our Values (What We Stand For) - Transparency, Accountability, Quality
- The Problem We Solve - Why software projects fail
- How We're Different - Key differentiators (portal, audits, milestones, discovery)
- Final CTA - "Start Your Discovery" and contact links
The About page includes Person schema.org markup for the founder to improve SEO.
Process Page Phases
- Discovery - Clarity before commitment
- Build - Implement with discipline
- Audit - Verify quality
- Launch - Controlled release
- Iterate - Long-term success
Audit Categories
| Category | Audits Count |
|---|---|
| Code & Architecture | 2 |
| Security | 3 |
| Performance | 3 |
| Quality | 3 |
| Operations | 3 |
| User Experience | 4 |
| Integrations | 1 |
| Total | 19 |
Animation System
All marketing pages use a consistent animation toolkit defined in resources/css/animations.css. No custom JavaScript is needed - animations are triggered by Alpine.js directives.
Animation Classes
| Class | Effect |
|---|---|
reveal reveal-up | Fade in + slide up |
reveal reveal-left | Fade in + slide from left |
reveal reveal-right | Fade in + slide from right |
reveal reveal-scale | Fade in + scale up |
reveal-stagger | Auto-delays children 100ms apart |
hero-stagger | Auto-delays children 150ms apart |
hover-lift | TranslateY + shadow on hover |
btn-shimmer | Shimmer effect on buttons |
btn-arrow-slide | Arrow slides right on hover |
press-effect | Scale down on click |
section-divider | Decorative section separator |
Patterns
Hero (immediate on load):
<div class="hero-stagger" x-data="{ shown: false }" x-init="$nextTick(() => shown = true)">
<h1 class="reveal reveal-up" :class="shown && 'revealed'">...</h1>
</div>
Section (reveal on scroll):
<div class="reveal reveal-up" x-data x-intersect.once="$el.classList.add('revealed')">...</div>
Card grid (staggered):
<div class="reveal-stagger" x-data x-intersect.once="$el.querySelectorAll('.reveal').forEach(el => el.classList.add('revealed'))">
<div class="reveal reveal-up hover-lift">Card</div>
</div>
Accessibility
Animations are automatically disabled when prefers-reduced-motion: reduce is set, handled by @media query in animations.css.
Pages with Animations
All marketing pages: Home, Process, Services, About, Contact, Blog, FAQ, Audits, and all service detail pages.
Related Features
- Authentication - Core auth system
- Client Dashboard - Portal after login
- Project Management - Project questionnaire flow
Contact Form Submissions
Contact form submissions are stored in the database for admin management and follow-up.
Contact Form Submission Flow
- User visits
scopeforged.com/contact - Fills form: name, email, company (optional), message
- Submission stored in
contact_submissionstable - Admin notification sent (database + broadcast)
- Admin can manage submissions via admin panel
Admin Management
Location: Admin → CRM → Contact Submissions or /admin/contact-submissions
Features:
- List all submissions with filtering (status, date range, search)
- View individual submission details
- Update status (new → reviewed → responded → archived)
- Add admin notes
- Delete submissions
Status Flow
[New] → [Reviewed] → [Responded] → [Archived]
↘ ↗
[Archived]
| Status | Description |
|---|---|
new | Just submitted, needs attention |
reviewed | Admin has seen it |
responded | Admin has replied via email or other means |
archived | No longer active, kept for records |
Contact Submission Model
Location: app/Models/ContactSubmission.php
| Field | Type | Description |
|---|---|---|
name | string | Submitter name |
email | string | Submitter email |
company | string | Company name (optional) |
message | text | Message content |
status | string | new, reviewed, responded, archived |
admin_notes | text | Internal notes |
reviewed_by | bigint | Admin who reviewed |
reviewed_at | timestamp | Review timestamp |
source | string | contact_form (default) |
ip_address | string | Submitter IP |
user_agent | string | Browser user agent |
Admin Notification
When a contact form is submitted, all admin users receive:
- Database notification (bell icon badge)
- Real-time broadcast notification
- Deep link to submission detail page
Anti-Spam Protections
The public contact form is gated by two zero-UX-impact bot defenses in ContactController:
- Honeypot field — a visually and semantically hidden
websiteinput is rendered in the form. Real users never see or interact with it; bots that auto-fill all fields will populate it. A non-empty value triggers a silent drop. - Time trap — on
GET /contact, the controller stores the current Unix timestamp in the session undercontact_form_loaded_at. OnPOST, the controller rejects submissions that arrive in under 3 seconds or with no recorded render time (i.e., the bot POSTed directly without ever loading the form).
When either tripwire fires, the controller:
- Returns the same success redirect and flash message a legitimate submission would (so bots cannot tell the drop from an accept and adapt their tactics)
- Writes nothing to
contact_submissions - Sends no admin notification
- Logs a
contact.spam_droppedevent with the IP, user agent, submitted name/email, and reason (honeypot_filled,no_render_timestamp, orsubmitted_too_fast)
Constants live as private const on ContactController:
HONEYPOT_FIELD = 'website'FORM_LOADED_AT_SESSION_KEY = 'contact_form_loaded_at'MIN_FORM_FILL_SECONDS = 3
Test coverage: tests/Feature/Http/Controllers/Marketing/ContactControllerTest.php (the "Spam Protection Tests" section).
If sophisticated bots adapt past these defenses, the next escalation tier is Cloudflare Turnstile / hCaptcha plus per-IP rate limiting.
Case Studies
The case studies section showcases completed projects and client success stories.
Case Studies Feature Toggle
Case Studies can be enabled/disabled via a system setting accessible in the admin panel.
Setting: case_studies_enabled (boolean, default: true)
Location: Admin → Settings (marketing group)
Behavior when disabled:
- Navigation links removed from header (desktop and mobile)
- Direct URL access returns 404
- Setting is cached for performance
Implementation:
App\Models\Settings\SystemSetting::getValue('case_studies_enabled', true)- Check performed in
CaseStudyController::ensureCaseStudiesEnabled() - Conditional rendering in
resources/views/marketing/partials/header.blade.php
Case Study Model
Location: App\Models\Marketing\CaseStudy
| Field | Type | Description |
|---|---|---|
title | string | Case study title |
slug | string | URL slug |
client_name | string | Client or company name |
industry | string | Industry category |
service_type | string | Primary service delivered |
challenge | text | The problem/challenge |
solution | text | How it was solved |
results | text | Outcomes and metrics |
featured_image | string | Hero image path |
is_featured | boolean | Show on homepage |
is_published | boolean | Publicly visible |
Case Study Views
resources/views/marketing/case-studies/
├── index.blade.php # Case studies grid with filtering
└── show.blade.php # Individual case study detail
SEO Optimization
The marketing site includes comprehensive SEO features for improved search engine visibility.
SEO Features
| Feature | Implementation |
|---|---|
| Meta titles | Unique per-page titles via SeoService |
| Meta descriptions | 155 character descriptions |
| Open Graph tags | og:title, og:description, og:image, og:type, og:url |
| Twitter Cards | summary_large_image format |
| Canonical URLs | Set on all pages |
| JSON-LD structured data | Organization, WebSite, Service, BreadcrumbList |
| Sitemap | Dynamic XML at /sitemap.xml |
| robots.txt | Sitemap reference, admin/portal disallow |
SEO Configuration
Location: config/seo.php
return [
'site_name' => 'Scopeforged',
'default_title' => 'Professional Software Development',
'default_description' => 'Scopeforged provides...',
'twitter_handle' => '@scopeforged',
'og_image' => '/images/og-default.jpg',
'locale' => 'en_US',
'organization' => [
'name' => 'Scopeforged',
'url' => 'https://scopeforged.com',
'logo' => '/images/logo.png',
// ...
],
];
SeoService
Location: app/Services/SeoService.php
// Usage in views
$seoService = app(SeoService::class);
$seoService->setTitle('About Us');
$seoService->setDescription('Learn about Scopeforged...');
$seoService->addJsonLd(['@type' => 'BreadcrumbList', ...]);
SEO Component
Location: resources/views/components/seo/meta.blade.php
<x-seo.meta
:title="$seoTitle"
:description="$seoDescription"
:canonical="$seoCanonical"
:og-image="$seoOgImage"
:json-ld="$seoJsonLd"
/>
Sitemap
Route: /sitemap.xml
Controller: app/Http/Controllers/Marketing/SitemapController.php
The sitemap is dynamically generated and includes:
- All public marketing pages
- Priority and changefreq for each URL
- Last modification timestamps
Per-Page SEO
| Page | Title Pattern | JSON-LD Schemas |
|---|---|---|
| Home | Scopeforged - Professional Software Development | Organization, WebSite |
| Process | How We Work - Our 5-Phase Process | Scopeforged | BreadcrumbList |
| Services | Software Development Services | Scopeforged | BreadcrumbList |
| Service Detail | {Service Name} | Scopeforged | Service, BreadcrumbList |
| Audits | Technical Audit Catalog | Scopeforged | BreadcrumbList |
| About | About Scopeforged | BreadcrumbList |
| Contact | Contact Us | Scopeforged | BreadcrumbList |
Team & Founder Profile
The About page features a founder profile section that humanizes the brand and builds trust.
Founder Profile Component
Location: resources/views/components/marketing/founder-profile.blade.php
<x-marketing.founder-profile
name="Philip Rehberger"
title="Founder & Lead Developer"
photo="/images/team/founder.jpg"
:credentials="['Laravel Expert', 'Security Specialist', 'Full-Stack Developer']"
linkedin="https://linkedin.com/in/philiprehberger"
github="https://github.com/philiprehberger"
>
<x-slot:bio>
<p>Bio content here...</p>
</x-slot:bio>
</x-marketing.founder-profile>
| Prop | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Full name |
title | string | Yes | Job title |
photo | string | Yes | Path to photo |
credentials | array | No | List of credentials/skills |
linkedin | string | No | LinkedIn profile URL |
twitter | string | No | Twitter/X profile URL |
github | string | No | GitHub profile URL |
bio | slot | Yes | Bio content (HTML allowed) |
Team Member Card Component
Location: resources/views/components/marketing/team-member-card.blade.php
A compact card for displaying team members in a grid layout. Useful if the team expands.
<x-marketing.team-member-card
name="Team Member"
title="Role"
photo="/images/team/member.jpg"
bio="Short bio"
linkedin="..."
/>
Required Assets
| Asset | Location | Notes |
|---|---|---|
| Founder photo | /public/images/team/founder.jpg | Minimum 800x800px, professional headshot |
Performance Optimizations
Performance improvements applied based on Lighthouse audit (2026-02-16).
Font Loading
Fonts are loaded asynchronously using the media="print" onload pattern to avoid render-blocking:
<link rel="preconnect" href="https://fonts.bunny.net" crossorigin>
<link rel="preload" href="..." as="style">
<link href="..." rel="stylesheet" media="print" onload="this.media='all'">
<noscript><link href="..." rel="stylesheet"></noscript>
JS Bundle Optimization
Echo/Pusher (73KB) are dynamically imported only when VITE_REVERB_APP_KEY is set. Marketing pages never load WebSocket dependencies. See resources/js/bootstrap.js and resources/js/echo-setup.js.
Animation Performance
The btn-shimmer effect uses transform: translateX() instead of animating the left property, running on the compositor thread to avoid CLS (layout shifts).
Cache Headers
Vite-hashed assets (app-CXfhYMq5.css) get immutable 1-year cache headers via .htaccess FilesMatch with a regex matching Vite's alphanumeric hash format.
Accessibility
- "Pending" badge in browser mockup uses
text-gray-600for WCAG AA contrast compliance (5.74:1 ratio) - Cookie consent link uses descriptive text: "Learn more about our privacy policy"
Implementation Phases
Phase 1 (Completed)
- Core public pages (home, process, services, audits, about, contact)
- Centralized authentication (login, signup, password reset)
- Role-based redirects
- Auth middleware updates
- Privacy policy and terms of service
Phase 2 (Completed)
- Contact form submission management
- Admin notification for new submissions
- SEO optimization with meta tags and structured data
- Dynamic XML sitemap
- robots.txt with sitemap reference
- Team & Founder profile section on About page
- Person schema.org markup for founder
Phase 3 (Planned)
- Blog system
- Analytics integration
- Lead magnet system
- A/B testing capability