Buy Template Now $65
Skip to main content

Content Editing


Pulse AI uses a content-driven architecture, which means most page content is stored inside dedicated content files rather than directly inside components.

This makes it easy for content editors, marketers, and developers to update copy, images, features, pricing, legal pages, and blog content without touching UI code.


Content Directory Structure

All editable content is located inside the content directory.

pulse-ai/
├── content/
   ├── blog/
   ├── marketing/
   ├── legal/
   └── shared/

Folder Purpose

| Folder | Description | | ----------- | ----------- | | blog | Blog posts, articles, guides, and resources | | marketing | Homepage, landing pages, pricing, features, testimonials, FAQs, etc. | | legal | Privacy Policy, Terms of Service, Cookie Policy, Compliance pages | | shared | Reusable content used across multiple pages |


How Content Is Imported

Components do not contain hardcoded text. Instead, content is imported from the content directory.

import { BENEFITS_CONTENT } from "@/content/marketing/benefits";

The imported content is then passed into a component:

<BenefitsSection
  title={BENEFITS_CONTENT.title}
  subtitle={BENEFITS_CONTENT.subtitle}
  benefits={BENEFITS_CONTENT.items}
/>

This means you only need to edit the content file when updating website copy.


Example Content File

File location:

content/
└── marketing/
    └── benefits.ts

Content:

export const BENEFITS_CONTENT = {
  title: "Why Teams Choose Pulse AI",
  subtitle: "Automate workflows, improve productivity, and scale faster.",
  items: [
    {
      title: "Save Time",
      description: "Automate repetitive tasks and focus on strategic work.",
      icon: "Clock",
    },
    {
      title: "Increase Revenue",
      description: "Generate more leads and improve conversion rates.",
      icon: "TrendingUp",
    },
    {
      title: "Improve Collaboration",
      description: "Keep your team aligned with centralized workflows.",
      icon: "Users",
    },
  ],
};

Matching Component Props

Content objects should mirror the structure expected by the component.

For example, if a component expects:

interface BenefitItem {
  title: string;
  description: string;
  icon: LucideIcon;
}
 
interface BenefitsSectionProps {
  title: string;
  subtitle: string;
  benefits: BenefitItem[];
}

The content file should provide matching data:

export const BENEFITS_CONTENT = {
  title: "Why Teams Choose Pulse AI",
  subtitle: "Automate workflows, improve productivity, and scale faster.",
  items: [
    {
      title: "Save Time",
      description: "Automate repetitive tasks.",
      icon: Clock,
    },
  ],
};

Then map it into the component:

<BenefitsSection
  title={BENEFITS_CONTENT.title}
  subtitle={BENEFITS_CONTENT.subtitle}
  benefits={BENEFITS_CONTENT.items}
/>

Because the data shape matches the component props, the component renders content automatically without additional changes.


For maximum flexibility, export content as plain objects.

export const HERO_CONTENT = {
  badge: "Trusted by 5,000+ Teams",
  title: "Scale Faster With AI",
  subtitle: "Automate operations and increase productivity.",
  primaryButton: {
    label: "Get Started",
    href: "/signup",
  },
  secondaryButton: {
    label: "Book Demo",
    href: "/demo",
  },
  image: "/images/hero/dashboard.webp",
};

Component Usage Example

Content file:

export const HERO_CONTENT = {
  title: "Scale Faster With AI",
  subtitle: "Automate operations and increase productivity.",
};

Component:

interface HeroProps {
  title: string;
  subtitle: string;
}
 
export default function Hero({ title, subtitle }: HeroProps) {
  return (
    <section>
      <h1>{title}</h1>
      <p>{subtitle}</p>
    </section>
  );
}

Page:

import Hero from "@/components/sections/hero";
import { HERO_CONTENT } from "@/content/marketing/hero";
 
export default function HomePage() {
  return (
    <Hero
      title={HERO_CONTENT.title}
      subtitle={HERO_CONTENT.subtitle}
    />
  );
}

Shared Content

Use the shared directory for content reused across multiple pages.

content/
└── shared/
    └── company.ts
export const COMPANY = {
  name: "Pulse AI",
  email: "hello@pulseai.com",
  supportEmail: "support@pulseai.com",
};

Usage:

import { COMPANY } from "@/content/shared/company";
 
<footer>
  Contact us at {COMPANY.email}
</footer>

Hero Content

Hero content lives inside the marketing directory.

content/
└── marketing/
    └── hero.ts
export const HERO_CONTENT = {
  badge: "Trusted by 5,000+ Teams",
  title: "Scale Faster With AI",
  subtitle: "Automate operations and increase productivity.",
  primaryButton: {
    label: "Get Started",
    href: "/signup",
  },
  secondaryButton: {
    label: "Book Demo",
    href: "/demo",
  },
  image: "/images/hero/dashboard.webp",
};

Legal documents live inside the legal directory.

content/
└── legal/
    ├── privacy-policy.ts
    ├── terms-of-service.ts
    └── cookie-policy.ts
export const PRIVACY_POLICY = {
  title: "Privacy Policy",
  sections: [
    {
      heading: "Information We Collect",
      content: "We collect information you provide directly to us.",
    },
  ],
};

Best Practices

  • Keep all editable text inside content/
  • Match content structure to component props
  • Use descriptive export names
  • Store reusable values in shared/
  • Avoid hardcoded marketing copy inside components
  • Keep components focused on presentation and layout
  • Let content files control text, images, links, and CTA labels

Summary

Pulse AI separates content from presentation. Components are responsible for how content looks, while files inside the content directory control what content is displayed.

This approach makes the application easier to maintain, easier to localize, and significantly faster to update without modifying component logic.