Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Google Docs Help Bundle Laravel Package

codific/google-docs-help-bundle

A Symfony bundle that renders help pages from Google Docs content, letting non-technical teams edit documentation in Docs while the application serves it automatically.

View on GitHub
Deep Wiki
Context7

Getting Started

Read the code before you read the README. In a repo with no stars, no dependents, and no release cadence, the docs drift and there's no community to ask. Open these in order:

  1. README.md — for the intended config shape (treat it as a suggestion, not a contract).
  2. DependencyInjection/Configuration.php — the authoritative list of config keys. Everything else is commentary.
  3. DependencyInjection/*Extension.php — how services are wired, aliased, and tagged.
  4. Service/ — the real pipeline: Google Docs fetch → parse → HTML render.

Everything you actually care about lives in Service/. The bundle wrapper is mostly plumbing around it.

Minimal setup (Symfony host app):

composer require codific/google-docs-help-bundle
  1. Register the bundle in config/bundles.php (Flex may handle this).
  2. In Google Cloud: create a service account, enable the Google Docs API and Google Drive API, download the JSON key.
  3. Share the target Google Doc with the service account email (Viewer is sufficient). Skip this and you get 403/404 — this is the step everyone forgets.
  4. Add config/packages/codific_google_docs_help.yaml with the credentials path and the document ID (the long string in the Docs URL, not the URL itself).
  5. Confirm wiring:
bin/console debug:container | grep -i codific
bin/console config:dump-reference <bundle_alias>

First use case — the one that justifies the package: a public Help/FAQ page where a non-technical author edits a Google Doc using Heading 1/2/3, paragraphs, bullet lists, links, images, and tables, and the site renders a clean styled page. Inject the bundle's renderer service into a controller, pass the document ID, output the HTML in Twig, and wrap the fetch in cache so you aren't billing the Docs API per request.

If you're on Laravel, stop and read this first. This is a Symfony bundle, not a Laravel package. There is no service provider, no facade, no config/*.php publish. Your realistic options:

  • Port the parsing services from Service/ into app/Support/ and bind them in a ServiceProvider (most likely path, ~a few days).
  • Run it as a sidecar Symfony service and call it over HTTP.
  • Skip it entirely and hit google/apiclient directly (the TPM assessment's recommendation, and probably correct).

Do not attempt to boot a Symfony DI container inside Laravel just to consume this. Dual-container setups are fragile and will cost you more than the port.

Implementation Patterns

Treat fetch, parse, and render as three separate concerns. Don't assume a single call does everything — inspect Service/ and compose the pieces yourself. The natural seam is:

Docs API client → raw Document JSON → parser → node tree → renderer → HTML

That node-tree boundary is the only place worth integrating against. It makes the package testable, lets you swap the renderer, and lets you feed recorded fixtures instead of live API responses.

Wrap it in your own interface — this is non-negotiable. Whatever you do, don't let controllers or Blade/Twig templates depend on bundle internals:

interface HelpPageRenderer
{
    public function render(string $documentId): string;
}

Then implement it with the bundle's services (or your ported copy, or a direct google/apiclient call). This is your seam for swapping implementations, adding sanitization, and surviving the day you fork or drop the dependency.

Cache hard, render cheap. The Docs API is slow and quota-limited. Never call it per request.

return Cache::remember("help:doc:{$documentId}", now()->addHours(1), function () use ($documentId) {
    return $this->renderer->render($documentId);
});

Key by document ID. Invalidate on deploy. Expose an artisan/console command (help:refresh) so support can force a re-fetch after an edit without waiting for TTL.

Persist the parse output, not just the HTML. Save the fetched/parsed node tree (JSON) to disk or a cache key as a build step. Benefits: deterministic rendering, page survives Google outages or credential rotation, and you get a diffable history of content changes. For critical pages, commit the artifact.

Sanitize before |raw. Google Docs content is user-controlled — anyone with edit access to the doc can inject whatever the Docs API will return. Run output through symfony/html-sanitizer (or Laravel's mews/purifier) with an allowlist of the tags your authors actually use. Treat image URLs and link hrefs as untrusted.

Override templates rather than patching vendor. Symfony bundles expose templates at templates/bundles/<BundleName>/. Copy the bundle's templates into your app, restyle to your design system, and keep the override thin so bundle updates don't become merge conflicts. Same idea for node renderers: implement the bundle's renderer interface and tag the service rather than editing vendor/.

Drive document IDs from config/env per environment. Staging renders a draft doc; production renders the published one. Put the ID in .env and read it through a config value, not hardcoded in a controller.

Add a smoke test against a recorded fixture. Capture a real Docs API JSON response, commit it, and assert the rendered HTML contains expected headings, list items, and resolved image URLs. These are the tests that catch Google API shape changes before your help page goes blank.

Gotchas and Tips

It is a Symfony bundle, not a Laravel package. Repeating because it's the single most expensive misunderstanding here. No service provider, no facade, no publishes(). Confirm this before you commit to an approach.

Google API setup is the classic failure point. Three errors account for nearly all breakage:

Symptom Cause
400 accessNotConfigured Docs API or Drive API not enabled in the project
403 / 404 Doc not shared with the service account email
401 / scope errors Wrong OAuth scope, or user OAuth used where a service account was needed

Also: pass the document ID, not the URL. If you're passing anything containing docs.google.com, that's your bug.

Google Docs markup is noisier than it looks. Expect to normalize in a post-processing pass:

  • Trailing empty paragraphs at the end of every doc — drop empty nodes.
  • Soft line breaks (\n inside a paragraph), not just paragraph boundaries.
  • Heading styles applied inconsistently by authors (a "Heading 2" typed as bold body text).
  • Nested lists that flatten into siblings.
  • Images: inline object IDs need a separate resolution step against inlineObjects to get a usable URL. This is not automatic in most naive integrations.
  • Tables and code blocks usually need special handling or a custom renderer.

Build a fixture of a real, messy document and keep it in the test suite. Authors will produce shapes you didn't anticipate.

Config quirks. README examples lag Configuration.php. Trust the config tree:

bin/console config:dump-reference <alias>

If injection fails with "service not found," the service may be private — retry with debug:container --show-private and reference it by alias or inject via interface.

Debug the pipeline in two halves. Dump the raw API response and the parsed node tree separately. In practice, 90% of "the template is broken" bugs are "the parser silently dropped a node type." Once you know which half is wrong, the fix is usually obvious.

Extension points to know. The clean seams are:

  1. Custom node renderers — implement the bundle's renderer interface and tag the service. Preferred over patching.
  2. Twig template overrides — restyle without touching PHP.
  3. New node types — add a node + renderer pair, don't edit vendor code.

If you need anything beyond these, you are past the point where forking is cheaper than patching. Pin a specific commit, vendor it into your org, and document the diff in the repo.

Bus factor is the real risk. Zero stars, zero dependents, no release cadence, no security response. A composer update can silently break a production help page. Mitigate by:

  • Vendoring or forking into your org namespace with a pinned commit.
  • Keeping your HelpPageRenderer interface as the only contract your app depends on.
  • Storing rendered output as a committed artifact so a broken dependency can't take the page down.

Budget the replacement cost up front. The TPM assessment puts a from-scratch Docs-to-HTML pipeline at roughly 1–2 engineering weeks against google/apiclient. If you're spending more than that adapting this bundle, you've lost. Treat it as a reference implementation and a code sample, not a dependency you inherit.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource