Skip to content

Instantly share code, notes, and snippets.

@lcw99
Last active January 22, 2025 15:57
Show Gist options
  • Save lcw99/ac1738cb6d5bb032085077605f56665e to your computer and use it in GitHub Desktop.
Save lcw99/ac1738cb6d5bb032085077605f56665e to your computer and use it in GitHub Desktop.

Enhancing SEO in Flutter Web Projects with Next.js Integration

When building websites with Flutter, a significant challenge encountered is Search Engine Optimization (SEO). The main issue arises because search engine crawlers often fail to index the text content in Flutter web applications. This limitation stems from the fact that Flutter web builds essentially result in static websites, which aren't crawler-friendly by default.

Addressing this challenge with Flutter alone is a daunting task. Given the nature of static sites produced by Flutter web builds, incorporating an additional web project, like one built with Next.js, becomes essential. This approach is not only about solving crawling issues but also about dynamically providing appropriate meta tags based on the content, which is nearly impossible with just Flutter.

Rather than struggling with these limitations, a practical solution involves embedding your Flutter web site within a server-side rendering project like Next.js. This method allows for significant improvements in SEO. For instance, you can detect web crawlers and return suitable meta tags accordingly. Similarly, for content within your Flutter web that needs to be exposed to crawlers, presenting a slimmed-down HTML version without CSS proves to be highly effective.

Here's a basic example of how to integrate a Flutter web project within a Next.js project:

  1. Create a Next.js Project: First, set up a new Next.js project if you don't have one already.

    npx create-next-app my-nextjs-project
    cd my-nextjs-project
  2. Include Your Flutter Web Project: Place your built Flutter web project in the public directory of your Next.js project.

    my-nextjs-project/
    ├── public/
    │   └── flutter_web_project/   # Your Flutter web build files
    └── ...
    
  3. Server-Side Rendering with Next.js: In your Next.js pages, use server-side rendering to detect crawlers and modify meta tags dynamically. Here's an example of a basic setup:

    import { useEffect } from 'react';
    
    const Home = ({ isCrawler }) => {
      useEffect(() => {
        if (!isCrawler) {
          // Load Flutter web app for regular users
          window.location.href = '/flutter_web_project/index.html';
        }
      }, [isCrawler]);
    
      return (
        <div>
          {isCrawler ? (
            // Provide SEO-friendly content for crawlers
            <div>
              <h1>My Flutter Web App</h1>
              <p>Here's some content that's important for SEO...</p>
              {/* More SEO-friendly content */}
            </div>
          ) : (
            // Regular users will be redirected to Flutter web app
            <p>Loading...</p>
          )}
        </div>
      );
    };
    
    export async function getServerSideProps(context) {
      const userAgent = context.req.headers['user-agent'];
      const isCrawler = /bot|googlebot|crawler|spider|robot|crawling/i.test(userAgent);
      return { props: { isCrawler } };
    }
    
    export default Home;

Conclusion:

Integrating a Flutter web project into a server-side rendered framework like Next.js not only resolves crawling issues but also opens up the door for dynamic meta tag management and better overall SEO performance. This approach leverages the strengths of both technologies, offering a more comprehensive solution for web development.

Important Note:

To implement this integration successfully, it's essential to modify the URL strategy in your Flutter web project. By default, Flutter uses hash (#) in the URLs, which can be problematic for SEO. To enhance the SEO, you should switch to using the 'path' URL strategy that doesn't include the hash.

You can change this in your Flutter web project by utilizing the url_strategy package. Here’s how to set it up:

  1. Add the url_strategy package to your pubspec.yaml file:

    dependencies:
      url_strategy: ^0.2.0
  2. Set the URL strategy to 'path' in your main.dart:

    import 'package:url_strategy/url_strategy.dart';
    
    void main() {
      setPathUrlStrategy(); // Use path-based URLs instead of hash-based
      runApp(MyApp());
    }

By doing this, your Flutter web URLs will be cleaner and more SEO-friendly, which is crucial for better indexing by search engines.

@LoadJulz
Copy link

I have to say this is a great approach to overcome the SEO issue with Flutter Web. I am currently also trying around to get some basic SEO done with Flutter Web. I also have tried your approach on an own project. I am figuring out the step 2 of your guide. Do you mean by "build web files" the /web folder in the build folder of my flutter project? If I only add this I only see an infinite loading screen and nothing is happening. It doesn't find the manifest.json (even if it is in the folder) and the flutter.js is not loading properly probably because some files are missing.

Could you tell me a bit more which files I need to copy inside the Next.js folder in order to execute the project successfully?

@lcw99
Copy link
Author

lcw99 commented Jun 10, 2024

just run on command prompt
flutter build web
output should be in build/web folder. just copy this folder to flutter_web_project in step 2.

@hadewet
Copy link

hadewet commented Sep 12, 2024

Will this approach not be considered cloaking?

@lcw99
Copy link
Author

lcw99 commented Sep 12, 2024 via email

@NazishAhsan
Copy link

is it possible to do the seo using dynamic data retrieved from API??

@lcw99
Copy link
Author

lcw99 commented Sep 18, 2024 via email

@sumersm7
Copy link

sumersm7 commented Nov 3, 2024

I tried it with nextjs13 and I don't know what kind of navigation is used by next website. So when tried locally it run for the home page , but for nested path next app open instead of flutter

And

When I deploy it using node alpine docker image
Next work but flutter app doesn't.
And same when share nested path it open next app

@lcw99
Copy link
Author

lcw99 commented Nov 3, 2024

@sumersm7
Copy link

sumersm7 commented Nov 5, 2024

@lcw99 i just updated the match congif

export const config = {
  matcher: '/((?!api|_next/static|_next/image|main.dart.js|icons|assets|favicon.ico|favicon.png|flutter_bootstrap.js|manifest.json|flutter.js.map|flutter_service_worker.js).*)', // Apply middleware to all pages
};

and it worked for me

@colbymaloy
Copy link

how about updating the title and description meta tags ? because thats what google search looks at im pretty sure

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment