Sr. Content Developer at Microsoft, working remotely in PA, TechBash conference organizer, former Microsoft MVP, Husband, Dad and Geek.
152066 stories
·
33 followers

Why WordPress Emails Go to Spam (And How to Fix It)

1 Share

If your WordPress site sends order confirmations, password resets, or contact form notifications, but those messages end up in spam folders, it’s almost like they were never sent at all. Transactional emails are vital for communications. When they go missing, customers get frustrated and you miss important inquiries or tasks. 

You’re far from the only person to experience this kind of issue. So, how do you fix it?

First, determine why it’s happening. Then you can then implement measures like updating your content or using an SMTP plugin or a reputable form builder like Jetpack Forms. These tools improve deliverability for emails originating from your site. 

In this post, we’ll take a look at the reasons WordPress emails go to spam. We’ll then show you how to resolve this issue and make sure it doesn’t happen again. Let’s dive right in!

Why WordPress emails get marked as spam

There are different culprits behind WordPress emails going to spam. Understanding the root causes will help you identify the problem and take the necessary steps to fix it. 

Here’s what might be happening and what you can do:

Server reputation issues

Shared hosting increases the likelihood that your emails will be marked as spam.

Websites on shared servers have the same IP address. If one website on the server sends spam or experiences delivery issues, email providers may flag that IP. As a result, your legitimate WordPress emails might get caught in spam filters, too. 

Some hosting providers maintain reputable IP addresses, but if you notice repeated spam issues, you might want to check if your server’s IP is on a blocklist. You can use a tool like MXToolbox for this. 

Missing authentication

Email providers use authentication protocols to verify that an email is coming from your domain (and not a malicious source). There are three main records: 

  • SPF (Sender Policy Framework): It identifies which servers are allowed to send emails on your domain’s behalf.
  • DKIM (DomainKeys Identified Mail): This adds a cryptographic signature to your emails to confirm that the message hasn’t been intercepted.
  • DMARC (Domain-based Message Authentication, Reporting & Conformance): This tells email providers how to handle unauthenticated messages.

Without these records in place, your emails may appear suspicious, and providers like Gmail or Outlook will therefore mark them as spam.

Spoofing detection

Spoofing is when the “from” address on an email doesn’t match the server sending it. For example, if your WordPress contact form uses info@yourdomain.com but the server isn’t authorized via SPF/DKIM, email clients like Gmail may flag the email as potential fraud.

This is common when using the default WordPress PHP mail functions. Many hosting servers are not configured to send authenticated emails, which consequently triggers spoofing alerts.

Content triggers

Many spam filters analyze the content of emails. Certain keywords and formatting styles can trigger spam detection.

These include excessive capitalization or exclamation points, too many links, and overuse of promotional or “sensitive” words.

If the nature of your site covers sensitive topics, your email’s use of certain words, while acceptable to your audience, might trigger spam filters. In this case, you’ll need to find new phrases or workarounds. 

Your messages can be flagged if their content contains spam-like patterns.

Volume concerns

Sending a high volume of emails in a short period is another red flag for spam detectors. Many email providers track sending patterns, and a sudden surge of emails from the same source, even if legitimate, might result in the sender being flagged as spam.

This is particularly true for ecommerce sites that send order confirmations and other transactional messages daily. If you regularly hit email limits on your shared hosting plan, consider solutions that improve deliverability.

How to fix WordPress emails going to spam

Now, let’s look at how to stop your WordPress emails from going to spam. Let’s explore several different solutions.

 1. Install and configure an SMTP plugin

The default PHP mail function in WordPress may not give you the best email deliverability. An SMTP (Simple Mail Transfer Protocol) plugin ensures that your emails are sent via authenticated servers. This means that they’re less likely to be marked as spam. 

There are different plugins you can use, one of the best options being MailPoet. This transactional email service comes with an SMTP solution built in. It boasts a near 99 percent global delivery rate and the SMTP is very easy to activate. 

Here’s how to quickly set up SMTP with MailPoet. Navigate to Plugins → Add Plugin and use the search bar to find the tool.

installing the MailPoet plugin

Click on Install Now and Activate, and you’ll be directed to the setup page.

setting up a MailPoet account

MailPoet will ask you to connect to your account. You can create a MailPoet account for free.

connecting MailPoet to a WordPress site

Once you’ve connected to your account, go to MailPoet → Settings in your WordPress dashboard and select the Send With tab.

turning on the MailPoet sending service

Here, make sure that MailPoet Sending Service is selected. That’s it: Your emails are now delivered through MailPoet’s SMTP service. 

2. Use a reliable form plugin to enhance deliverability

A reliable form plugin like Jetpack Forms can improve deliverability. Built by Automattic, the people behind WordPress.com, Jetpack Forms integrates seamlessly with your WordPress site and works well with SMTP plugins, ensuring messages are sent securely.

The plugin is available for free. Go to your WordPress dashboard and click on Plugins → Add Plugin. Look for “Jetpack – WP Security, Backup, Speed, & Growth” in the search bar.

adding the Jetpack plugin in WordPress

Select Install Now and Activate, then connect to your WordPress.com account or create one for free.

You can now open any page or post to add a form. Click on the plus icon (+) to add a new block and select Form. Jetpack offers pre-made templates, including registration forms, contact form, and more.

choosing a form type with Jetpack

You can then customize these forms by adding, removing, and editing fields. 

3. Make sure your form plugin has anti-spam protection

Even if your emails reach inboxes, spam submissions from bots can trigger filters that block your messages. Jetpack Forms integrates with Akismet, which automatically blocks spammy form submissions. 

This not only protects your inbox, but also helps you maintain a positive sender reputation.

Akismet has a 99.99 percent spam detection accuracy. It also runs spam checks in the background, so it doesn’t interfere with the user experience of real visitors. 

4. Authenticate your domain (SPF, DKIM, DMARC)

As mentioned earlier, there are DNS records that authenticate your emails and make sure that they arrive in your customers’ inboxes. Most hosting providers allow you to add DNS records for SPF, DKIM, and DMARC.

If you bought your domain through a registrar, you’ll need to manage these records from that account.

When you set up these records, email providers can verify that your domain is legitimate. Therefore, your messages are less likely to be marked as spoofed.

Some providers have reporting tools that let you check whether unauthorized emails are being sent from your domain.

The process for adding these records will vary depending on your provider, so refer to their documentation for step-by-step instructions.

5. Check your email content

Spam filters also analyze what’s inside an email. So even if your WordPress emails are sent from a reputable server with proper authentication, they can still end up in spam if the content raises red flags. Here are some common things that trigger spam filters:

  • Overuse of spammy keywords: Phrases like “Act Now,” “Cure,” “Medication,” “Get Rich Quick,” “Earn $$$,” or “No Credit Check” are often associated with unsolicited marketing emails.
  • Excessive punctuation and capitalization: Subject lines like “BUY NOW!!!” or emails full of ALL CAPS can make your message look aggressive or promotional.
  • Too many links: If your email contains more links than text, it may appear suspicious.
  • Unnecessary attachments: Many email clients block or filter messages with unexpected attachments, especially large uncompressed files.
  • Unclear sender information: If your email says it’s from “Admin” or “No-reply,” recipients may distrust it.

So, make sure to keep formatting clean and simple. A well-structured email with short paragraphs and clear fonts looks more trustworthy.

Also, personalize the message when possible, as this signals authenticity. Include the recipient’s name or order details.

You’ll also want to use a clear subject line. Instead of vague titles like “Important Information”, go for something more specific like “Order Confirmation #12345” or “Message from YourWebsite Contact Form.”

You can use tools like Mail Tester or GlockApps to check whether your email content is likely to trigger spam filters. Sending test emails to accounts on different platforms (like Gmail and Outlook) is also a good way to see how your content performs.

6. Monitor email volume

Many WordPress sites on shared hosting have built-in sending limits (e.g. 100–500 emails per hour). Exceeding these limits can cause emails to be flagged.

Plus, a sudden spike in email activity may look like spam behavior to ISPs. If your IP address is associated with bulk mailing without proper controls, it could get listed on spam blocklists.

If you need to send a large batch of emails, avoid delivering them all at once. Many SMTP plugins and email services allow you to schedule or queue emails. 

You may also want to consider a dedicated email service provider like Mailgun, SendGrid, or Amazon SES. These services are designed for high-volume sending.

How to ensure this doesn’t happen again

Now that you know how to stop WordPress emails from going to spam, here’s how to prevent this problem in the future.

Regularly test your contact forms

Try to send test submissions weekly (or after major updates). Simply fill out your contact form with a test message and confirm delivery in your inbox. It’s also a good idea to check across multiple email providers.

If your form has attachments, dropdowns, or custom fields, test them all.

Regular testing ensures that your most basic communication channel stays reliable. Plus, you’ll catch issues before customers do.

Regularly test your WordPress and WooCommerce emails

Beyond contact forms, WordPress also sends a variety of automated emails, like password resets, order confirmations, invoices, and shipping updates. If these don’t reach customers, it can damage trust and lead to lost revenue.

So, test WooCommerce transactional emails by placing small test orders. You’ll also want to track bounce rates if you send bulk notifications. High bounces indicate an authentication issue. Depending on the email service you use, you should be able to track metrics like open and click-through rates. 

Periodically review your DNS and SMTP settings

DNS and SMTP settings are essential for email deliverability, and small changes in hosting, domain providers, or plugins can cause disruptions.

For example, you might move to a new registrar or your host resets DNS records. Switching servers or upgrading plans may also change your IP address.

Therefore, check DNS records quarterly, using tools like MXToolbox to confirm your SPF, DKIM, and DMARC are intact.

It’s also important to review SMTP plugin settings and make sure that authentication credentials (like API keys or app passwords) haven’t expired.

Keep plugins and WordPress updated

Finally, you’ll want to keep WordPress core, plugins, and themes up to date. Outdated software can introduce bugs, conflicts, or vulnerabilities that impact email deliverability. 

For example, new versions of Gmail, Microsoft, or third-party mail APIs may require updated authentication methods. Additionally, hackers often exploit outdated plugins to send spam, which can damage your domain’s reputation.

You can enable automatic updates or update plugins manually when new versions are available. If you opt for the latter, make sure to check your website for plugins at least once a week. 

It’s a good idea to run a contact form submission or a WooCommerce test order after updates to confirm that everything is working as it should. 

Level up your contact forms with built-in spam protection

Choosing a plugin like Jetpack Forms adds another layer of security. Its integration with Akismet stops spam before it hits your inbox. Akismet uses AI and machine learning to block spammy content through forms. It does all this work in the background, without affecting your forms or the user experience of your customers. 

With Jetpack Forms, you’ll also have access to the AI Assistant. This feature helps you build forms more easily. Simply enter a prompt, like “create a dropdown field with a list of countries,” and the AI Assistant will create it for you.

Are you ready to boost email deliverability and security? Get started with Jetpack Forms today!





Read the whole story
alvinashcraft
29 minutes ago
reply
Pennsylvania, USA
Share this story
Delete

Microsoft wants to let you share app windows with Copilot right from the Windows 11 taskbar

1 Share

If you hover over apps on the Windows 11 taskbar, you can now share your app’s window with Copilot and start asking questions, such as how to reply to an email if you are in Outlook. As silly as that might sound, this is the whole point of Copilot Vision.

I spotted the “Share with Copilot” feature on my Intel Lunar Lake Copilot+ PC, but it’s rolling out to everyone, and does not require one of these “AI” PCs. This means, if you have non-AI PCs, including AMD or Intel, you are still going to see “Share with Copilot” on your taskbar, and that makes sense (more on that later).

“Share with Copilot” is rolling out with Windows 11 KB5072033 (Build 26200.7462 / 26100.7462 or newer), and it’s turned on by default, but I found a way to turn it off if you hate the idea (and you should).

How does “Share with Copilot” on the taskbar work?

In our tests, Windows Latest observed that “Share with Copilot” shows up when I hover over open apps on the taskbar. And it literally shows up for any app window, including Cloudflare WARP, which is a VPN-like service. I also spotted the toggle for Netflix, which has DRM-protected content, so it does not work correctly.

Share with Copilot for taskbar

When you share any app window, Copilot uses cloud-based AI to analyze the content of the app and provide insights. For example, I opened an Outlook email in the background and shared the window with Copilot. Copilot started reading my email, which was already open, but it was unable to browse other emails, move around, or click anywhere.

Copilot share screen mode on Windows 11

That’s because Copilot Vision is a “read-only” and “dictate-only” feature, which means Copilot can only see what you can see, and it can offer “assistance.”

For example, I asked Copilot how to respond to the email, and it told me to look for a “Send” button that doesn’t even exist. At that point, Copilot was hallucinating. Then, I specifically asked it to show me how and where to click. This time, Copilot Vision worked as I expected.

Copilot tells me to send me email

Copilot activated its own “cursor”, which showed up on the screen, and then it highlighted where I needed to click. Thankfully, Copilot correctly analyzed my screen and told me to use the ‘reply’ button, not ‘send,’ which does not exist on the screen, but was recommended last time.

Next, I asked Copilot how to delete the email, and it again highlighted the correct option.

Copilot offering hands on assistance on Windows 11

Microsoft calls it “guided assistance,” and one support document confirms that Copilot Vision is supposed to help you, but it won’t work for DRM-protected or sensitive content.

How is Microsoft adding “Share with Copilot” to all app windows on the taskbar?

Windows Latest found that Microsoft is using a Windows API called ” Windows.UI.Shell.ShareWindowCommandSource.”

According to a support document, this API allows a communication app to plug into Windows 11’s Shell (like the taskbar or share UI) so Windows can show Start sharing / Stop sharing commands and pass the app the exact WindowId the user picked.

The API is supposed to be used by apps like Teams, but Microsoft is going out of its way to use it for Copilot. It’s not an open API that developers can use. And the biggest catch is that not everyone can use the API, as it’s marked as a “Limited Access Feature.”

When an API is marked as “Limited Access Feature,” it means Microsoft has to approve you and give developers an unlock token before they can use it in a real product.

Share with Copilot button on the taskbar for Windows 11

In other words, if OpenAI wants to replicate the same behaviour, it needs to reach out to Microsoft and wait for the approval. On the other hand, Microsoft can use its “limited access” APIs, which were designed for communication apps like Teams, for its own AI assistance.

That’s why we see only Copilot using it, as Microsoft can grant itself (or selected partners) access, and Copilot can then register during a session as a “sharing command source.”

Can I disable “Share with Copilot” on the Windows 11 taskbar?’

Yes, you can disable “Share with Copilot” on the Windows 11 taskbar when it shows up on your PC.

If you go to Settings > Personalization > Taskbar and expand “Taskbar behavior,” you’ll find a new toggle “Share any window from my taskbar with.” It has options like Communication apps, such as Teams, Zoom (if approved by Microsoft),etc. And it also has a new “Chat agent apps” toggle.

You can either choose “communication apps” or “none” to block the taskbar from showing the “Share with Copilot” option.

Windows 11 taskbar Copilot sharing screen

In most cases, this option will be set to “All apps” by default, and that explains why “Share with Copilot” popped up out of nowhere on my PC.

Windows release note

In the official release notes (screenshotted above), Microsoft confirmed that users will now see an “option to share its window with Copilot” after the update, but it also noted that the feature is rolling out gradually.

The post Microsoft wants to let you share app windows with Copilot right from the Windows 11 taskbar appeared first on Windows Latest

Read the whole story
alvinashcraft
6 hours ago
reply
Pennsylvania, USA
Share this story
Delete

Kubernetes v1.35: New level of efficiency with in-place Pod restart

1 Share

The release of Kubernetes 1.35 introduces a powerful new feature that provides a much-requested capability: the ability to trigger a full, in-place restart of the Pod. This feature, Restart All Containers (alpha in 1.35), allows for an efficient way to reset a Pod's state compared to resource-intensive approach of deleting and recreating the entire Pod. This feature is especially useful for AI/ML workloads allowing application developers to concentrate on their core training logic while offloading complex failure-handling and recovery mechanisms to sidecars and declarative Kubernetes configuration. With RestartAllContainers and other planned enhancements, Kubernetes continues to add building blocks for creating the most flexible, robust, and efficient platforms for AI/ML workloads.

This new functionality is available by enabling the RestartAllContainersOnContainerExits feature gate. This alpha feature extends the Container Restart Rules feature, which graduated to beta in Kubernetes 1.35.

The problem: when a single container restart isn't enough and recreating pods is too costly

Kubernetes has long supported restart policies at the Pod level (restartPolicy) and, more recently, at the individual container level. These policies are great for handling crashes in a single, isolated process. However, many modern applications have more complex inter-container dependencies. For instance:

  • An init container prepares the environment by mounting a volume or generating a configuration file. If the main application container corrupts this environment, simply restarting that one container is not enough. The entire initialization process needs to run again.
  • A watcher sidecar monitors system health. If it detects an unrecoverable but retriable error state, it must trigger a restart of the main application container from a clean slate.
  • A sidecar that manages a remote resource fails. Even if the sidecar restarts on its own, the main container may be stuck trying to access an outdated or broken connection.

In all these cases, the desired action is not to restart a single container, but all of them. Previously, the only way to achieve this was to delete the Pod and have a controller (like a Job or ReplicaSet) create a new one. This process is slow and expensive, involving the scheduler, node resource allocation and re-initialization of networking and storage.

This inefficiency becomes even worse when handling large-scale AI/ML workloads (>= 1,000 Nodes with one Pod per Node). A common requirement for these synchronous workloads is that when a failure occurs (such as a Node crash), all Pods in the fleet must be recreated to reset the state before training can resume, even if all the other Pods were not directly affected by the failure. Deleting, creating and scheduling thousands of Pods simultaneously creates a massive bottleneck. The estimated overhead of this failure could cost $100,000 per month in wasted resources.

Handling these failures for AI/ML training jobs requires a complex integration touching both the training framework and Kubernetes, which are often fragile and toilsome. This feature introduces a Kubernetes-native solution, improving system robustness and allowing application developers to concentrate on their core training logic.

Another major benefit of restarting Pods in place is that keeping Pods on their assigned Nodes allows for further optimizations. For example, one can implement node-level caching tied to a specific Pod identity, something that is impossible when Pods are unnecessarily being recreated on different Nodes.

Introducing the RestartAllContainers action

To address this, Kubernetes v1.35 adds a new action to the container restart rules: RestartAllContainers. When a container exits in a way that matches a rule with this action, the kubelet initiates a fast, in-place restart of the Pod.

This in-place restart is highly efficient because it preserves the Pod's most important resources:

  • The Pod's UID, IP address and network namespace.
  • The Pod's sandbox and any attached devices.
  • All volumes, including emptyDir and mounted volumes from PVCs.

After terminating all running containers, the Pod's startup sequence is re-executed from the very beginning. This means all init containers are run again in order, followed by the sidecar and regular containers, ensuring a completely fresh start in a known-good environment. With the exception of ephemeral containers (which are terminated), all other containers—including those that previously succeeded or failed—will be restarted, regardless of their individual restart policies.

Use cases

1. Efficient restarts for ML/Batch jobs

For ML training jobs, rescheduling a worker Pod on failure is a costly operation that wastes valuable compute resources. On a 1,000-node training cluster, rescheduling overhead can waste over $100,000 in compute resources monthly.

With RestartAllContainers actions you can address this by enabling a much faster, hybrid recovery strategy: recreate only the "bad" Pods (e.g., those on unhealthy Nodes) while triggering RestartAllContainers for the remaining healthy Pods. Benchmarks show this reduces the recovery overhead from minutes to a few seconds.

With in-place restarts, a watcher sidecar can monitor the main training process. If it encounters a specific, retriable error, the watcher can exit with a designated code to trigger a fast reset of the worker Pod, allowing it to restart from the last checkpoint without involving the Job controller. This capability is now natively supported by Kubernetes.

Read more details about future development and JobSet features at KEP-467 JobSet in-place restart.

apiVersion: v1
kind: Pod
metadata:
 name: ml-worker-pod
spec:
 restartPolicy: Never
 initContainers:
 # This init container will re-run on every in-place restart
 - name: setup-environment
 image: my-repo/setup-worker:1.0
 - name: watcher-sidecar
 image: my-repo/watcher:1.0
 restartPolicy: Always
 restartPolicyRules:
 - action: RestartAllContainers
 onExit:
 exitCodes:
 operator: In
 # A specific exit code from the watcher triggers a full pod restart
 values: [88]
 containers:
 - name: main-application
 image: my-repo/training-app:1.0

2. Re-running init containers for a clean state

Imagine a scenario where an init container is responsible for fetching credentials or setting up a shared volume. If the main application fails in a way that corrupts this shared state, you need the init container to rerun.

By configuring the main application to exit with a specific code upon detecting such a corruption, you can trigger the RestartAllContainers action, guaranteeing that the init container provides a clean setup before the application restarts.

3. Handling high rate of similar tasks execution

There are cases when tasks are best represented as a Pod execution. And each task requires a clean execution. The task may be a game session backend or some queue item processing. If the rate of tasks is high, running the whole cycle of Pod creation, scheduling and initialization is simply too expensive, especially when tasks can be short. The ability to restart all containers from scratch enables a Kubernetes-native way to handle this scenario without custom solutions or frameworks.

How to use it

To try this feature, you must enable the RestartAllContainersOnContainerExits feature gate on your Kubernetes cluster components (API server and kubelet) running Kubernetes v1.35+. This alpha feature extends the ContainerRestartRules feature, which graduated to beta in v1.35 and is enabled by default.

Once enabled, you can add restartPolicyRules to any container (init, sidecar, or regular) and use the RestartAllContainers action.

The feature is designed to be easily usable on existing apps. However, if an application does not follow some best practices, it may cause issues for the application or for observability tooling. When enabling the feature, make sure that all containers are reentrant and that external tooling is prepared for init containers to re-run. Also, when restarting all containers, the kubelet does not run preStop hooks. This means containers must be designed to handle abrupt termination without relying on preStop hooks for graceful shutdown.

Observing the restart

To make this process observable, a new Pod condition, AllContainersRestarting, is added to the Pod's status. When a restart is triggered, this condition becomes True and it reverts to False once all containers have terminated and the Pod is ready to start its lifecycle anew. This provides a clear signal to users and other cluster components about the Pod's state.

All containers restarted by this action will have their restart count incremented in the container status.

Learn more

We want your feedback!

As an alpha feature, RestartAllContainers is ready for you to experiment with and any use cases and feedback are welcome. This feature is driven by the SIG Node community. If you are interested in getting involved, sharing your thoughts, or contributing, please join us!

You can reach SIG Node through:

Read the whole story
alvinashcraft
6 hours ago
reply
Pennsylvania, USA
Share this story
Delete

An Astro site for my CSS Snippets

1 Share

As I think I've mentioned a few times already, I'm learning Astro and attempting to build random stuff with it just as an excuse to help practice and learn. With that in mind, during the Christmas break and between marathon sessions of Baldur's Gate 3, I built a little site I thought I'd share here on the blog. To be clear, this is nothing special, and doesn't come close to using all of the possible Astro features of course, but it was a useful coding exercise for myself and fun to build.

The web platform as a whole has gotten dramatically better over the past decade, and CSS improvements are a big part of that. There is a huge amount of new CSS features I'm "kinda" aware of but don't really have much experience with. One of the things I do to help me in that regard is keep notes of CSS snippets I find myself using again and again so I don't have to Google for them. I use Microsoft OneNote to track these and just write it down in quick and dirty blocks of text like so:

Center vertically in div: 
align-content: center 
 
Center iFrame: 
display:block;margin:auto 

CSS for Borders: 
fieldset {  
     border-style:solid; 
     border-width:thin; 
} 

Table CSS for borders: 
table { 
    border-collapse: collapse; 
    border: 1px solid black; 
    width: 100%; 
    max-width: 500px; 
} 

th, td { 
    border: 1px solid black; 
    padding: 5px;  
} 

Two Cols: 
.twocol { 
    display: grid; 
    grid-template-columns: 33% 66%; 
} 

There isn't any additional information here as I know what I'm typically searching for and just do a quick copy, paste, and modify to suit whatever I'm building.

I thought it might be interesting to take these tips and create a simple Astro site out of them. I'd use one Markdown source file per tip (which admittedly it perhaps overkill for some of these short snippets) and see if Astro could render the code and the output.

If you don't actually care about how I built it, you can go ahead and navigate to https://css-snippets.netlify.app/ and check it out. Here's a sample of one of the snippets:

screenshot from site

Alright, so here's how I built it.

Source Markdown

As I mentioned, I wanted my content to be driven by simple Markdown files. For this, I made use of Astro's content collections feature. First, I created a directory for my snippets called... snippets. In there I placed one Markdown file per snippet. Each file has a title, a set of tags, and the CSS snippet along with HTML to demonstrate it. Here's one for zebra striping table rows:

---
title: Zebra stripe a table
tags: ["tables"]
---

<style>
/* just to make it easier to see */
table {
    width: 500px;
}

tbody tr {
  background-color: #0a5b20;
}

tbody tr:nth-child(even) {
  background-color: #000000; 
}
</style>

<table>
    <thead>
    <tr>
        <td>Name</td>
        <td>Age</td>
    </tr>
    </thead>
    <tbody>
    <tr>
        <td>Luna</td>
        <td>13</td>
    </tr>
    <tr>
        <td>Elise</td>
        <td>15</td>
    </tr>
    <tr>
        <td>Pig</td>
        <td>10</td>
    </tr>
    <tr>
        <td>Zelda</td>
        <td>2</td>
    </tr>
    </tbody>
</table>

To let Astro know about the collection, I then added content.config.ts to the root of my src file and defined how it should find those Markdown files:

import { defineCollection } from 'astro:content';
import { glob } from 'astro/loaders';

const snippets = defineCollection({ 
    loader: glob({pattern: '*.md', base:'./snippets/'}),
});

export const collections = { snippets };

This was enough to make it available to my home page.

Rendering Snippets

First, I added a simple list to my home page. Right now this just lists everything, but I've only got a few snippets.

---
import { getCollection, getEntry } from 'astro:content';
import BaseLayout from '../layouts/BaseLayout.astro';
const allSnippets = await getCollection('snippets');
---

<BaseLayout pageTitle="Welcome">

<ul>
{allSnippets.map(snippet => (
	<li><a href=`snippets/${snippet.id}`>{snippet.data.title}</a></li>
))}
</ul>

</BaseLayout>

I won't bother sharing the layout file, but will note I made use of a nice little CSS framework, Simple.css.

Next, I added a template that would render one file per snippet. For this, I made an Astro file named src/pages/snippets/[id].astro. The [id] portion makes it dynamic. This page both handles the logic of "how do I know what routes to support" and "how do I render each one":

---
import { Code } from 'astro:components';
import { getCollection } from 'astro:content';
import BaseLayout from '../../layouts/BaseLayout.astro';

export async function getStaticPaths() {
  const snippets = await getCollection('snippets');
  return snippets.map(snippet => ({
    params: { id: snippet.id },
    props: { snippet },
  }));
}

const { snippet } = Astro.props;
---

<BaseLayout pageTitle={snippet.data.title}>

<p>
  Tags:
  {snippet.data.tags.map(tag => (
    <a href=`/tags/${tag}` class="tag">{tag} </a>
  ))}
</p>

<h3>Code</h3>

<Code code={snippet.body} lang="html" />

<h3>Output</h3>
<div set:html={snippet.body}></div>

</BaseLayout>

On top you can see where I get my collection and define the paths. I just use the Markdown's id value (which comes from the filename) and pass the content in as well. That's picked up in the template as snippet and then rendered both using Astro's native Code component for source code rendering and as raw HTML in a div.

The last part of the site is similar - handling tag pages - but the logic is a bit more complex. First, I added src/pages/tags/[id].astro. Here's how I handled the logic:

---
import { getCollection } from 'astro:content';
import BaseLayout from '../../layouts/BaseLayout.astro';
import { toTitleCase } from '../../utils/formatter.js';

export async function getStaticPaths() {
    const snippets = await getCollection('snippets');
    let tagPages = {};

    snippets.forEach((snippet) => {
        snippet.data.tags.forEach((tag) => {
            if (!tagPages[tag]) {
                tagPages[tag] = [];
            }
            tagPages[tag].push(snippet);
        });
    });

    return Object.keys(tagPages).map((tag) => ({
        params: { id: tag },
        props: { tag, pages:tagPages[tag] },
    }));
}

const { tag, pages } = Astro.props;
---

<BaseLayout pageTitle={toTitleCase(tag)}>

    <ul>
{pages.map(snippet => (
	<li><a href=`/snippets/${snippet.id}`>{snippet.data.title}</a></li>
))}
</ul>

</BaseLayout>

Basically, loop over my content, get unique tags, and create an array of pages for each tag. You can see an example of this here: https://css-snippets.netlify.app/tags/tables/

Deployment

The last step was deploying it, and here I had multiple options. I chose Netlify as I host most of my sites there. Webflow supports Astro apps as well, but they are tied to existing web sites, not really standalone. Even though my GitHub repo has a bunch of Astro crap in it, I used the Netlify CLI to connect it and set it up. Netlify supports dynamic as well as static Astro apps, and you should check their docs for more information on that, but for me this was literally about a 5 minute process at most. "It just worked" which is the best thing a dev can say about something. As I shared above, you can browse the site here, https://css-snippets.netlify.app/, and if you want to see all of the source, you can find it here: https://github.com/cfjedimaster/astro-tests/tree/main/css-snippets

As always, let me know what you think, and I've got my next little Astro site planned already! :)

Read the whole story
alvinashcraft
6 hours ago
reply
Pennsylvania, USA
Share this story
Delete

Rectangle-Pilling

1 Share

Besides “slopsquatting”, another tech term I ran into recently, this time describing a phenomenon in the AR/VR world, is “rectangle-pilling”. My colleague Tony brought this gem back from Siggraph. It identifies a tendency among designers to repeatedly recreate 2D design metaphors in spatial computing scenarios. For instance, you’ll notice that while Apple is exporting its glass visual metaphor from the AVP to its other devices (yay!) it still emphasizes windows layouts on the AVP. Originally this seemed like a good way to help users of other Apple devices quickly learn how to use the AVP, but instead of being a bridge, it seems now to be sticking around as a core element of their spatial design language. As AndroidXR rolls out, it is rolling out with Google’s “Material Design 3” design language, which is also a flat-design metaphor.
The trend is commonly known as 2D-in-3D. The term “rectangle-pilling” describes the way in which designers who believe in promoting 2D-in-3D currently dominate AR/VR companies, shoving out those who point out that instead of using old media metaphors, it would be better to explore “true” 3D design.
How did the 2D-in-3D crowd come to dominate? To answer this, it is worth pointing out that “digital design” became a big thing in the 2000s as people with artistic leanings found they could earn exciting livings as web developers. Digital design got its curriculum from print design and created a culture in which all one’s knowledge and status came from understanding how fonts, borders, and images fit onto a rectangular space — and applying the golden ratio at every step. In 2007 there was a brief movement toward isomorphic design with the rise of smartphones but this was quickly reversed and “flat design” ascended again.
Architects, on the other hand, are natural spatial designers. They think in 3D and are constantly converting 3D spaces into 2D instructions and back again.
But when AR/VR companies start hiring designers — the sorts of people who other designers feel have design chops — they go to the pool of digital design people rather than the pool of architects. And the design culture in these companies will end up reinforcing this notion that 2D-in-3D is the right way to do things.
Which leaves people who natively think in 3D feeling like they’ve just been “rectangle-pilled”.
There are, of course, good reasons to have 2D elements in spatial computing, like legibility when surfacing information. But for people who feel they’ve gotten “rectangle-pilled”, there is the sense that 2D-in-3D has become a crutch rather than a bridge to something new.
Potentially, constantly seeing 2D design elements reinforced in VR and AR makes people wonder what the point of VR and AR really is. Do I really need to read a 2D webpage in my VR headset? Can’t I just do that on my tablet?

Read the whole story
alvinashcraft
6 hours ago
reply
Pennsylvania, USA
Share this story
Delete

124: Every Electric Vehicle Coming To The US In 2026 For The First Time

1 Share
In this episode:
• We talk about every electric vehicle coming to the US in 2026 for the first time.




Download audio: https://dts.podtrac.com/redirect.mp3/audioboom.com/posts/8825764.mp3?modified=1767407053&sid=5141110&source=rss
Read the whole story
alvinashcraft
6 hours ago
reply
Pennsylvania, USA
Share this story
Delete
Next Page of Stories