# Upgrade guide

Version updates can be a bit of a manual process. A boilerplate is meant to be a starting point for you to build from - rather than a framework like Phoenix. However, it is possible.

### 2.2 -> 3.0

Petal Pro has been upgraded to Tailwind 4. Some utilities have been removed or renamed. See the [Tailwind upgrade guide](https://tailwindcss.com/docs/upgrade-guide) for more information.

To upgrade to Tailwind 4 in your project, make sure you update `mix.exs`:

```diff
-  {:tailwind, "~> 0.2", runtime: Mix.env() == :dev}
+  {:tailwind, "~> 0.3", runtime: Mix.env() == :dev}
```

And `config.exs` (note that the paths have changed and that you need 4.0.9 or above):

```diff
config :tailwind,
-  version: "3.3.3",
+  version: "4.1.11",
   default: [
     args: ~w(
-      --config=tailwind.config.js
-      --input=css/app.css
-      --output=../priv/static/assets/app.css
+      --input=assets/css/app.css
+      --output=priv/static/assets/app.css
     ),
-    cd: Path.expand("../assets", __DIR__)
+    cd: Path.expand("..", __DIR__)
  ]
```

Don't forget to run:

```bash
mix tailwind.install
```

#### Updated app.css

`app.css` has been updated to support CSS first configuration:

{% code title="app.css" %}

```css
@import "tailwindcss";

@source "../../deps/petal_components/**/*.*ex";
@import "../../deps/petal_components/assets/default.css";

@import "./colors.css";
@import "./combo-box.css";
@import "./editorjs.css";
@import "./animations.css";
@import "../node_modules/tippy.js/dist/tippy.css" layer(components);

@plugin "@tailwindcss/typography";
@plugin "@tailwindcss/forms";
@plugin "@tailwindcss/aspect-ratio";
@plugin "./tailwind_heroicons.js";

...
```

{% endcode %}

To see the latest changes for 3.0.0, go to:

{% embed url="<https://github.com/petalframework/petal_pro/tree/v3.0.0/assets/css>" %}

The following files have changed:

* `app.css`
* `combo-box.css`&#x20;
* `editorjs.css`&#x20;

The following files have been added:

* `colors.css`&#x20;
* `animations.css`&#x20;
* `tailwind_heroicons.js`

Finally, `tailwind.config.js` has been removed.

Now you should be able to follow the [Tailwind upgrade guide](https://tailwindcss.com/docs/upgrade-guide) to update the rest of your project. Running `mix format` should automatically arrange tailwind classes in your project.

### 2.0 -> 2.2

With Petal Components 2.0.6, the `heroicons` dependency has been replaced with a CSS-based approach. This is based on what has been implemented in the Phoenix repo - the reasoning is explained in this [issue](https://github.com/phoenixframework/phoenix/issues/5622). To upgrade an existing Petal Pro project, add the dependency in `mix.exs`:

{% code title="mix.exs" %}

```diff
def deps do
  [
+    {:heroicons,
+      github: "tailwindlabs/heroicons",
+      tag: "v2.1.5",
+      app: false,
+      compile: false,
+      sparse: "optimized"},
  ]
end
```

{% endcode %}

This will download a copy of the source SVG files directly from GitHub (into `deps/heroicons/optimized`). Then the following code will process these files to create custom CSS classes:

{% code title="assets/tailwind.config.js" %}

```diff
const colors = require("tailwindcss/colors");
const plugin = require("tailwindcss/plugin");
+ const fs = require("fs");
+ const path = require("path");

module.exports = {
  plugins: [
+    // Embeds Heroicons (https://heroicons.com) into your app.css bundle
+    // See your `CoreComponents.icon/1` for more information.
+    //
+    plugin(function({matchComponents, theme}) {
+      let iconsDir = path.join(__dirname, "../deps/heroicons/optimized")
+      let values = {}
+      let icons = [
+        ["", "/24/outline"],
+        ["-solid", "/24/solid"],
+        ["-mini", "/20/solid"],
+        ["-micro", "/16/solid"]
+      ]
+      icons.forEach(([suffix, dir]) => {
+        fs.readdirSync(path.join(iconsDir, dir)).forEach(file => {
+          let name = path.basename(file, ".svg") + suffix
+          values[name] = {name, fullPath: path.join(iconsDir, dir, file)}
+        })
+      })
+      matchComponents({
+        "hero": ({name, fullPath}) => {
+          let content = fs.readFileSync(fullPath).toString().replace(/\r?\n|\r/g, "")
+          let size = theme("spacing.6")
+          if (name.endsWith("-mini")) {
+            size = theme("spacing.5")
+          } else if (name.endsWith("-micro")) {
+            size = theme("spacing.4")
+          }
+          return {
+            [`--hero-${name}`]: `url('data:image/svg+xml;utf8,${content}')`,
+            "-webkit-mask": `var(--hero-${name})`,
+            "mask": `var(--hero-${name})`,
+            "mask-repeat": "no-repeat",
+            "background-color": "currentColor",
+            "vertical-align": "middle",
+            "display": "inline-block",
+            "width": size,
+            "height": size
+          }
+        }
+      }, {values})
+    })
  ],
};
```

{% endcode %}

### 1.8 -> 2.0

Starting with 2.0, the Petal Framework has returned to Petal Pro. There is a discussion with regards to this change [in the PR](https://github.com/petalframework/petal_pro/pull/229). The Petal Framework package will be supported in the long run - so there is no need to upgrade immediately. However, over time new features will be added to Petal Pro, rather than the Petal Framework package. If you upgrade to 2.0, you will no longer need to provide your Petal Framework license key. If you have generated a `Dockerfile` for deployment, then you can remove the following section:

<pre class="language-diff" data-title="Dockerfile"><code class="lang-diff"># Remove the Petal repo:
<strong>- RUN --mount=type=secret,id=PETAL_LICENSE_KEY \
</strong>-     mix hex.repo add petal https://petal.build/repo \
-       --fetch-public-key "SHA256:6Ff7LeQCh4464psGV3w4a8WxReEwRl+xWmgtuHdHsjs" \
-       --auth-key $(cat /run/secrets/PETAL_LICENSE_KEY)
</code></pre>

In addition, the `npm` recipe has been merged. Petal Pro is still using `esbuild`, however, javascript libraries are now downloaded as an npm package (instead of depending on a CDN).

You may need to add `nodejs` and `npm` to your `Dockerfile`:

{% code title="Dockerfile" %}

```diff
# install build dependencies
+ RUN apt-get update -y && apt-get install -y build-essential git nodejs npm \
+     && apt-get clean && rm -f /var/lib/apt/lists/*_*
```

{% endcode %}

In the past `mix assets.setup` would install Tailwind CSS and esbuild. Tailwind is now installed with `mix setup`, esbuild is installed via npm with `mix assets.deploy`. You'll need to remove:

{% code title="Dockerfile" %}

```diff
- RUN mix assets.setup
```

{% endcode %}

Finally, `lib/petal_pro_web/petal_framework_translations.ex` is no longer required. Instead, components like the `DataTable` can use [Gettext](https://hexdocs.pm/gettext/Gettext.html) directly.

### 1.6 -> 1.7

Starting in this release, we now use [Styler](https://github.com/adobe/elixir-styler) to format our codebase. This means there will be a large amount of changes. To minimise merge or rebase c                                             onflicts when upgrading, we recommend you swap out Recode with Styler first:

{% code title="mix.exs" %}

```diff
- {:recode, "~> 0.6", only: [:dev, :test]},
+ {:styler, "~> 0.11", only: [:dev, :test], runtime: false},
```

{% endcode %}

{% code title=".formatter.exs" %}

```diff
- plugins: [Phoenix.LiveView.HTMLFormatter, Recode.FormatterPlugin]
+ plugins: [Phoenix.LiveView.HTMLFormatter, Styler]
```

{% endcode %}

Then, replace the content of `.credo.exs` with the one in this repo.

Finally, run the formatter for Styler to take care of things:

```elixir
mix deps.get && mix format
```

Another change we recommend you make before upgrading, especially if you've made changes to your landing page, is to rename `PetalProWeb.Components.LandingPage` to `PetalProWeb.LandingPageComponents`, make sure you also rename the file from `landing_page.ex` to `landing_page_components.ex`.

Given the amount of changes in this release, we recommend you backup your branch, then use `merge` instead of `rebase` to bring your branch up to date.

### 1.5.2

When upgrading to this version, you will need to make your local hex aware of our hex repo. Please follow the instructions [here](https://petal.build/components/install-petal-framework) (it involves using a license key unique to you).

### Updating Petal Framework

Updating the Petal Framework package is as simple as updating any dependency - simply update the version in \`mix.exs\`.

```elixir
{:petal_framework, "~> x.x.x", repo: :petal}
```

### Updating the boilerplate code

Here is some discussion amongst members in a [Github issue](https://github.com/petalframework/petal_pro/issues/14).

Firstly, I'd use `{rename_project, "~ 0.1.0"}` to rename your project back to \`PetalPro\` if you renamed it to something else.

Personally, I'd use option 3.

#### Option 1 - Copy your files into a fresh project&#x20;

*Manual and time-consuming, but surgical.*

If you haven't changed too many existing files and added mostly new ones, you could start a fresh project with the latest Petal Pro and migrate over the work you've done from the previous project. This is likely the easiest route. If you want to keep your git history, then you could try copying the `.git` folder from the previous project into the new one.

#### Option 2 - Using git branches

With this option, you maintain a “pure” Petal branch in your repository with no other modifications. Then, you merge this branch into your main app when you upgrade.

Follow the instructions [here](https://docs.saaspegasus.com/upgrading.html#using-branches-recommended).&#x20;

#### Option 3 - Rebasing

Keep a branch in sync with the PetalPro repo, and when it updates, you rebase (replay) your commits on top of it.

```bash
# clone petal_pro
git checkout -b petal_pro --track origin/main
git checkout main

# develop your codebase
touch lib/new_file
git add -A
git commit -m "Added a new file!"

# petal_pro updates
git checkout petal_pro
git pull
git checkout main
git rebase petal_pro
```

#### Option 4 - Attempt a git merge

```bash
git remote add petal_pro git@github.com:petalframework/petal_pro.git
git fetch petal_pro
git merge petal_pro/main --allow-unrelated-histories
```

**Option 5 - rsync**

* rsync -r --delete --exclude=.git \~/code/petal\_pro-1.3.0/ \~/code/your-app
* git checkout HEAD path/to/files/rsync/deleted/but/shouldnt/have (I used --delete with rsync so I'd know about files that were removed, for example, I think some of the org stuff was moved, and I don't want cruft)
* git add -p
* Use rename\_phoenix\_project.sh to rename back to your app name

#### Option 6 - Use a diffing tool like Araxis merge

Comment from a Pro user:&#x20;

The easiest way for me is to create a fresh project from the updated petal\_pro, rename it to the same name as your existing project, and then run a diff tool like Araxis merge against the root directories. As long as you have mostly added your own files and not modified the template files much it doesn't take too long. You can either merge the template changes into your existing project (better for git history) or merge your customizations into the fresh project.
