codeat3/blade-academicons
A Laravel Blade component package for using Academicons icons in your views. Render scholarly and academic SVG icons with simple Blade tags, with support for sizing and styling via CSS classes. Ideal for Laravel apps needing academic iconography without hand-writing SVG markup.
Install and confirm.
composer require codeat3/blade-academicons
php artisan about # or: composer show codeat3/blade-academicons
php artisan view:clear
Auto-discovery registers the service provider; there are no assets to publish, no npm step, no migration. Icons are inline <svg> rendered at request time. Pin the constraint ("codeat3/blade-academicons": "^1.9") so future Laravel-compatibility bumps land without a manual review; 1.9.0 only widened the framework constraint (Laravel 13) with no API or output change.
Where to look first. Do not start from the README's icon list — it will be incomplete. The authoritative slug list is the icon source in the vendor directory:
ls vendor/codeat3/blade-academicons
# the directory holding the raw .svg files is the ground truth for slugs
The slug is the filename minus .svg, kebab-cased, and it becomes the component suffix. orcid.svg → <x-academicons-orcid />; google-scholar.svg → <x-academicons-google-scholar />. Skim the directory once, write down the ~10 marks you actually need, and ignore the rest. Roughly 150 exist; a researcher-facing product needs maybe eight.
First use case — an author byline. The highest-value, lowest-risk first surface is a link row on a publication or profile page:
<a href="https://orcid.org/0000-0002-1825-0097"
target="_blank" rel="me noopener"
class="inline-flex items-center gap-1.5 text-sm text-gray-600 hover:text-gray-900">
<x-academicons-orcid class="h-4 w-4" aria-hidden="true" />
<span>ORCID</span>
</a>
Ship exactly one of these, in light and dark mode, before doing anything else. It validates rendering, currentColor theming, and sizing in one pass, and it is the shape every subsequent call site will take.
Direct usage. The component renders a bare <svg> whose attributes pass through to the root element, so Tailwind utilities and ARIA land where you expect:
<x-academicons-google-scholar class="h-5 w-5 shrink-0" fill="currentColor" />
Keep fill="currentColor" (or a CSS text-* utility driving it) rather than hardcoding a brand color. That single convention is what makes dark mode and hover states free.
Wrap it once — the pattern that pays for itself. Do not scatter raw icon components across views. Build one internal component that owns anchor semantics, accessible labeling, spacing, and the icon lookup:
{{-- resources/views/components/academic-link.blade.php --}}
@props(['icon', 'href', 'label'])
<a href="{{ $href }}"
target="_blank"
rel="me noopener"
{{ $attributes->merge(['class' => 'inline-flex items-center gap-1.5 text-sm hover:underline']) }}>
<x-dynamic-component
:component="'academicons-'.$icon"
class="h-4 w-4"
aria-hidden="true" />
<span class="sr-only">{{ $label }}</span>
</a>
Call sites then carry only data:
<x-academic-link icon="orcid" :href="$author->orcid_url" label="ORCID profile" />
<x-academic-link icon="google-scholar" :href="$author->scholar_url" label="Google Scholar" />
This is the single most important decision in the whole integration. It isolates the academicons prefix, the anchor semantics, and the icon-pack choice in one file — swapping libraries or changing the prefix later becomes a one-line edit instead of a grep-and-replace across dozens of views.
Data-driven rows. Store un-prefixed slugs in your model, config, or a small array, then loop. This is what makes the abstraction worth having:
// config/academic_links.php
'author_links' => ['orcid', 'google-scholar', 'researchgate', 'arxiv', 'dblp'],
<div class="flex gap-3">
@foreach ($author->academicLinks() as $link)
<x-academic-link :icon="$link['slug']" :href="$link['url']" :label="$link['label']" />
@endforeach
</div>
Validate slug against the known list at the data layer (a config array or an enum), not in the view. See the gotcha on unknown slugs below.
Dynamic component names. <x-academicons-{{ $slug }} /> does not work — Blade component names are resolved statically, not interpolated. The only supported form is x-dynamic-component with the full prefixed name as a string, as shown above. If you customize the prefix, that string must be built from config('blade-academicons.prefix') rather than hardcoded.
Config-driven prefix. Publish the config only if you need to avoid a name collision or want a project-specific namespace:
php artisan vendor:publish --tag=blade-academicons-config
It exposes one knob: the component prefix. There is no view to publish and no render hook. Anything beyond attributes — sizing scales, label content, link semantics — belongs in your wrapper, not in vendor patching.
Livewire and Blade-rendered markdown. Both work without special handling; the icon is ordinary inline SVG inside a Blade view. What does not work is anything that bypasses Blade compilation: a JS-side template, a client-rendered table, a Vue/React island. If your table rows are hydrated client-side, this package cannot help there.
Testing. Assert rendering rather than pixel output:
Blade::render('<x-academicons-orcid />'); // smoke test
$this->get('/authors/1')->assertSee('orcid.org'); // integration
A single smoke test is enough to catch the cache/registration failures described below.
An unknown slug fails loudly, not silently. A typo like googlescholar or google_scholar produces Unable to locate a class or view for component [academicons-...] — a 500, not a blank space. Since slugs come from filenames, they are easy to get subtly wrong (researchgate vs research-gate, semanticscholar vs semantic-scholar). Keep one validated list of slugs and let a test iterate over it, rendering every icon in use. This converts a per-page runtime failure into a single CI failure.
Stale caches after config or dependency changes. Component registration is compiled. After changing the prefix, running composer update, or deploying, run:
php artisan view:clear && php artisan config:clear
A stale compiled view references the old prefix and 500s every page that uses an icon. Put this in the deploy runbook, not in someone's memory. It is the most likely production incident this package will cause.
Inline SVG is not free at scale. Every usage inlines the full path set. One icon in a footer or a profile header: irrelevant. Five icons per row in a 500-row publication table: hundreds of kilobytes of duplicate markup. Mitigations, in order of preference:
<symbol> sprite once per page and <use>-reference it.Decide this as a UI convention now, before someone loops icons into a data table.
Passing class works; passing conflicting attributes does not merge how you expect. Attribute pass-through merges utility classes, but if the vendored SVG carries a hardcoded fill or width/height, your class may lose. Check one rendered icon in devtools before assuming h-5 w-5 is in control. Always set an explicit size — an unsized inline SVG is a layout-shift source.
Accessibility has two correct modes, and mixing them is the usual bug. If there is a visible text label next to the icon, the icon is decorative: aria-hidden="true" and no aria-label. If the icon is standalone, it needs role="img" plus aria-label. Icon-only links additionally need an sr-only text node or aria-label on the <a>, not on the <svg>. The wrapper component should enforce one of these so call sites cannot get it wrong.
Do not put these in email. Gmail strips or mangles inline SVG in several contexts and Outlook desktop is inconsistent. Transactional and marketing mail should use hosted PNGs or plain text links. This is a web-app tool.
Trademark hygiene is a one-line policy, not a project. The marks are trademarks of ORCID, Google Scholar, ResearchGate, and others, and the icon set carries its own upstream license. Using them adjacent to a real profile link is standard practice. Using them as decorative trust signals on a marketing page implies an endorsement that does not exist. Write the sentence down and move on.
If you are migrating off the Academicons webfont, finish the job. Existing <i class="ai ai-orcid"> markup renders nothing once the CSS is gone, and leaving the CSS ships a font you no longer need. Remove the markup, the ai ai-* stylesheet, and the font files in the same change; otherwise you get invisible icons that look like a CSS regression for a week.
Treat the wrapper as your abandonment insurance. One star, zero dependents, single maintainer. That is fine for what this is — but it means the wrapper component is not optional polish, it is the thing that makes replacing this package a 20-minute task instead of a 20-file audit. If you find yourself importing the vendor path directly or patching a published view, you have spent the insurance premium.
Scope discipline. Academicons is a narrow, single-purpose set. It complements your general icon library; it does not replace it. If you already run another codeat3/blade-* package, this is convention consistency and a clean yes. If this is your first one, you are adding a one-off dependency for a narrow need — make sure the researcher-facing surface actually exists this cycle before taking the lockfile entry.
How can I help you explore Laravel packages today?