Rebuilding a website that has been running for years means working with much more than its design.

There are courses, articles, trainers, images, translations, old links, and countless decisions embedded in the existing content. Some are well documented. Others only become visible when you try to move them.

That was the challenge when I started rebuilding the Business Development Group website.

I wanted a new public experience and a more useful content-management system while preserving the information BDG had accumulated in WordPress. I used Claude Code as my development partner to investigate the old structure, build the new application, and develop the migration process.

Since writing the first version of this story, I have continued refining the platform. Some of the most useful lessons came from that later work: improving course descriptions, simplifying course pages, updating visual assets, and making English and Armenian behave consistently.

The migration established the foundation. Working with the resulting product revealed what needed to happen next.

Understanding what was already there

From the outside, the old website looked like a familiar collection of pages: courses, trainers, blog posts, and company information.

Inside WordPress, a course represented a much richer set of information. It could include pricing, duration, schedules, categories, trainer relationships, program content, images, translations, and metadata.

Moving the visible text would only preserve part of that information.

I began by treating WordPress as the source dataset for the migration. I exported the content and investigated how the different records and fields related to one another.

That investigation helped me decide what the new application should model explicitly. Courses, trainers, articles, media, and localized content each needed a clear place in the new system.

It also exposed an important distinction: preserving information does not require preserving the structure that originally stored it.

Building a new application around the content

The rebuild uses a custom PHP/Laravel application, with Blade templates and Tailwind CSS for the interface. Claude Code supported the development work across the application and migration tooling.

This gave me room to design the website and its editing experience around BDG's needs.

Course information could have dedicated fields. Trainer profiles could be managed as connected content. Blog publishing could have its own workflow. Promotional sections could be updated independently.

The public website now brings together course discovery, upcoming programs, trainers, corporate training, and educational content in English and Armenian. You can explore the result at bdg.am.

What mattered to me was the connection between these two sides of the product: the experience visitors see and the tools the team uses to maintain it.

A page is much easier to keep useful when its underlying content is structured clearly.

Making the migration repeatable

I approached the migration as a series of transformations.

WordPress courses became course records in the new application. Posts became blog content. Media references needed their own handling. Language relationships had to be interpreted and carried forward.

Where possible, I preserved a reference to the original WordPress record. This made it possible to recognize content that had already been imported.

That changed the workflow considerably. I could run an import, inspect the result, correct the mapping, and run it again without deliberately creating a second copy of everything.

Repeatability gave me room to learn.

An importer also needed to report what it could not resolve confidently: missing translations, unclear relationships, duplicate slugs, missing images, or content requiring manual review.

Those reports helped me focus on exceptions instead of manually inspecting every record with equal attention.

Migrating two languages

English and Armenian made the migration more demanding.

Language versions could have different amounts of content. Some relationships were explicit; others required investigation. A translated page might exist while individual fields remained empty.

I wanted the migration to preserve the source accurately. When reliable content was missing, the right next step was to flag it for review. Translation and editorial improvement could happen separately.

This separation made it easier to understand where information came from and which changes were intentional.

Localization also affected presentation. A layout that worked with a short English heading could behave differently with Armenian text. URLs, character encoding, spacing, and language selection all needed attention.

These concerns continued after the initial migration. Every new content feature had to work across both languages and across different generations of course content.

Giving media its own migration strategy

Images required more than copying a URL.

The new application needed to understand existing WordPress media references during the transition while supporting a separate storage approach for newly managed assets.

That transitional approach allowed the work to proceed in stages. The website could recognize legacy references while the media system evolved.

Later, I refined another part of the image experience: branded default covers for course directions.

When the names of two directions changed to "IT and Programming" and "Sales and Marketing," their artwork also needed updating. The labels and covers had to tell the same story.

I prepared optimized WebP versions of the replacement artwork, preserving the composition and matching the existing cover proportions. The default-cover mapping could then be updated while courses with individually uploaded images retained their own artwork.

It was a small example of how a design decision travels through a content system. Renaming a category can affect navigation, imagery, course pages, and editorial expectations.

Preserving the routes people already knew

Old URLs were another important part of the migration.

People could arrive through a search result, a bookmark, or a link published years earlier. The new routing structure needed to account for those entry points.

I created mappings between legacy URLs and their new destinations and made old paths part of the migration checks.

This expanded my definition of a working page. The new page needed to render correctly, and an existing link needed to lead somewhere appropriate.

I came away treating URL history as part of the content being migrated. It carries continuity for both readers and search engines.

Refining the course page after the rebuild

Once the foundation was in place, I continued working on how course information was presented.

One example was the introductory text beneath course titles. Depending on the course, that text could come from an excerpt, a translated short description, or an imported content block.

Initially, I removed a generic fallback sentence that added little value. Further review led to a broader decision: remove the description block from the hero so the title, learning outcomes, and primary actions had a clearer hierarchy.

The underlying descriptions remained available for other uses, including relevant content sections and metadata.

That distinction mattered. Editing the presentation did not require deleting useful source material.

The implementation also needed to account for both languages and multiple content sources. A change that appeared complete on an English course could still leave the equivalent Armenian text visible through a different path.

This became a recurring lesson: verify the content paths behind the interface, especially when migrated and newly created records coexist.

A description editor revealed a deeper problem

One of the latest improvements began with a straightforward issue: a course description written as separate paragraphs could appear on the public page as one continuous block of text.

The text had been saved, but its intended structure had not carried through to the rendered page.

I improved the description editor to support paragraphs, bullet lists, numbered lists, emphasis, and links. The implementation reused an editing pattern already present in the course form.

Existing descriptions needed attention too. Plain text containing line breaks and lists had to remain readable, while imported WordPress content that already contained formatting needed to retain its structure.

During that investigation, I also found a related language issue: the English description of a newly created course could be omitted because of how the page selected its localized content.

The work therefore addressed both formatting and language selection, with regression tests covering the relevant behavior.

It was a useful reminder that an editor feature spans an entire journey: writing, saving, reopening, selecting the language, and displaying the result.

Automated checks covered those paths. Browser review remained a separate step for confirming the final appearance on desktop and mobile.

Making pricing easier to read

Another recent refinement was standardizing the displayed currency label to AMD.

The numerical values and pricing rules stayed the same. The change concerned how the amount was communicated, including keeping the amount and currency label together where appropriate.

Even a small formatting change required checking different states: monthly pricing, full-course pricing, discounts, and both languages.

These details are easy to underestimate during a redesign. They become more noticeable once the larger layout is working and attention shifts toward consistency.

How Claude Code supported the work

Claude Code was useful throughout the project because it could help investigate connected parts of the application.

I could ask it to trace how a WordPress field was imported, how a translation was selected, where a price was formatted, or why a description appeared differently on the public page.

That made the workflow more fluid:

Understand the behavior, define the intended result, implement the change, inspect it, and test the surrounding cases.

I still made the product decisions. I reviewed assumptions and judged whether the result made sense for BDG.

Sometimes a technically reasonable implementation missed the intended experience. Sometimes an investigation uncovered a second issue behind the first. Both required continued attention.

The value was in being able to work through those questions faster and carry an improvement across the connected parts of the product.

Testing real content changed the design

Real content challenged assumptions that clean mockups would never have exposed.

Long titles affected hierarchy. Missing dates changed what a course card could say. Partial translations revealed gaps in language handling. Imported descriptions and newly authored descriptions behaved differently.

I used automated tests to check repeatable behavior, including content rendering, localization, URL handling, and compatibility with migrated records.

Visual review served a different purpose. It helped assess whether paragraphs were readable, list markers were visible, Armenian text wrapped well, and the page remained balanced on smaller screens.

Neither replaced the other.

A structurally correct page still needs to be read and used.

What I would repeat

The most useful practices from this project were straightforward:

  • Understand the old content model before designing the migration.
  • Preserve source references so imports can be traced and repeated.
  • Report uncertainty instead of silently guessing.
  • Treat media, language relationships, and URLs as migration work.
  • Separate source preservation from editorial changes.
  • Check both migrated content and newly created content.
  • Use real examples early enough to influence the design.
  • Keep testing the complete editing and publishing journey.

I would also leave room for refinement after the rebuild. The course editor, hero layout, covers, and currency labels all showed how much can be learned once the new system is in use.

The result is a bilingual application with its own content model and editing experience, carrying forward years of material from WordPress.

For me, the most rewarding part has been gaining the ability to keep improving it. The same understanding that made the migration possible now helps me make smaller, more precise product decisions — and follow them through from the editor to the page a visitor sees.