<turbo-stream action="append" target="posts_list"><template>    <div class="postbit" id="197971" data-post-id="197971">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="josevalim" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/josevalim/120/1787_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  josevalim
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Creator of Elixir</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="cnck1387" data-post="6" data-topic="35992">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/c/2bfe46/48.png" class="avatar"> cnck1387:</div>
<blockquote>
<p>If we had application template support as a feature (like Rails) this could be a solved problem outside of the official generator</p>
</blockquote>
</aside>
<p>As the person who literally implemented the Rails Application Templates in the incarnation still used today, they have many pitfalls that may not be obvious unless you maintain them and/or write anything mildly complex with them. For example:</p>
<ol>
<li>
<p>Brittle. Whenever you change the generated code, which is often common, there is a chance template code will break or it will generate the wrong application</p>
</li>
<li>
<p>They don’t compose. As application templates get more and more complex, it is unlikely you can run multiple of them</p>
</li>
<li>
<p>Untested. Back then I don’t remember seeing a single application generator which comes with a comprehensive test suite (which would help addressing previous points)</p>
</li>
<li>
<p>Hard to maintain. It is really hard to maintain an application template as you extend it because they lack structure</p>
</li>
</ol>
<p>But most importantly, I think application templates most often miss the point: what are the odds that you need to execute something exactly when the application is being generated? For example, take <code>mix phx.gen.auth</code>, it could be designed as an <code>--auth</code> flag to <code>phx.new</code> but it is just so much better as its own standalone project.</p>
<p>So what about Tailwind support on Phoenix if it is not part of Phoenix? How would someone approach that? Easy:</p>
<pre><code>$ mix archive.install hex phx_new
$ mix archive.install hex phx_new_tailwind
$ mix phx.new foo
$ cd foo
$ mix phx.new.tailwind # change everything required for tailwind support
</code></pre>
<p>While this approach doesn’t necessarily address point 1, because this type of code will always be brittle, it pretty much does better in all other points mentioned above. The beauty of <code>phx_new_tailwind</code> is:</p>
<ol>
<li>
<p>Is its own project, with proper structure, and hopefully tests</p>
</li>
<li>
<p>Has its own command, which means it has a proper place to document all of its options and behaviour (something you don’t get with application templates iirc)</p>
</li>
</ol>
<p>I am sure this process is nowhere as fleshed out as Rails Application Templates, but I would rather use this approach as a starting point and improve it based on feedback than pick a solution that has many known pitfalls. In any case, it is 100% possible today.</p>
<p>This is not even specific to Phoenix… as the same can be achieved with Rails generators and it is pretty much the approach I preferred back then: <code>devise</code> and <code>simple_form</code> used <code>rails devise:install</code> and <code>rails simple_form:install</code> commands instead of templates. I remember maintaining some front-end based installers way back then too.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="197971" data-batch-url="/posts/batch_likers">
                        14
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/adding-tailwind-flag-to-phx-new/35992/22">Post #21</a>
	                </div>
	            </div>
              <div id="likers-container-197971" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="197971"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-most-liked cat-most-liked" title="One of the top 3 liked posts in this thread!"></div>
  </section>
</div>
    <div class="postbit" id="197982" data-post-id="197982">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="cnck1387" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  cnck1387
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote group-livebook_core_team" data-username="josevalim" data-post="22" data-topic="35992">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/josevalim/48/1787_2.png" class="avatar"> josevalim:</div>
<blockquote>
<p>hey have many pitfalls that may not be obvious unless you maintain them and/or write anything mildly complex with them.</p>
</blockquote>
</aside>
<p>I’ve maintained one project for years. Funny enough it ended up being one of my most popular projects on GitHub. I think folks just like the idea of starting off with something instead of a blank slate. From a code organization POV I didn’t find it tough to maintain and it was pretty complex.</p>
<aside class="quote group-livebook_core_team" data-username="josevalim" data-post="22" data-topic="35992">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/josevalim/48/1787_2.png" class="avatar"> josevalim:</div>
<blockquote>
<p>I don’t remember seeing a single application generator which comes with a comprehensive test suite</p>
</blockquote>
</aside>
<p>At the time I had integration tests too, basically running the CLI tool to generate the app and then run assertions on that generated app to make sure certain things existed. It also even ran the test suite of the generated app to make sure all of its tests passed (which I had a lot of).</p>
<p>Was it perfect? No. Is it the best code ever written? Hell no. I ended up making this thing shortly after learning Rails and building a few real world apps. I figured rolling up all of those patterns I learned into something someone else can use to bootstrap their app quicker with a bit of opinions felt useful.</p>
<aside class="quote group-livebook_core_team" data-username="josevalim" data-post="22" data-topic="35992">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/josevalim/48/1787_2.png" class="avatar"> josevalim:</div>
<blockquote>
<p>it is 100% possible today</p>
</blockquote>
</aside>
<p>Totally, but there’s at least 1 missing link.</p>
<p>Right now everyone needs to go off and do their own thing, creating their own custom generators with no unified DSL for manipulating files. That’s why you have all of that generic file and project manipulation code tucked away in the gen auth project. IMO it would be much more beneficial to have that stuff available in an official package (or built into mix, etc.) that anyone can use for their own generators.</p>
<aside class="quote group-livebook_core_team" data-username="josevalim" data-post="22" data-topic="35992">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/josevalim/48/1787_2.png" class="avatar"> josevalim:</div>
<blockquote>
<p>They don’t compose. As application templates get more and more complex, it is unlikely you can run multiple of them</p>
</blockquote>
</aside>
<p>Agreed. I ran into this problem with orats even while working on only 1 template and eventually switched away from application templates to just having a skeleton of a project available, and a thin CLI wrapper to customize names of things.</p>
<p>Although <a href="https://railsbytes.com/public/templates" class="inline-onebox" rel="noopener nofollow ugc">Rails Bytes</a> seems to be quite popular nowadays where the community can find and contribute templates.</p>
<p>Maybe the missing links isn’t so much Rails application templates for Phoenix as a direct port, but more so a really slick set of functions to CRUD text in an Elixir / Phoenix project (the DSL) to begin with?</p>
<aside class="quote group-livebook_core_team" data-username="josevalim" data-post="22" data-topic="35992">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/josevalim/48/1787_2.png" class="avatar"> josevalim:</div>
<blockquote>
<p>I think application templates most often miss the point: what are the odds that you need to execute something exactly when the application is being generated?</p>
</blockquote>
</aside>
<p>At the end of the day, generating the initial project becomes a trigger to execute the application template. Technically another trigger could do this, but it feels natural to happen during the generation of a new project.</p>
<p>I think running commands is also a key component besides the functions that give you a nice DSL to CRUD files because think back to your Devise gem. It had a generator that would insert files into your project.</p>
<p>A Rails application template could get triggered from creating a new project, add devise to the gemfile, install everything, run the devise generator and edit the files that generator created. This only becomes convenient and possible when you have access to both the DSL for CRUDing files and a means to run commands.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="197982" data-batch-url="/posts/batch_likers">
                        2
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/adding-tailwind-flag-to-phx-new/35992/23">Post #22</a>
	                </div>
	            </div>
              <div id="likers-container-197982" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="197982"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #22"></div>
  </section>
</div>
    <div class="postbit" id="197985" data-post-id="197985">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="josevalim" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/josevalim/120/1787_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  josevalim
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Creator of Elixir</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="cnck1387" data-post="23" data-topic="35992">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/c/2bfe46/48.png" class="avatar"> cnck1387:</div>
<blockquote>
<p>At the time I had integration tests too, basically running the CLI tool to generate the app and then run assertions on that generated app to make sure certain things existed. It also even ran the test suite of the generated app to make sure all of its tests passed (which I had a lot of).</p>
</blockquote>
</aside>
<p><img src="https://forum.elixirforum.com/images/emoji/apple/+1.png?v=15" title=":+1:" class="emoji only-emoji" alt=":+1:" loading="lazy" width="20" height="20"></p>
<aside class="quote no-group" data-username="cnck1387" data-post="23" data-topic="35992">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/c/2bfe46/48.png" class="avatar"> cnck1387:</div>
<blockquote>
<p>That’s why you have all of that generic file and project manipulation code tucked away in the gen auth project. IMO it would be much more beneficial to have that stuff available in an official package (or built into mix, etc.) that anyone can use for their own generators.</p>
</blockquote>
</aside>
<p>Exactly. I would 100% prefer to focus on tackling this problem than providing templates as a whole. Otherwise I expect anyone using templates in anger to run into the same issues as you and eventually move away.</p>
<p>Mix does ship with a <code>Mix.Generator</code> module but its API today is tiny. We definitely can augment it but I also suspect a high-level API that knows about Phoenix specific constructs would be necessary.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="197985" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/adding-tailwind-flag-to-phx-new/35992/24">Post #23</a>
	                </div>
	            </div>
              <div id="likers-container-197985" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="197985"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #23"></div>
  </section>
</div>
    <div class="postbit" id="197987" data-post-id="197987">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="dbern" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/dbern/120/7635_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  dbern
                      <span class="op-star" title="Thread Starter">
                        <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                      </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote group-livebook_core_team" data-username="josevalim" data-post="22" data-topic="35992">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/josevalim/48/1787_2.png" class="avatar"> josevalim:</div>
<blockquote>
<p>While this approach doesn’t necessarily address point 1, because this type of code will always be brittle, it pretty much does better in all other points mentioned above. The beauty of <code>phx_new_tailwind</code> is:</p>
<ol>
<li>Is its own project, with proper structure, and hopefully tests</li>
<li>Has its own command, which means it has a proper place to document all of its options and behaviour (something you don’t get with application templates iirc)</li>
</ol>
</blockquote>
</aside>
<p>Wonderful! This <code>phx_new_tailwind</code> may need to pin itself against versions of Phoenix to ensure compatibility since Phoenix generates with foo (for example Webpack) by default, but I don’t see that as a huge problem.</p>
<p>The unfortunate part about separate projects like this is that it requires more instruction to the user and has less visibility.</p>
<ul>
<li>
<p>re: visibility: If there is a family of generators like this, it would be helpful to have a section on the Phoenix readme/guides that points to these generators since they’re potentially important to the user when starting a project, so they don’t run <code>mix phx.new</code> before they realize these other starters are available.</p>
</li>
<li>
<p>re: user instruction: if the user is expected to run <code>mix phx.new</code> first and then <code>mix phx.new.tailwind</code>, then that’s adding more friction to these generators that flags like <code>--live</code> don’t have. I’m not suggesting those flags also be separated; just saying that experience is nicer to new users. An alternative is to have the user only run <code>mix phx.new.tailwind</code>, which passes original flags onto <code>mix phx.new</code> and then proceeds to add its own templates and adjustments.</p>
</li>
</ul>
<p>If you have implementation suggestions, I’d love them. Like I said in the original post, I’d love to work on this feature. Thanks for your thoughts!</p>
<hr>
<p>separately, I found a need to see the diffs between generated Phoenix projects. Anyone know of a tool that shows these? Something like <a href="http://railsdiff.org" rel="noopener nofollow ugc">http://railsdiff.org</a>. I’d like to add support for these in <a href="https://diff.hex.pm" rel="nofollow">https://diff.hex.pm</a> somehow.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="197987" data-batch-url="/posts/batch_likers">
                        2
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/adding-tailwind-flag-to-phx-new/35992/25">Post #24</a>
	                </div>
	            </div>
              <div id="likers-container-197987" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="197987"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #24"></div>
  </section>
</div>
    <div class="postbit" id="197988" data-post-id="197988">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="chrismccord" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/chrismccord/120/24233_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  chrismccord
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Creator of Phoenix</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="dbern" data-post="25" data-topic="35992">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/dbern/48/7635_2.png" class="avatar"> dbern:</div>
<blockquote>
<p>Like I said in the original post, I’d love to work on this feature. Thanks for your thoughts!</p>
</blockquote>
</aside>
<p>Whether we use tailwind itself has other considerations for the team which we are still exploring, so hang tight for now! <img src="https://forum.elixirforum.com/images/emoji/apple/slight_smile.png?v=15" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20"></p>
<p>From a maintenance perspective alone on our side, I encourage folks to go the separate project route if they want to ship specialized generators. I don’t foresee us going an extensible template route in any near term future.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="197988" data-batch-url="/posts/batch_likers">
                        3
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/adding-tailwind-flag-to-phx-new/35992/26">Post #25</a>
	                </div>
	            </div>
              <div id="likers-container-197988" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="197988"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #25"></div>
  </section>
</div>
    <div class="postbit" id="197990" data-post-id="197990">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="cnck1387" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  cnck1387
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote group-livebook_core_team" data-username="josevalim" data-post="24" data-topic="35992">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/josevalim/48/1787_2.png" class="avatar"> josevalim:</div>
<blockquote>
<p>Mix does ship with a <code>Mix.Generator</code> module but its API today is tiny. We definitely can augment it but I also suspect a high-level API that knows about Phoenix specific constructs would be necessary.</p>
</blockquote>
</aside>
<p>I think that would go a long ways and yes, having knowledge about Phoenix would be very helpful. Although I’m not sure how that would pan out in the end for both end users and generator authors.</p>
<p>For example earlier you mentioned this workflow:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">$ mix archive.install hex phx_new
$ mix archive.install hex phx_new_tailwind
$ mix phx.new foo
$ cd foo
$ mix phx.new.tailwind # change everything required for tailwind support
</code></pre>
<p>As an end user that’s a few extra steps to add Tailwind to a project. Realistically it’ll probably be more steps because I would guess that most folks would install <code>phx_new_tailwind</code> as a dependency of their existing project, generate the files and then remove the dependency since all it did was produce files in a specific location.</p>
<p>I mostly agree with you that despite Bytepack existing, realistically I can’t see anyone cherry picking 15 tiny isolated templates and having them all play nice together with little to no user intervention. There’s just too many conflicts about where things may or may not exist in a file once you have 10 other things writing to that file that you have no control over.</p>
<p>And that leads full circle back to having pre-created applications that have whatever opinions you want baked in, and you take it or leave it with no generators. This works and it’s what I do but it also has its own set of problems like wanting to customize the names of things, so you end up with some crazy shell script to do find / replaces in a bunch of files and directories.</p>
<p>I’ll admit it’s not an easy problem to solve, and tailwind support is just an introduction to the idea of wanting to quickly add custom optional features to an existing base application.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="197990" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/adding-tailwind-flag-to-phx-new/35992/27">Post #26</a>
	                </div>
	            </div>
              <div id="likers-container-197990" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="197990"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #26"></div>
  </section>
</div>
    <div class="postbit" id="198010" data-post-id="198010">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="hauleth" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/hauleth/120/18942_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  hauleth
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="cnck1387" data-post="27" data-topic="35992">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/c/2bfe46/48.png" class="avatar"> cnck1387:</div>
<blockquote>
<p>I can’t see anyone cherry picking 15 tiny isolated templates and having them all play nice together with little to no user intervention.</p>
</blockquote>
</aside>
<p>My 2 cents on that is:</p>
<p>Most users do not start projects which needs so many customisations from day one (and if they do, then I would say, they do something wrong). In a lot of cases people will do <code>mix phx.new</code> once, and then they will go with the project, because let’s be honest, it is not that often that you start new projects from the ground up. For sure it is less often than adding features to existing projects.</p>
<p>For example, I am using completely different approach for naming my controllers and stuff (instead of <code>MyAppWeb.FooController</code> I use <code>MyAppWeb.Controllers.Foo</code> to follow naming convention used almost all other Elixir projects) which requires me to do “few” manual steps. I do it by the hand each time, and TBH I never had a problem with that, because in last year I needed to do it twice. Oh, and by the way, I am not using Webpack at all, so I need to change it to Parcel as well, so this is quite some time for preparing that. Having such generator maybe would be useful, but I do all of that so rarely, that <a href="https://xkcd.com/1319/" class="inline-onebox" rel="noopener nofollow ugc">xkcd: Automation</a> and <a href="https://xkcd.com/1205/" class="inline-onebox" rel="noopener nofollow ugc">xkcd: Is It Worth the Time?</a> describes why it is not worth my time.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="198010" data-batch-url="/posts/batch_likers">
                        2
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/adding-tailwind-flag-to-phx-new/35992/28">Post #27</a>
	                </div>
	            </div>
              <div id="likers-container-198010" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="198010"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #27"></div>
  </section>
</div>
    <div class="postbit" id="198063" data-post-id="198063">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="hpjm" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  hpjm
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>I love Tailwind, and use it a lot, but I’m not sure that this proposal is a good idea. I realise that there are lots of other folks who would prefer to use Bulma, or Bootstrap or [insert CSS framework here].</p>
<p>I’ve also set up Tailwind with Phoenix, and it really isn’t that difficult if you know your way around Webpack. In fact all you need is the default how to on the Tailwind page.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="198063" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/adding-tailwind-flag-to-phx-new/35992/29">Post #28</a>
	                </div>
	            </div>
              <div id="likers-container-198063" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="198063"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #28"></div>
  </section>
</div>
    <div class="postbit" id="198074" data-post-id="198074">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="wojtekmach" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/wojtekmach/120/999_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  wojtekmach
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Hex Core Team</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Regarding generators, there’s perhaps one more piece of context worth adding and a distinction to be made. We have:</p>
<ol>
<li><em>application</em> generators like <code>mix phx.new</code> or the potential new <code>mix phx.new.tailwind</code></li>
<li><code>phx.gen.*</code> generators, like <code>mix phx.gen.html</code>, <code>mix phx.gen.live</code>, etc.</li>
</ol>
<p>The latter happen to be configurable to some extent, by default they read templates from Phoenix’s <code>priv/templates</code> directory, but if your app has it’s own <code>priv/templates</code>, that’d take priority. Thus, you can customise the template files like this:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">$ cp -R _build/dev/lib/phoenix/priv/templates priv/
$ open priv/templates/phx.gen.live/index.html.leex
$ mix phx.gen.live Blog Post posts title:string # uses your local overrides
</code></pre>
<p>I couldn’t find this behaviour documented anywhere and thus there’s probably no explicit contract between <code>mix phx.gen.*</code> and the respective templates, so there’s no compatibility guarantee going forward. However, if there’s a <code>mix phx.gen.tailwind</code> task, that is pinned to a specific Phoenix version, it could generate <code>priv/templates</code> that are augmented with tailwind related changes if that’d be useful.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="198074" data-batch-url="/posts/batch_likers">
                        5
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/adding-tailwind-flag-to-phx-new/35992/30">Post #29</a>
	                </div>
	            </div>
              <div id="likers-container-198074" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="198074"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #29"></div>
  </section>
</div>
    <div class="postbit" id="198076" data-post-id="198076">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="wojtekmach" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/wojtekmach/120/999_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  wojtekmach
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Hex Core Team</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="cnck1387" data-post="27" data-topic="35992">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/c/2bfe46/48.png" class="avatar"> cnck1387:</div>
<blockquote>
<p>For example earlier you mentioned this workflow:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">$ mix archive.install hex phx_new
$ mix archive.install hex phx_new_tailwind
$ mix phx.new foo
$ cd foo
$ mix phx.new.tailwind # change everything required for tailwind support
</code></pre>
<p>As an end user that’s a few extra steps to add Tailwind to a project. Realistically it’ll probably be more steps because I would guess that most folks would install <code>phx_new_tailwind</code> as a dependency of their existing project, generate the files and then remove the dependency since all it did was produce files in a specific location.</p>
</blockquote>
</aside>
<p>Hmm, I thought <code>mix phx.new.tailwind</code> would use the <code>phx.new</code> task under the hood but I misunderstood the intention. If it would work that way, though, fwiw we’d have one less step: (not that I personally think having multiple steps is a big deal)</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">$ mix archive.install hex phx_new
$ mix archive.install hex phx_new_tailwind
$ mix phx.new.tailwind foo
$ cd foo
</code></pre>
<p>Archives can’t have deps so we need to explicitly first install <code>phx_new</code>. Again, since we can’t have deps we can’t pin to a specific phoenix version either, however I suppose <code>phx_new_tailwind</code> could vendor a specific <code>phx_new</code> version for maximum compatibility in which case we’d have:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">$ mix archive.install hex phx_new_tailwind
$ mix phx.new.tailwind foo
$ cd foo
</code></pre>
<p>If the idea for the tailwind generator is to be used on an existing app, I’d consider calling it <code>mix phx.gen.tailwind</code>. A very subtle difference but perhaps worth making.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="198076" data-batch-url="/posts/batch_likers">
                        6
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/adding-tailwind-flag-to-phx-new/35992/31">Post #30</a>
	                </div>
	            </div>
              <div id="likers-container-198076" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="198076"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #30"></div>
  </section>
</div>
</template></turbo-stream><turbo-stream action="replace" target="load-more-container"><template><div id="load-more-container" class="load-more-container">
    <a class="load-more-button" data-turbo-stream="true" href="/topics/35992/load_more?page=4">Load more posts (4 remaining)</a>
</div></template></turbo-stream>