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

Wink Laravel Package

themsaid/wink

Wink is a Laravel package for quickly building a simple blog or publishing platform with a clean admin panel. Manage posts, pages, tags, and media, write in Markdown, and customize the frontend to fit your site.

View on GitHub
Deep Wiki
Context7

Getting Started

Wink is an admin-only publishing backend that bolts onto an existing Laravel app. It gives you a dashboard, a Post model, tags, image uploads, and draft/publish states — but no public-facing views. That split is the single most important thing to understand before you start: you are installing a CMS authoring tool, and you own everything the reader sees.

Minimal path:

composer require themsaid/wink
php artisan wink:install      # publishes config/migrations/assets, prompts for admin credentials
php artisan storage:link      # required for locally-stored post images
php artisan serve

Then hit /wink (or whatever path you set in config/wink.php) and log in with the account the installer created.

Where to look first:

  1. config/wink.php — dashboard path, domain binding, middleware/guard, storage disk. Almost every behavioral question is answered here.
  2. The published migrations — confirm the actual table names and columns before you write queries against them.
  3. vendor/themsaid/wink/src/Models/Post.php — the scopes (published, ordering) and relationships you'll build your frontend on.
  4. The published assets directory — this is what the dashboard's Vue bundle loads; re-publish after upgrades.

First use case (30 minutes): write one post in the dashboard → create a BlogController@show in your app that resolves by slug, 404s on unpublished posts, and renders body inside your own layout. That loop — dashboard writes, your app reads — is the entire day-to-day relationship.

Implementation Patterns

Frontend controller triad. Give yourself three routes immediately: index (paginated published posts, newest first), show (by slug), and a tag archive. Wink stores published_at, so every public query must be scoped:

$posts = Post::published()->latest('published_at')->paginate(12);
$post  = Post::published()->where('slug', $slug)->firstOrFail();

Keep drafts out of every path — index, show, RSS, sitemap, search. A single forgotten scope leaks unpublished work.

Preview without a second CMS. Add an authenticated route that resolves a post regardless of published_at, gated behind auth + your admin check, and link to it from the dashboard. Don't loosen the public published scope to support previews.

Cache aggressively, bust on events. Rendered post HTML is a perfect cache target — it changes rarely and reads constantly. Key on slug + updated_at, and clear from a model observer (saved, deleted) on the Wink Post model rather than trying to hook the dashboard controllers.

Guard the dashboard like a real admin panel. The config's middleware list is the only thing between the internet and your publish button. Wrap it with your own gate or role middleware, and if you bind Wink to a separate domain in config, remember the session cookie domain still has to line up or you'll get login redirect loops.

Images. Uploads land on the disk named in config. Local: verify storage:link and that APP_URL is correct, or you'll get absolute URLs pointing at nothing. S3: the bucket objects must be publicly readable (or you need a URL resolver), because Wink stores a URL, not a signed redirect. Add your own resizing/srcset pipeline downstream — Wink doesn't generate derivative sizes.

Headless / decoupled. If you want a separate frontend, skip Wink's views entirely: build JSON Resource classes over the Wink models and serve them from your own routes. Nothing in the package forces server-rendered HTML.

Multi-author. Posts relate to your app's user model, so author pages are just an eager-loaded author relationship plus a query filter. Same story for tag archives via the pivot.

Testing. Wink ships no factories you can rely on long-term; write your own and truncate/refresh the Wink tables in your test suite. Assert the negative cases — draft not in index, draft 404 on show — because those are the regressions that actually ship.

Gotchas and Tips

  • Maintenance risk is the headline. Last release was May 2023. On Laravel 11/12 you may hit illuminate/* constraint conflicts and middleware/JSON-column quirks. Either pin your Laravel version, loosen the constraints deliberately, or budget time for a fork. Don't discover this during a framework upgrade.
  • Table-name collisions. Wink creates its own posts/tags tables in your database. If you already have a posts table, stop and rename before running migrations. Check the published migrations rather than assuming a prefix.
  • Re-publish assets after every upgrade (vendor:publish --force), or the dashboard will silently run stale JavaScript against a newer API and fail in confusing ways.
  • Don't edit vendor files. Publish view overrides into resources/views/vendor/wink and keep your diff upgradeable.
  • Timezone drift. published_at comparisons against now() are the classic "why is my post live early/late" bug. Pick UTC end-to-end and set app.timezone accordingly; scheduled publishing works via the scope, so no queue or cron is needed — but cached pages won't invalidate themselves at publish time. Run a scheduled cache-bust if you cache.
  • Auth guard mismatch is the most common install failure: the dashboard's configured guard doesn't match the one your session actually uses. Symptom is an infinite redirect to login despite correct credentials.
  • Sanitize on output, not input. The editor stores HTML. If non-admins can ever author, sanitize at render time so you can tighten policy later without rewriting content.
  • Uninstalling is manual. Removing the package leaves tables, uploaded files, and published config behind. Write down what wink:install touched on day one so teardown is possible.
  • Debugging checklist: php artisan route:list | grep -i wink to confirm the dashboard is actually registered; config('wink.path') and config('wink.middleware') to confirm routing and auth; Telescope for the queries behind a slow index page.
  • What you're signing up for: no sitemap, RSS, comments, search, SEO fields, revisions, or preview links out of the box. Those are all yours. Wink's real value is a competent, zero-config authoring UI plus a clean model you can build on — evaluate it as a starting point, not a finished blog.
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.
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core
nodisrupt/laravel-agent
sierratecnologia/media-manager