Drupal case study · 06 Used AI tools

Connected Community and Learning

An online community needed to bring learning into the place where members already connected with people, groups, and organizations. I designed and developed the core integration between the Drupal community and a separate learning platform, including course synchronization, a searchable local course catalog, and secure course launch. The integration is in its final stages of development and has not yet launched.

Organization
An online community built on Open Social, with courses delivered through a separate Opigno learning platform.
Need
Courses lived in a separate learning system, making them harder to discover and connect to the people, groups, memberships, and experiences already inside the community.
Solution
A synchronized, searchable course catalog inside the community, OAuth 2.0 and REST communication, a secure single-use course launch, and the design for membership-based course access.
Status
In its final stages of development, with core synchronization, course discovery, and launch architecture in place. Not yet launched.
My role
Designed the integration and built the core synchronization, local course catalog, search integration, OAuth and REST communication, and secure launch flow.
  • OAuth
  • Key
  • Entity API
  • Search API
  • Queue API
  • Lock API
  • Flood API
  • HTTP Client
  • Lazy Builders

The challenge

Our community experience and learning experience lived in two different open-source Drupal products: Open Social and Opigno. Each was strong at its own job, but users experienced them as two separate systems. They could discover a conversation or organization in the community, yet courses, enrollment, and progress lived elsewhere.

Members needed to find courses where they already participated, enter the learning system without another sign-in, and see relevant learning status back in the community. We also wanted what the community already knew about a member to help decide which courses they could reach. All of that had to feel like one product without merging databases or tightly coupling two independently deployed systems.

The solution

I designed an integration that kept the two systems independent while making them work together. Course records were synchronized from the learning platform into the community as local Drupal content, so members could find courses through the community’s own search alongside people, groups, and organizations.

When a member chose a course, the launch flow checked their access and handed them to the learning platform with a secure, single-use token instead of a second sign-in. The integration was also designed so community-side rules, such as membership, could decide which courses a member could reach.

What it was designed to enable

The integration was designed to let members discover learning alongside the people, groups, and organizations already in the community. Because synchronized course records existed locally in Drupal, courses could participate in Views, search, dashboards, and planned community-side access rules such as membership-based course eligibility.

The learning platform remained responsible for the actual training experience and learner progress, while the community handled discovery, access, and the surrounding member experience. Open Social and Opigno stayed independently deployable and responsible for their own data.

My role

I designed the integration between the two systems and built the core synchronization, local course catalog, Search API integration, OAuth and REST communication, and secure course-launch flow. I also worked through the trust boundaries, failure behavior, and how community-side membership rules could influence learning access, and I reviewed the work that touched the integration on both deployments.

The project is in its final stages of development and has not yet launched, so this case study focuses on the architecture and integration work I have completed rather than presenting it as a finished production rollout.

Technical implementation

OAuth 2 credentials authenticated communication between the systems, with secrets managed through Drupal’s Key integration. A versioned REST API contract defined requests, responses, synchronization checkpoints, and errors. Course records were synchronized into local entities and indexed with Search API, so discovery remained fast, searchable, and available even when the learning system was not responding.

Launch authorization used a short-lived, one-time token instead of putting identity or durable credentials in a URL. Learner progress followed a separate synchronization path and appeared through personalized lazy builders, allowing the surrounding course page to remain cacheable. Course discovery stayed local to the community, while only narrowly authorized launch and learner-state requests crossed the boundary into the learning system.

How synchronization and launch worked

A scheduled coordinator acquired a lock, read the last saved checkpoint, and requested the next bounded batch through the authenticated REST API. It validated the response, updated local course entities, queued Search API indexing, and saved the next checkpoint only after the batch succeeded. Interrupted work resumed without skipping records.

For launch, Open Social checked the learner’s access and requested a short-lived token. The browser carried that token to Opigno, where it was consumed exactly once and checked against the intended learner and course before the destination opened. Expired, reused, or mismatched tokens failed without revealing hidden course information.

Drupal under the hood

OAuth 2, REST, and Key
Separated machine authentication from human sessions and kept secrets out of exported configuration.
Entity and Search APIs
Created a Drupal-native local catalog with normal field, display, access, Views, and indexing support.
Queue, Lock, and Flood APIs
Controlled background work, prevented overlapping synchronization, and rate-limited sensitive requests.
HTTP client, cache metadata, lazy builders, and Twig
Handled remote failure safely while keeping public pages reusable and learner status personalized.

Why I chose this approach

I chose to synchronize course information into the community instead of making every course display depend on a live request to the learning platform.

Keeping course records locally meant Drupal could use its normal tools for search, Views, dashboards, and relationships to community data. It also created a clean place for community-side rules, such as membership, to influence learning access.

The learning platform still remained responsible for the actual course experience and learner progress. That separation let each system continue doing the job it was built for while giving us a practical way to make them feel like one product.

It required more synchronization work than simply embedding a remote catalog, but it reduced runtime dependency between the two systems and gave the community much more control over how learning appeared and behaved.

Examples of how I used AI

I used it to help implement and debug parts of a complex cross-system integration, explore alternatives, refactor code, and expand automated testing while I remained responsible for the architecture, security boundaries, and technical decisions. The examples below are representative of that work rather than a complete list of where I used it.

API and authentication work
I defined the versioned API contract, trust boundaries, launch flow, and failure behavior between the two systems. I used AI while implementing and refining portions of the OAuth 2 authenticated REST API, synchronization requests, and launch-token handling, which gave me more time to concentrate on how the systems should behave when authentication failed, data was incomplete, or one side was unavailable.
Working through integration problems
The integration involved two independently deployed Drupal applications with different responsibilities for course data, learner state, authentication, and access. I used AI as another way to explore implementation options and debug behavior across that boundary, while keeping the architectural decisions and final implementation under my control.
Automated testing
AI made it practical to build more automated coverage alongside the implementation. I used it to accelerate PHPUnit tests around backend services and integration behavior and Playwright tests around browser-level workflows. I reviewed, refined, and ran those tests rather than treating generated coverage as proof by itself.
My role
I supplied the architecture, constraints, Drupal conventions, and security requirements, then reviewed the implementation and tests the same way I would review work from another developer. AI accelerated the work, but the design decisions and responsibility for the result remained mine.