Skip to content

fix(generate): add support for Expo Router app directory prompts #2905

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 20 commits into
base: feat/expo-sdk-53
Choose a base branch
from

Conversation

cdanwards
Copy link
Member

@cdanwards cdanwards commented Feb 24, 2025

Description

This PR addresses a user who creates screens within an ignited app using expo-router. It checks for the existence of src/app (the expo router configuration) and then determines where to put the screen in 4 ways:

  • An override provided in the CLI command
  • destinationDir set from the screen generator template
  • If neither of those exists, it prompts the user to provide a dir path, if none is provided or they decide to not create that directory, it defaults to src/app/

Screenshots

Scenario Result
Using CLI Override for directory override
Using directory set in template front matter frontmatter
Setting via prompts - chooses to create dir created_dir
Setting via prompts - detects src/app and user just taps enter CleanShot 2025-04-30 at 07 26 44@2x
Setting via prompts - goes to default src/app Screenshot 2025-02-27 at 10 57 11 AM

Checklist

  • README.md and other relevant documentation has been updated with my changes
  • I have manually tested this, including by generating a new app locally (see docs).

@cdanwards cdanwards marked this pull request as ready for review February 27, 2025 16:04
Copy link
Contributor

@frankcalise frankcalise left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work! A few comments for discussion where I think we can shore things up. Also if you think we can add a test to double check the user gets prompted in the way you're expecting if both are omitted that's probably worth adding.

@@ -52,6 +52,53 @@ async function generate(toolbox: GluegunToolbox) {
pascalName = pascalName.slice(0, -1 * pascalGenerator.length)
command(`npx ignite-cli generate ${generator} ${pascalName}`)
}
// Check if src/app exists, denoting an Expo Router app
if (generator === "screen") {
const isExpoRouterApp = filesystem.exists("src/app") === "dir"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this is the correct directory structure to determine expo-router in an Ignite application, however omitting the src/ nesting is totally valid and it is possible a dir structure looks like this:

  • app (the routes)
  • components
  • hooks
  • etc...

This is in fact the default expo application structure and Ignite generators should continue to be compatible for any project, not just our opinionated structure.

So perhaps we should look into a different mechanism for determining this? Maybe we check app or src/app to cover both. Or look for package.json to have expo-router?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, that definitely tracks. I think it would make sense to check for expo-router. Do you think it make more sense to check within the package.json dependencies or within the app.json expo plugins?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd say package.json is easier because you know where it will live, under dependencies, so you can search for the key there.

Issues with the app.json route:

  • It could also be in app.config.js or app.config.ts
  • Plugins is an array of a mix of strings and/or arrary, making searching through it a bit more difficult

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah that's fair, thanks!

@cdanwards cdanwards requested a review from frankcalise March 5, 2025 15:53
Copy link
Contributor

@frankcalise frankcalise left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good! Spotted a couple of things to look over

@@ -52,6 +52,54 @@ async function generate(toolbox: GluegunToolbox) {
pascalName = pascalName.slice(0, -1 * pascalGenerator.length)
command(`npx ignite-cli generate ${generator} ${pascalName}`)
}
// Check if src/app exists, denoting an Expo Router app
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this comment could use updating now that we changed the strategy to look at package.json

@fpena fpena requested a review from frankcalise April 30, 2025 14:29
@jamonholmgren
Copy link
Member

Sorry about not chiming in on the original issue!

I have some thoughts.

  1. I think the screen should be separated from the route.
npx ignite-cli g screen DetailScreen

The screen should always (IMO) be in src/app/screens/detail-screen.tsx (if it's an Expo Router app)

  1. We need a route generator
npx ignite-cli g route listings/detail DetailScreen

This creates a route file at app/listings/detail.tsx which imports the specified screen.

This would allow us to have multiple routes that can import the same screen.

It also eliminates this specialized generator logic which I think is going away from the spirit of the simple generators we want for Ignite. Ignite's generators got too complicated in earlier versions, which is why I rewrote them to be super simple in Ignite 6. The whole CLI was just over 900 lines of code at that point (vs 3k+ for previous versions), and I really don't want to continue to bloat it with additional logic if we can avoid that.

@frankcalise
Copy link
Contributor

frankcalise commented May 26, 2025

I made some updates to this to help progress it along.

Now, for expo-router projects, we restored the screen generator to keep it being placed in src/screens, matching react navigation ignite projects (aside from the root dir)

In addition to that, upon a new project it will generate a route generator template which you can use like so:

npx ignite-cli g route welcome --dir=src/app/some/route

resulting in

src/app/some/route/welcome.tsx and generates

import { WelcomeScreen } from "@/screens/WelcomeScreen"

export default function Welcome() {
  return <WelcomeScreen />
}

Copy link
Contributor

@coolsoftwaretyler coolsoftwaretyler left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Took at look at these changes and tried them out locally across Expo Router/not Expo Router projects generated from a local build of the CLI. Looking good!

@markrickert markrickert mentioned this pull request Jun 3, 2025
8 tasks
@frankcalise frankcalise changed the base branch from master to feat/expo-sdk-53 June 4, 2025 12:34
</Screen>
)
export default function Index() {
return <WelcomeScreen />
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Praise: I love this! Less duplicated code in the boilerplate to maintain! 🎉

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm well the WelcomeScreen itself is still duped, but maybe I can get that even better.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Woot think I can reduce it further, changes incoming 🙏

utilize @demo macro removal to just touch up the boilerplate/app/screens/WelcomeScreen instead of having a copy
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Generating a new screen when using Expo Router results in wrong placement
6 participants