The essential news about content management systems and mobile technology. Powered by Perfect Publisher and XT Search for Algolia.
The News Site publishes posts to the following channels: Facebook, Instagram, Twitter, Telegram, Web Push, Tumblr, and Blogger.
You created your website for a reason. Whether it’s showing off your art, passing on family recipes, or selling boutique high-performance yo-yos. (That may or may not be Doc Pop’s example.) You created your website to reach an audience and to communicate directly with that audience.
Wouldn’t it be great if there was an easier way for you to connect with them and make it easier for them to follow you and engage with your content online? In this final episode of the Fediverse Files, Doc Pop walks you through how to connect your WordPress site to the Fediverse using ActivityPub.
Federate your website today and get 25% off a WordPress.com Business or Commerce hosting plan by using coupon code federate25—or click below:
Get your 25% offRead more https://wordpress.com/blog/2024/09/13/wordpress-fediverse/
Laravel Herd released v1.11 this week, a significant update that includes Laravel Forge integration, sharing Herd project configuration across a team, a convenient profiler integration, and more:
Herd.yml
fileherd profile
Herd now has direct integration with Laravel Forge, enabling you to deploy your site directly from Herd, open an SSH connection on the server, or even open your site on forge.laravel.com. Head over to the documentation to learn more!
With Herd v1.11, you can share project configuration with your
team using a Herd.yml
file in the root of your
project. You can configure the project name, domain aliases, PHP
version, and SSL certificates.
You set up the Herd.yml
using the herd
init
command. If your project doesn't have the file, the
init
command prompts you through the setup process.
Pro users can also define services in the Herd.yml
file.
When a new developer clones your project, running herd
init
will get them up and running immediately, and all
developers will have the same setup. Projects can configure the
Forge server and site IDs to share site configurations with all
developers.
Check out the Herd documentation to learn all about Sharing project configurations.
The Herd v1.11 update is available immediately on macOS, with the Windows release happening soon.
Herd v1.11 has a new profiler for identifying performance issues in your code. Herd makes profile requests, CLI scripts, and long-running tasks seamless.
Here's an example of profiling Artisan commands via the Herd CLI:
herd profile artisan my-command
Herd's dump debugging features a new custom PHP extension that
makes using dd()
and dump()
automatic.
You can also configure Herd to dump queries, HTTP requests, views,
jobs, and logs.
You can learn more about Herd's features in the official documentation.
The post Laravel Herd Adds Forge Integration, Dump Updates, and More in v1.11 appeared first on Laravel News.
Join the Laravel Newsletter to get all the latest Laravel articles like this directly in your inbox.
Read more https://laravel-news.com/laravel-herd-1-11-0
Collaboration can be a powerful catalyst for growth. Ben Holman, a passionate advocate of pair programming, has taken this idea to the next level with his new project, The Pair-amid Scheme. The initiative is designed to connect programmers with strangers, creating opportunities to work together on coding projects in a collaborative and meaningful way.
Preview audio? You can listen in your podcast app of choice:
<iframe width="100%" height="180" frameborder="no" scrolling="no" seamless="" src="https://share.transistor.fm/e/c3bc0cc4"></iframe>View our YouTube playlist to check out all the other creator spotlight interviews.
The post Ben Holmen: Building Connections and Friendships through Pair Programming with Strangers appeared first on Laravel News.
Join the Laravel Newsletter to get all the latest Laravel articles like this directly in your inbox.
Read more https://laravel-news.com/pair-amid-scheme
The Laravel team released v11.23 this week, with the Laracon US
2024 open-source updates like defer()
, concurrency,
contextual container attritubes, and more.
Taylor Otwell contributed all of the goodies he shared
in his Laracon US 2024 keynote, including
chaperone()
, defer()
,
Cache::flexible()
, contextual container attributes,
and more.
The documentation is being updated; here are a few highlights you should check out to get familiar with these updates:
chaperone()
)See Pull Request #52710 for full details on everything added related to Taylor's .
Cam Kemshal-Bell added min and max ratio to the
dimensions
validation rule:
You can use these methods fluently, using
minRatio()
, maxRatio()
, and
ratioBetween()
:
use Illuminate\Validation\Rule;
//
// Using minRatio and maxRatio fluent methods
//
Rule::dimensions()
->minRatio(1 / 2)
->maxRatio(1 / 3);
// dimensions:min_ratio=0.5,max_ratio=0.33333333333333
//
// Equivalent using ratioBetween()
//
Rule::dimensions()->ratioBetween(min: 1 / 2, max: 1 / 3);
// dimensions:min_ratio=0.5,max_ratio=0.33333333333333
You can also use the string style dimensions
rule
with this update as well:
use Illuminate\Support\Facades\Validator;
Validator::make($request->all(), [
'min_12' => 'dimensions:min_ratio=1/2',
'square' => 'dimensions:ratio=1',
'max_25' => 'dimensions:max_ratio=2/5',
'min_max' => 'dimensions:min_ratio=1/4,max_ratio=2/5',
]);
Diaa Fares contributed two pull requests that continue
to add backed enum support. This release includes updates to the
Gate
methods and Authorize
middleware.
Here are some examples of using Enums with Gate
methods:
enum Abilities: string {
case VIEW_DASHBOARD = 'view-dashboard';
case EDIT = 'edit';
case UPDATE = 'update';
}
// Before
Gate::define('view-dashboard', function (User $user) {
return $user->isAdmin;
});
Gate::authorize('view-dashboard');
Gate::inspect('view-dashboard');
Gate::check('view-dashboard');
Gate::any(['edit', 'update], $post);
Gate::none(['edit', 'update]], $post);
Gate::allows('update', $post);
Gate::denies('update', $post);
// After
Gate::define(Abilities::VIEW_DASHBOARD, function (User $user) {
return $user->isAdmin;
});
Gate::authorize(Abilities::VIEW_DASHBOARD);
Gate::inspect(Abilities::VIEW_DASHBOARD);
Gate::check(Abilities::VIEW_DASHBOARD);
Gate::any([Abilities::EDIT, Abilities::UPDATE], $post);
Gate::none([Abilities::EDIT, Abilities::UPDATE], $post);
Gate::allows(Abilities::UPDATE, $post);
Gate::denies(Abilities::UPDATE, $post);
Here's an example of the Authorize
middleware's
support for backed enums:
Route::get('/dashboard', [AdminDashboardController::class, 'index'])
->middleware(
Authorize::using(Abilities::VIEW_DASHBOARD)
)
->name(AdminRoutes::DASHBOARD);
Kennedy Tedesco contributed a Skip middleware
to skip a job based on a condition. This middleware has three
static constructor methods you can use, including
when()
, unless()
. The job is skipped
based on the result of the condition used:
class MyJob implements ShouldQueue
{
use Queueable;
public function handle(): void
{
// TODO
}
public function middleware(): array
{
return [
Skip::when($someCondition), // Skip when `true`
Skip::unless($someCondition), // Skip when `false`
Skip::when(function(): bool {
if ($someCondition) {
return true;
}
return false;
}),
];
}
}
findOrFail()
MethodSteve Bauman contributed a findOrFail()
method on Eloquent collections that adds a way to find a model on
an already populated collection:
$users = User::get(); // [User(id: 1), User(id: 2)]
$users->findOrFail(1); // User
$user->findOrFail([]); // []
$user->findOrFail([1, 2]); // [User, User]
$user->findOrFail(3); // ModelNotFoundException: 'No query results for model [User] 3'
$user->findOrFail([1, 2, 3]); // ModelNotFoundException: 'No query results for model [User] 3'
You can see the complete list of new features and updates below and the diff between 11.22.0 and 11.23.0 on GitHub. The following release notes are directly from the changelog:
everyThirtyMinutes
cron expression by
@SamuelNitsche in https://github.com/laravel/framework/pull/52662Skip
middleware for Queue Jobs by
@KennedyTedesco in https://github.com/laravel/framework/pull/52645withoutDelay()
to PendingDispatch by
@KennedyTedesco in https://github.com/laravel/framework/pull/52696Container::getInstance()
to use
null coalescing assignment by @xurshudyan in
https://github.com/laravel/framework/pull/52693Eloquent\Collection::findOrFail
by
@stevebauman in https://github.com/laravel/framework/pull/52690confirmed
validator rule by @jwpage in https://github.com/laravel/framework/pull/52722$guards
from array to string by @kayw-geek
in https://github.com/laravel/framework/pull/52719Tag
attribute by @TijmenWierenga in https://github.com/laravel/framework/pull/52743fromUrl()
to Attachment by @KennedyTedesco in https://github.com/laravel/framework/pull/52688The post Chaperone, Defer, Cache::flexible, and more are now available in Laravel 11.23 appeared first on Laravel News.
Join the Laravel Newsletter to get all the latest Laravel articles like this directly in your inbox.
Read more https://laravel-news.com/laravel-11-23-0
Over the past couple of months we’ve been working away at a new SaaS marketing site template for Tailwind UI. It’s called Radiant, and you can start using it today.
We just wrapped up work on a beautiful new SaaS marketing site template called Radiant, and it’s available now as part of Tailwind UI.
It’s built with Next.js, Framer Motion, and Tailwind CSS, with a blog powered by Sanity.
It’s been a while since we built a SaaS marketing template like this, and in that time we’ve learned a lot about what makes a template like this useful and easy to work with. We’ve tried to incorporate all of those learnings into Radiant.
Check out the live preview as always for the full experience — there are tons of cool details in this one that you have to see in the browser to really appreciate.
It’s super easy to overdo animation on a site like this. We’ve all seen sites where you can’t even scroll a few pixels without a bunch of different elements animating in to place. Even worse is how slow things feel when you have to wait for the content to appear before you can read it.
Radiant is loaded with delightful animations, but they are all layered on to existing content and triggered by user interaction so the site still feels fast. In most cases, we went for animations that loop to make elements feel “alive” while you’re interacting with them.
We used Framer Motion for almost all of the animations. It’s declarative, making it easy to create our own APIs for complex animations that other people can customize without much effort.
It does have some drawbacks to work around though. For example, when you have multiple elements animating independently it’s annoying to pass a hover state down to each child. We ended up leveraging Framer’s variant propagation to make this work — a hover event triggers a variant change in the parent that propagates down to the children because they share the same variant keys.
export function BentoCard() {
return (
<motion.div
initial="idle"
whileHover="active"
variants={{ idle: {}, active: {} }}
data-dark={dark ? 'true' : undefined}
>
/* ... */
</motion.div>
)
}
There is no difference between the variants in the parent so it doesn’t actually change but the children still get a signal to change variants on hover, even if they are deeply nested.
function Marker({
src,
top,
offset,
delay,
}: {
src: string
top: number
offset: number
delay: number
}) {
return (
<motion.div
variants={{
idle: { scale: 0, opacity: 0, rotateX: 0, rotate: 0, y: 0 },
active: { y: [-20, 0, 4, 0], scale: [0.75, 1], opacity: [0, 1] },
}}
transition={{ duration: 0.25, delay, ease: 'easeOut' }}
style={{ '--offset': `${offset}px`, top } as React.CSSProperties}
className="absolute left-[calc(50%+var(--offset))] size-[38px] drop-shadow-[0_3px_1px_rgba(0,0,0,.15)]"
>
/* ... */
</motion.div>
)
}
/* ... */
The logo timeline animation is a bit different, because we wanted the logos to pause in their current position when you stop hovering, rather than return to their original position. This doesn’t play very well with Framer’s approach of specifying start and end states, so it was actually easier to build this in CSS.
It exploits the fact that you can set a negative
animation-delay
value to offset the start position of
the element. That way all the logos share the same animation
keyframes but they can start at different positions and have
different durations.
function Logo({
label,
src,
className,
}: {
label: string
src: string
className: string
}) {
return (
<div
className={clsx(
className,
'absolute top-2 grid grid-cols-[1rem,1fr] items-center gap-2 whitespace-nowrap px-3 py-1',
'rounded-full bg-gradient-to-t from-gray-800 from-50% to-gray-700 ring-1 ring-inset ring-white/10',
'[--move-x-from:-100%] [--move-x-to:calc(100%+100cqw)] [animation-iteration-count:infinite] [animation-name:move-x] [animation-play-state:paused] [animation-timing-function:linear] group-hover:[animation-play-state:running]',
)}
>
<img alt="" src={src} className="size-4" />
<span className="text-sm/6 font-medium text-white">{label}</span>
</div>
)
}
export function LogoTimeline() {
return (
/*...*/
<Row>
<Logo
label="Loom"
src="./logo-timeline/loom.svg"
className="[animation-delay:-26s] [animation-duration:30s]"
/>
<Logo
label="Gmail"
src="./logo-timeline/gmail.svg"
className="[animation-delay:-8s] [animation-duration:30s]"
/>
</Row>
/*...*/
This approach means we don’t need to track the play state in
JavaScript, we can just use a
group-hover:[animation-play-state:running]
class to
start the animation when the parent is hovered.
As you’ve maybe noticed, we’re using a bunch of arbitrary
properties for individual animation
properties in this
component, since these utilities don’t exist in Tailwind today.
This is what’s great about building these templates — it helps us
find blind spots in Tailwind CSS. Who knows, maybe we’ll see these
utilities added for v4.0!
The trickiest part of designing a SaaS template like this, is coming up with interactive elements that people can apply to their own product without too much effort. There’s nothing worse than buying a template and realizing that it’s so specific to the example content that you can’t actually use it for your own project.
We came up with some core graphical elements that most SaaS products might have. A map with pins, a logo cluster, a keyboard — things that could be applied to a bunch of different features. Because we wanted them to be easy to repurpose for your own product, we built a lot of them in code and designed nice APIs for them.
The logo cluster, for example, has a simple API that lets you pass in your own logos, tweak their position and hover animation to match.
<Logo
src="./logo-cluster/dribbble.svg"
left={285}
top={20}
hover={{ x: 4, y: -5, rotate: 6, delay: 0.3 }}
/>
The keyboard shortcuts section is another good example. Adding your own shortcuts is as simple as passing an array of key names to the Keyboard component and because each key is a component, you can easily add custom keys or change the layout.
<Keyboard highlighted={['F', 'M', 'L']} />
It turns out it’s actually quite a lot of work to build a keyboard in code, but at least now you’ll never have to find that out for yourself.
Of course, we also left spots for you to drop in screenshots of your own product. Here’s what this section looks like customized to suit our friends at SavvyCal, using the same interactive components.
Usually we just use MDX when adding a blog to a template, but this time we thought it would be fun to play with a headless CMS for a chance instead. We decided to give Sanity a go for this one after polling our audience and hearing a lot of good things.
Instead of creating files, making commits, and managing images and stuff by hand, a CMS lets you handle everything from their UI, so even non-developers can easily contribute.
One cool thing about headless CMSes like Sanity is you get your content back in a structured format, so similar to MDX you can map elements to your own custom components to handle all of your typography styles.
<PortableText
value={post.body}
components={{
block: {
normal: ({ children }) => (
<p className="my-10 text-base/8 first:mt-0 last:mb-0">
{children}
</p>
),
h2: ({ children }) => (
<h2 className="mb-10 mt-12 text-2xl/8 font-medium tracking-tight text-gray-950 first:mt-0 last:mb-0">
{children}
</h2>
),
h3: ({ children }) => (
<h3 className="mb-10 mt-12 text-xl/8 font-medium tracking-tight text-gray-950 first:mt-0 last:mb-0">
{children}
</h3>
),
blockquote: ({ children }) => (
<blockquote className="my-10 border-l-2 border-l-gray-300 pl-6 text-base/8 text-gray-950 first:mt-0 last:mb-0">
{children}
</blockquote>
),
},
types: {
image: ({ value }) => (
<img
className="w-full rounded-2xl"
src={image(value).width(2000).url()}
alt={value.alt || ''}
/>
),
},
/* ... */
}}
/>
Working with a CMS also means all of your assets like images are hosted for you, and you can control the size, quality, and format of the image on the fly.
<div className="text-sm/5 max-sm:text-gray-700 sm:font-medium">
{dayjs(post.publishedAt).format('dddd, MMMM D, YYYY')}
</div>
{post.author && (
<div className="mt-2.5 flex items-center gap-3">
{post.author.image && (
<img
className="aspect-square size-6 rounded-full object-cover"
src={image(post.author.image).width(64).height(64).url()}
alt=""
/>
)}
<div className="text-sm/5 text-gray-700">
{post.author.name}
</div>
</div>
)}
Like you might do with front matter in Markdown, you can also
enrich content with custom fields. For example, we added a
featured
boolean field to the blog post schema so you
can highlight some posts in a special section on the blog.
Sanity in particular is a paid product, but they have a pretty generous free tier which is more than enough to play around. And if you wanted to try out a different headless CMS, I think the Sanity integration we’ve put together here will still serve as a great informative example of how you might approach wiring things up with another tool.
And that’s Radiant! Have a look under the hood, kick the tires, and let us know what you think.
Like all of our templates, it’s included with a one-time purchase Tailwind UI all-access license, which is the best way to support our work on Tailwind CSS and make it possible for us to keep building awesome stuff for you for years to come.
(The post Radiant: A beautiful new marketing site template appeared first on Tailwind CSS Blog.)
Read more https://tailwindcss.com/blog/2024-09-12-radiant-a-beautiful-new-marketing-site-template
Page 1 of 1347