#How to use alpine.js inside of a <script> tag in astro?

20 messages · Page 1 of 1 (latest)

red ingot
#

Hi. I want to use alpine.js inside of a <script> in an .astro component. I have added alpine via the pnpm astro add alpinejs command to my project.

My Astro component has a <script> at the bottom like this:

<script>
    console.log(Alpine);
</script>

This works as expected (I believe) in runtime because the Alpine instance gets logged in the browser console, but I am getting type errors:

Cannot find name 'Alpine'.ts(2304)

Additionally, because I have auto-imports in VSCode, the editor tries to import the alpine library like this:

<script>
    import Alpine from 'alpinejs';
    console.log(Alpine);
</script>

But that's obviously not what we want.

How do I fix these type errors?

obsidian bearBOT
#

Hi @red ingot. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:

#

To fix the TypeScript error (Cannot find name 'Alpine'.ts(2304)) when using Alpine.js in a <script> tag in your Astro component, you need to tell TypeScript that Alpine exists on the global window object. The official Astro Alpine.js integration recommends adding a type declaration for this.

Solution:

Create or update the file src/env.d.ts in your project and add the following code:

interface Window {
  Alpine: import('alpinejs').Alpine;
}

This informs TypeScript that window.Alpine is available globally, which resolves the type error in your scripts. You do not need to import Alpine directly in your <script> tag—Alpine is already loaded globally by the integration, and importing it in the script would not work as expected in the browser context.

Summary of steps:

  1. Add the above interface to src/env.d.ts.
  2. Remove any import Alpine from 'alpinejs' statements from your <script> tags.
  3. Use window.Alpine or just Alpine in your client-side scripts as needed.

Reference: Intellisense for TypeScript – Astro Alpine.js Integration Guide

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:

#

@red ingot Kapa.ai is still learning and improving, please let me know how I did by reacting below.

red ingot
#

@obsidian bear thanks for the suggestion. I did create an env.d.ts file like it is explained in the docs, but I still get the same error. However I noticed now that windows.Alpine works file.

<script>
    // works fine
    console.log(window.Alpine);
    // gives an error: Cannot find name 'Alpine'.ts(2304)
    console.log(Alpine);
</script>
obsidian bearBOT
#

Let me check the knowledge base for you again. One moment! :books:

#

You're correct in your observation: after adding the recommended type declaration to src/env.d.ts, TypeScript will recognize window.Alpine, but not the global Alpine variable by itself.

According to the official Astro Alpine.js integration documentation, the type declaration provided is:

interface Window {  Alpine: import('alpinejs').Alpine; }

This declaration tells TypeScript that window.Alpine exists, but it does not declare a global variable named Alpine. Therefore, using window.Alpine in your <script> tag will work without type errors, while using just Alpine will still result in a "Cannot find name 'Alpine'" error. This matches your experience and is the expected behavior based on the documentation.

In summary:

  • Use window.Alpine in your <script> tags to avoid TypeScript errors.
  • The documentation does not provide a way to make Alpine available as a global variable without the window. prefix in TypeScript, so this is the recommended and supported approach Astro Alpine.js Intellisense for TypeScript.

If you want to use Alpine without the window. prefix, you would need to declare it as a global variable in your type definitions, but the official documentation does not cover or recommend this.

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:

#

@red ingot Kapa.ai is still learning and improving, please let me know how I did by reacting below.

dense wave
#

@obsidian bear is Alpine still in active development and recommended for use with Astro?

obsidian bearBOT
#

Let me check the knowledge base for you again. One moment! :books:

#

Based on the provided knowledge sources, Alpine.js is officially supported and recommended for use with Astro through the @astrojs/alpinejs integration. The documentation describes how to install and use Alpine.js in Astro projects, and provides links to the integration’s GitHub repository and npm package. The documentation also references the latest version (v0.4.8) and includes example usage and configuration options.

However, the knowledge sources do not explicitly state whether Alpine.js itself is still in active development, nor do they provide a direct recommendation about Alpine.js’s long-term viability outside of its current support in Astro. The documentation does indicate that Alpine.js is a first-class, officially maintained integration and is presented alongside other popular frameworks, which suggests it is recommended for use with Astro at this time Astro Alpine.js Integration Guide.

If you need up-to-date information about Alpine.js’s development status, you may want to check the Alpine.js official website or its GitHub repository directly.

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:

#

@mint ether Kapa.ai is still learning and improving, please let me know how I did by reacting below.

dense wave
#

@obsidian bear How would you spread attributes into the following Button?

{
            welcome.actions.map((i, x) => (
                <div
                    class:list={[
                        'first:border-r first:border-(--color-hairline)',
                        'first:pr-4 lg:first:pr-6 last:pl-4 lg:last:pl-6',
                    ]}>
                    <Button
                        tag='a'
                        text={i}
                        variant={x === 0 ? 'elevated' : 'display'}
                        color={x === 0 ? 'body' : 'surface'}
                        href={x === 0 ? 'https://ficus.im' : '/q/1'}
                    />
                </div>
            ))
        }

I want if x === 0 then Button tag='a', then href
if x===1 then no tag, no href, but data-action='continue'

obsidian bearBOT
#

Let me check the knowledge base for you again. One moment! :books:

#

Based on the knowledge sources, in Astro (and JSX-like syntax in Astro components), you can use the spread operator (...) to pass a set of attributes or props to a component. You can build an object with the desired attributes and then spread it into your component.

Here’s how you could adapt your code to conditionally spread attributes into the Button component:

{
  welcome.actions.map((i, x) => {
    // Build the props object conditionally
    const buttonProps = x === 0
      ? { tag: 'a', href: '<https://ficus.im'> }
      : { 'data-action': 'continue' };

    return (
      <div
        class:list={[
          'first:border-r first:border-(--color-hairline)',
          'first:pr-4 lg:first:pr-6 last:pl-4 lg:last:pl-6',
        ]}
      >
        <Button
          text={i}
          variant={x === 0 ? 'elevated' : 'display'}
          color={x === 0 ? 'body' : 'surface'}
          {...buttonProps}
        />
      </div>
    );
  })
}

This approach is supported in Astro’s component syntax, as described in the dynamic attributes documentation:

Local variables can be used in curly braces to pass attribute values to both HTML elements and components.

And for spreading attributes:

You can use the spread operator (...) to pass all properties of an object as attributes to an element or component.

If you need to type these props in TypeScript, you can use the HTMLAttributes utility type as described in the TypeScript guide.

Note:
If you are using a framework component (like React or Vue) inside Astro, this pattern also works as expected.


#

@mint ether Kapa.ai is still learning and improving, please let me know how I did by reacting below.

dense wave
#

@obsidian bear You did miss some of my points.. when x===1 the tag should not be present

obsidian bearBOT
#

Let me check the knowledge base for you again. One moment! :books:

#

You're right—when x === 1, the tag and href attributes should not be present at all. In Astro, you can achieve this by conditionally building the props object and only including the attributes you want to spread. This is supported by Astro's dynamic attribute and spread syntax Dynamic Attributes in Astro.

Here’s how you can do it:

{
  welcome.actions.map((i, x) => {
    // Only include tag and href when x === 0
    const buttonProps = x === 0
      ? { tag: 'a', href: '<https://ficus.im'> }
      : { 'data-action': 'continue' };

    return (
      <div
        class:list={[
          'first:border-r first:border-(--color-hairline)',
          'first:pr-4 lg:first:pr-6 last:pl-4 lg:last:pl-6',
        ]}
      >
        <Button
          text={i}
          variant={x === 0 ? 'elevated' : 'display'}
          color={x === 0 ? 'body' : 'surface'}
          {...buttonProps}
        />
      </div>
    );
  })
}

This way, when x === 1, neither tag nor href will be present in the props passed to Button, and only data-action="continue" will be included. This approach is directly supported by Astro's component and attribute spreading syntax Dynamic Attributes in Astro.

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: