Back to Writing Page

πŸ—„οΈ JSON Documentation Structure for Product Copywriting

7 min read

Managing copy and text content in applications often starts simple but quickly becomes chaotic as your product grows. You begin with hardcoded strings scattered throughout your codebase, then realize you need translations, then struggle with inconsistent messaging across different parts of your app.

This guide presents an structured approach to organizing your copywriting documentation using JSON files that grows with your product. Whether you're building a simple MVP or managing a complex multi-language application, this system helps you maintain consistent, translatable, and maintainable copy across your entire product.

This is an extended explanation from this blog about How content designers can (and should) use JSON files.

The key principle is progressive complexity: start with the basics when you're small, then gradually expand the structure as your needs grow. This approach prevents over-engineering early on while ensuring you have a solid foundation for scaling.

Basic Structure (Level 1)

copydocs/
β”œβ”€β”€ en/                 # English copy
β”œβ”€β”€ id/                 # Indonesian copy  
└── README.md          # Documentation

Core Pages Structure (Level 2)

copydocs/
β”œβ”€β”€ en/
β”‚   β”œβ”€β”€ auth.json           # Authentication (login, signup, forgot password)
β”‚   β”œβ”€β”€ homepage.json       # Landing/homepage content
β”‚   β”œβ”€β”€ onboarding.json     # User onboarding flow
β”‚   β”œβ”€β”€ dashboard.json      # Main dashboard/home after login
β”‚   β”œβ”€β”€ profile.json        # User profile and account settings
β”‚   β”œβ”€β”€ errors.json         # Error messages and alerts
β”‚   └── common.json         # Shared/common copy (buttons, labels, etc.)
β”œβ”€β”€ id/
β”‚   β”œβ”€β”€ auth.json
β”‚   β”œβ”€β”€ homepage.json
β”‚   β”œβ”€β”€ onboarding.json
β”‚   β”œβ”€β”€ dashboard.json
β”‚   β”œβ”€β”€ profile.json
β”‚   β”œβ”€β”€ errors.json
β”‚   └── common.json
└── README.md

Expanded Structure (Level 3)

copydocs/
β”œβ”€β”€ en/
β”‚   β”œβ”€β”€ auth.json           # Login, signup, password reset
β”‚   β”œβ”€β”€ homepage.json       # Hero, features, pricing, testimonials
β”‚   β”œβ”€β”€ onboarding.json     # Welcome, setup, tutorials
β”‚   β”œβ”€β”€ dashboard.json      # Main dashboard after login
β”‚   β”œβ”€β”€ profile.json        # Account settings, preferences
β”‚   β”œβ”€β”€ billing.json        # Payments, subscriptions, invoices
β”‚   β”œβ”€β”€ notifications.json  # In-app notifications, alerts
β”‚   β”œβ”€β”€ search.json         # Search functionality copy
β”‚   β”œβ”€β”€ help.json          # Help center, FAQ, support
β”‚   β”œβ”€β”€ errors.json         # All error messages
β”‚   β”œβ”€β”€ success.json        # Success messages and confirmations
β”‚   β”œβ”€β”€ common.json         # Buttons, labels, navigation
β”‚   └── components/         # UI component-specific copy
β”‚       β”œβ”€β”€ modals.json
β”‚       β”œβ”€β”€ forms.json
β”‚       β”œβ”€β”€ tables.json
β”‚       └── navigation.json
β”œβ”€β”€ id/
β”‚   └── [same structure as en/]
└── README.md

Complete Structure (Level 4) - For Generic Product App

copydocs/
β”œβ”€β”€ en/
β”‚   β”œβ”€β”€ auth.json              # Authentication flows
β”‚   β”œβ”€β”€ homepage.json          # Public homepage/landing
β”‚   β”œβ”€β”€ about.json             # About us, company info
β”‚   β”œβ”€β”€ pricing.json           # Pricing plans and features
β”‚   β”œβ”€β”€ onboarding.json        # User onboarding experience
β”‚   β”œβ”€β”€ dashboard.json         # Main dashboard/home
β”‚   β”œβ”€β”€ profile.json           # User profile management
β”‚   β”œβ”€β”€ settings.json          # App settings and preferences
β”‚   β”œβ”€β”€ billing.json           # Payment and subscription
β”‚   β”œβ”€β”€ team.json              # Team management (if applicable)
β”‚   β”œβ”€β”€ projects.json          # Projects/workspace management
β”‚   β”œβ”€β”€ analytics.json         # Analytics and reporting
β”‚   β”œβ”€β”€ integrations.json      # Third-party integrations
β”‚   β”œβ”€β”€ notifications.json     # Notification center
β”‚   β”œβ”€β”€ search.json            # Search functionality
β”‚   β”œβ”€β”€ help.json              # Help center and support
β”‚   β”œβ”€β”€ legal.json             # Terms, privacy, policies
β”‚   β”œβ”€β”€ blog.json              # Blog/content section
β”‚   β”œβ”€β”€ contact.json           # Contact and support forms
β”‚   β”œβ”€β”€ admin.json             # Admin panel (if applicable)
β”‚   β”œβ”€β”€ mobile.json            # Mobile-specific copy
β”‚   β”œβ”€β”€ emails.json            # Email templates and content
β”‚   β”œβ”€β”€ errors.json            # Error messages
β”‚   β”œβ”€β”€ success.json           # Success messages
β”‚   β”œβ”€β”€ loading.json           # Loading states and placeholders
β”‚   β”œβ”€β”€ empty-states.json      # Empty state messages
β”‚   β”œβ”€β”€ common.json            # Shared copy across app
β”‚   └── components/            # Component-specific copy
β”‚       β”œβ”€β”€ navigation.json    # Menus, breadcrumbs
β”‚       β”œβ”€β”€ modals.json        # Modal dialogs
β”‚       β”œβ”€β”€ forms.json         # Form labels and validation
β”‚       β”œβ”€β”€ tables.json        # Table headers and actions
β”‚       β”œβ”€β”€ buttons.json       # Button text variations
β”‚       β”œβ”€β”€ tooltips.json      # Tooltip messages
β”‚       β”œβ”€β”€ badges.json        # Status badges and labels
β”‚       └── cards.json         # Card components
β”œβ”€β”€ id/
β”‚   └── [exact same structure as en/]
β”œβ”€β”€ locales.json               # Locale configuration
β”œβ”€β”€ translation-keys.md        # Translation key conventions
└── README.md                  # Complete documentation

Sample JSON Structure

auth.json

{
  "login": {
    "title": "Welcome Back",
    "subtitle": "Sign in to your account",
    "email_label": "Email Address",
    "password_label": "Password",
    "submit_button": "Sign In",
    "forgot_password": "Forgot your password?",
    "signup_link": "Don't have an account? Sign up"
  },
  "signup": {
    "title": "Create Account",
    "subtitle": "Get started with your free account",
    "name_label": "Full Name",
    "email_label": "Email Address",
    "password_label": "Password",
    "confirm_password_label": "Confirm Password",
    "submit_button": "Create Account",
    "login_link": "Already have an account? Sign in"
  }
}

common.json

{
  "buttons": {
    "save": "Save",
    "cancel": "Cancel",
    "delete": "Delete",
    "edit": "Edit",
    "submit": "Submit",
    "back": "Back",
    "next": "Next",
    "previous": "Previous"
  },
  "navigation": {
    "home": "Home",
    "dashboard": "Dashboard",
    "profile": "Profile",
    "settings": "Settings",
    "help": "Help",
    "logout": "Sign Out"
  },
  "status": {
    "loading": "Loading...",
    "saving": "Saving...",
    "saved": "Saved successfully"
  }
}

And for the implementation, I'll use these Javascript/React code:

JavaScript/React

// utils/copy.js
class CopyManager {
  constructor(locale = 'en') {
    this.locale = locale;
    this.cache = {};
  }

  async loadCopy(page) {
    if (!this.cache[page]) {
      const response = await fetch(`/copydocs/${this.locale}/${page}.json`);
      this.cache[page] = await response.json();
    }
    return this.cache[page];
  }

  async get(page, key) {
    const copy = await this.loadCopy(page);
    return this.getNestedValue(copy, key);
  }

  getNestedValue(obj, key) {
    return key.split('.').reduce((o, k) => o?.[k], obj);
  }
}

// react
// Usage in React component
import { useState, useEffect } from 'react';

function LoginForm() {
  const [copy, setCopy] = useState({});
  const copyManager = new CopyManager('en');

  useEffect(() => {
    copyManager.loadCopy('auth').then(setCopy);
  }, []);

  return (
    <form>
      <h1>{copy.login?.title}</h1>
      <p>{copy.login?.subtitle}</p>
      <input placeholder={copy.login?.email_label} />
      <input type="password" placeholder={copy.login?.password_label} />
      <button>{copy.login?.submit_button}</button>
    </form>
  );
}

Naming Convention for JSON Keys

The example keys above still use generic names like "title", "password_label", "submit", etc. Therefore, I recommend using a naming pattern for better readability and collaboration with developers to make it more maintainable.

I recommend the naming pattern:
{feature}{Component}{Scenario}

  • Feature: The main functionality or page area (login, dashboard, billing)
  • Component: The UI element type (button, modal, form, message)
  • Scenario: The specific state or action (success, error, loading, empty)

Examples

Good Examples:

{
  "loginFormError": "Invalid email or password",
  "dashboardCardEmpty": "No data available",
  "billingModalSuccess": "Payment method updated successfully",
  "profileButtonSave": "Save Changes",
  "searchInputPlaceholder": "Search products...",
  "onboardingStepTitle": "Welcome to our platform",
  "teamInviteSuccess": "Invitation sent successfully",
  "projectDeleteConfirm": "Are you sure you want to delete this project?"
}

Avoid These:

{
  "error1": "Something went wrong",     // Not descriptive
  "btn_save": "Save",                   // Inconsistent format
  "loginError": "Invalid credentials",  // Missing component
  "message": "Success",                 // Too generic
  "delete_project_confirmation": "Are you sure?" // Inconsistent case
}

Detailed Naming Guidelines

1. Feature Names (First Part)

  • Use the main page or functionality area
  • Keep it concise but descriptive

Examples: auth, dashboard, billing, profile, onboarding, search

2. Component Names (Second Part)

  • Describe the UI element type
  • Use singular form

Examples: Button, Modal, Form, Card, Input, Message, Title, Label

3. Scenario Names (Third Part)

  • Describe the state, action, or context
  • Be specific about the situation

Examples: Success, Error, Loading, Empty, Confirm, Cancel, Submit, Placeholder

Best Practices

  • Be Consistent: Stick to your chosen pattern across all files
  • Use CamelCase: Easier to read and consistent with JavaScript conventions
  • Be Descriptive: Someone should understand the context from the key name
  • Avoid Abbreviations: Use Button instead of Btn, Message instead of Msg
  • Group Related Items: Keep similar functionality together in the JSON structure
  • Document Edge Cases: Add comments in your README for special naming rules

Key Benefits of This Structure

  • Scalable: Easy to add new languages and pages
  • Organized: Logical grouping by functionality
  • Maintainable: Clear separation of concerns
  • Developer-friendly: Easy to import and use in code
  • Translator-friendly: Clear context for each copy element

The best system is the one your team will actually use consistently. Start small with just the core pages you need today, establish clear naming conventions early, and expand the structure as your product and team grow.

And hey, if you need a UX Writer/Technical Writer with more than 8+ years experience to make your content documentation more neat?
I'm just a one form away for project collaboration.

Read Another?

πŸ’° Fintech in Indonesia, The Importance of Clear Product Communication

Customer data exploitation, customer trust, and the fatal tragedy of advertising strategy.

Read this one

πŸ“ PRD for Writing Guidelines Tool

A Product Requirements Document for my interactive Writing Guidelines tool, designed to help, well, myself and clients to create consistent and effective content at scale.

Read this one

πŸ§‘πŸ»β€πŸ³ When Rigor Becomes Freedom, Its The Discipline of Mastery

I want to discuss one of the things I enjoy, the culinary world from the perspective of a connoisseur (well, more from a foody POVs precisely).

Read this one