Blog home

components JS FRAMEWORKS how to

How to simply integrate TwicPics into your Astro project

Learn how to easily and efficiently manage your images and short videos in your Astro.js projects.

How to simply integrate TwicPics into your Astro project

In this guide, we'll leverage React's easy integration with Astro.js to set up and use TwicPics Components.

In less than 10 minutes, you will be able to exploit all TwicPics Components' power :

  • CLS Optimization
  • Ideal Compression
  • Layout Driven
  • Lazy Loading
  • LQIP
  • Pixel Perfect
This tutorial requires using Node.js v18.14.1+ and TwicPics Components 0.25.1+.

Scaffold your new Astro Project

You can skip this part if you already have an existing project.

Setup Wizard

# create a new project with npm
npm create astro@latest

# create a new project with yarn
yarn create astro

Follow the instructions. Choose the recommended "Include sample files" option and if all goes well, you should see a "Good luck out there, astronaut! 🚀" message.

You can now cd into your new project directory.

Start Astro

# using npm
npm run dev

# using yarn
yarn dev

If all goes well, Astro should now be serving your project on http://localhost:4321/ and you should see something like this:

Lift off! We have a liftoff.
Lift off! We have a liftoff.

If you get stuck at any point, please visit the official Astro page.

Adding React to your project

You can skip this step if you have already activated React in your Astro project.

Integration Wizard

Use one of these command lines to activate React in your Astro project.

# using npm
npx astro add react

# using yarn
yarn astro add react

Answer yes (Y) to each question and Astro should automatically configure your project.

Learn more about Astro Integrations.

Testing React integration

We will create a little React component to verify that everything is working properly.

In the src/components folder, create a my-react-component.jsx file like:

// src/components/my-react-component.jsx
export const MyReactComponent = () => {
  return <div>🚀 I am a React Component 🚀</div>
}

Now, let's modify the main page of our project to include this React component.

// src/pages/index.astro
---
import Layout from '../layouts/Layout.astro';
import Card from '../components/Card.astro';
// import my-react-component
import { MyReactComponent } from '../components/my-react-component';
---

<Layout title="Welcome to Astro.">
  <main>
    <!-- ... -->
    <h1>Welcome to <span class="text-gradient">Astro</span></h1>
    <!-- Adds MyReactComponent to the template -->
    <MyReactComponent></MyReactComponent>
    <!-- ... -->
  </main>
</Layout>
<style>
  ...
</style>

If all goes well, you should see something like this:

That's one small step for a man.
That's one small step for a man.

React is now activated and working properly in your project.

If not, please refer to React Integration documentation.

Install and configure TwicPics Components

Now that React is up and running in your project, you can configure the React version of the TwicPics components.

In the following, we will use our test domain:https://demo.twic.pics
If you don't have a TwicPics domain yet, you can easily create your own for free.

Install TwicPics Components

Add the @twicpics/components package to your project:

# using npm
npm install @twicpics/components

# using yarn
yarn add @twicpics/components

Setting-up TwicPics Components

The configuration of the TwicPics components must be done at the main layout level of the application.

Modify the file src/layouts/Layout.astro as follows:

// src/layouts/Layout.astro
---
export interface Props {
  title: string;
}

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

<script>
  import "@twicpics/components/style.css";
  import { installTwicpics } from "@twicpics/components/react";
  installTwicpics( {
    domain: "https://demo.twic.pics", // set your very domain here
  } );
</script>

<html lang="en">
<!-- file rest unchanged -->

TwicPics Components are now ready to be used: we can display our first image with all the power of TwicPics.

Using TwicPics Components in a React component

Let's reopen our little React component src/components/my-react-component.jsx and modify it as follows:

// src/components/my-react-component.jsx

// import TwicImg from react version of TwicPics components
// and use <TwicImg/> as a replacement for <img/> tag
import { TwicImg } from '@twicpics/components/react'

export const MyReactComponent = () => {
  return <TwicImg src="one-giant-leap.jpg" />
}

The image used here is https://assets.twicpics.com/examples/one-giant-leap.jpg (jpeg - 2662x3697px - 1.69 Mo).

One giant leap for mankind.
One giant leap for mankind.

The network console shows us that we have loaded a webp - 800x800px - 109kB.

Our displayed media is :

  • ideally compressed.
  • perfectly adapted in size to its display area.
  • cropped in its container. This last one guarantees CLS optimization.
Note that here we have used TwicImg with no other properties than src.
Feel free to explore all other TwicImg properties.

Using TwicPics Components in .astro file

As a React developer, we used TwicImg in a React component in the previous example. But with Astro, you can integrate TwicImg directly into an .astro file: page, component, and even layout.

For example, let's modify the src/components/Card.astro component of our project as follows:

---
// src/components/Card.astro
import { TwicImg } from "@twicpics/components/react";
export interface Props {
  title: string;
  src: string;
}
const { title, src } = Astro.props;
---
<li class="link-card">
  <a href="#">
    <h2>
      {title}
      <span>&rarr;</span>
    </h2>
    <TwicImg src={src} ratio="16/9" focus="auto" />
  </a>
</li>
<style>
<!-- file rest unchanged -->
</style>

Then let's update the page src/pages/index.astro that uses this modified component:

---
import Layout from '../layouts/Layout.astro';
import Card from '../components/Card.astro';
import { MyReactComponent } from '../components/my-react-component';
---

<Layout title="Welcome to Astro.">
    <main>
        <h1>Welcome to <span class="text-gradient">Astro</span></h1>
        <!-- Adds MyReactComponent to the template -->
        <MyReactComponent></MyReactComponent>
        <p class="instructions">
            To get start, open the directory <code>src/pages</code> in your project.<br />
            <strong>Code Challenge:</strong> Tweak the "Welcome to Astro" message above.
        </p>
        <ul role="list" class="link-card-grid">
            <Card
                title="Earth"
                src="astro/earth.jpg"
            />
            <Card
                title="Moon"
                src="astro/moon.jpg"
            />
            <Card
                title="Saturn"
                src="astro/saturn.jpg"
            />
            <Card
                title="Neptune"
                src="astro/neptune.jpg"
            />
        </ul>
    </main>
</Layout>
<!-- file rest unchanged -->

This is what we should get:

To infinity and beyond
To infinity and beyond

There again, the network console shows us that our loaded images are :

  • ideally compressed
  • perfectly adapted in size to their display area
  • cropped in their container

What about LQIP?

There is one more thing to consider to fully use TwicPics Components in an Astro project.

By default, Astro removes all javascript code generated from the server-side pages. It is up to the developer to specify if (and when) javascript should be loaded client side. This is called partial hydration.

In our case, the LQIP functionality uses a small piece of javascript. So we have to use the client:load directive.

Let's modify src/components/Card.astro by adding client:load directive to our TwicImg React component:

// src/components/Card.astro
<TwicImg src={src} ratio="16/9" focus="auto" client:load />

Let's also modify src/pages/index.astrofile by adding client:load directive to our MyReactComponent React component:

// src/pages/index.astro
<!-- Adds MyReactComponent to the template -->
<MyReactComponent client:load/>

Here is the result:

Failure is not an option.
Failure is not an option.

TwicPics Components are now fully functional. Users will have a better experience: a blurry lightweight version of your media will be displayed until the final image is loaded.

To go further: integration with View Transitions

View Transitions is an exciting - yet experimental - feature released with Astro 3. Based on native browser transition effects, this feature simplifies the creation of bespoke animation effects as users navigate between pages.

As in the following example:

Space, the final frontier.

Now that you've gained a solid understanding of integrating TwicPics into your Astro projects, let's explore how to leverage TwicPics Components within the context of these View Transitions.

In the following, we will use Astro3 and TwicPics Components version 0.25.1+.

To showcase this section, we've crafted a brief demo with the source code available here. We used tailwindcss to eliminate the need for writing styles. If you haven't tried this tool yet, we highly recommend giving it a go.

Activate ViewTransition

As we want to activate transitions on all pages of our site, we add the ViewTranstion router to the common layout (where we previously configured TwicPics Components):

// src/layouts/Layout.astro
---
// imports TwicPics style
import "@twicpics/components/style.css";

// imports Astro ViewTransitions routing component
import { ViewTransitions } from "astro:transitions";
---

<script>
  // install and configurate TwicPics
  import { installTwicpics } from "@twicpics/components/react";
  installTwicpics( {
    domain: "https://demo.twic.pics/", // set your very domain here
  } );
</script>

<!doctype html>
<html lang="en">
  <head>
    <!-- header elements -->
    <!-- Activate the ViewTransition router for entire site -->
    <ViewTransitions />
  </head>
  <body>
    <slot />
  </body>
</html>

At this point, when navigating between the different pages of the site, we get a simple - but pretty - cross-fade effect between the page-old and page-new elements.

Something like this (where we've slowed down the animations for better clarity) :

An hyperdrive prototype.

Pairing matching elements

To achieve our morphing effect, we'll use the transition:name directive: this pairs an element in page-old with its equivalent in page-new. Astro will do the rest.

When using TwicPics Components, transition:name must be set on its container, not directly on the component itself.

For example:

// src/pages/old
---
// imports TwicImg into your .astro file
import { TwicImg } from "@twicpics/components/react";
--- 
<!-- start of your template -->
<div
  class="some_style"
  transition:name={ a_unique_id_for_this_given_template }
>
  <TwicImg 
    src={ src }
    client:load
    ratio="16/9"
  />
</div>
<!-- rest of your template -->
// src/pages/new
---
// imports TwicImg into your .astro file
import { TwicImg } from "@twicpics/components/react";
--- 
<!-- start of your template -->
<div
  class="some_style_may_be_different_from_paired_element"
  transition:name={ a_unique_id_for_this_given_template_but_same_as_paired_element }
>
  <TwicImg 
    src={ src }
    client:load
    ratio="4/3" <!-- Astro will manage the aspect-ratio change -->
  />
</div>
<!-- rest of your template -->

And that's it! Transitions configuration is now complete.

Astro handles the rest seamlessly (once again, with slowed-down animations):

Logic is the beginning of wisdom.

With our morphing effect in place, let's delve into the changes that occurred in the TwicPics API calls, focusing only on Earth images:

There are 3 important things to note here:

  • both of these variants originate from the same master file (jpeg - 6561x6561px - 1.66 Mo).
  • for each state, we load an image that is perfectly optimized and perfectly sized for its container.
  • no requests are made for intermediate states: the use of ViewTransition consumes no more bandwidth than a simple page change.

Where the power of TwicPics shines through

In the case of the previous demo, the actual pairing of our planet images is done here and there. In both cases, we used refit transformation:

// src/components/PlanetCard.astro
  ...
  <TwicImg
      src={ cover }
      alt={ name }
      client:load
      mode="contain" <!-- makes the image sit inside the area -->
      refit="5p" <!-- activates refit transformation with a 5% padding-->
  />
  ...

This way we achieved a harmonized visual result, even with varied sizes and framings in the original images of our planets. As illustrated here:

Fascinating !

Conclusion

With TwicPics Components, managing your media in an Astro.js project becomes a seamless and efficient process. Whether you prefer incorporating TwicPics within a React or Astro Component, the flexibility provided ensures a smooth integration.

Additionally, if you're exploring the experimental features of Astro 3, such as View Transitions, you can seamlessly pair TwicPics Components to enhance visual effects during navigation. Moreover, it's worth noting that using View Transitions incurs no additional bandwidth cost, ensuring a lightweight and efficient user experience. The demonstration site is available here.

If you want to discover more about the capabilities of TwicPics Components and explore their features such as smart cropping, driven layout, short video optimization feel free to visit this other demonstration page. They are free and open-source. Don't hesitate to test them for yourself. The only requirement to use them is to have a TwicPics account. If you don't already have one, you can easily create your own TwicPics account for free.