Python fir tree maker I've made a code that does exactly what https://sapin.herokuapp.com/?n=5 would do.
Here's my code ;
import sys

def firtree(tree_size):
    fir = []
    width = 1
    minus = 2
    foot_width = 1
    for i in range(1,tree_size+1):
        for j in range(1,i+4):
            fir.append(&quot;*&quot;*width)
            width = width + 2
        if i % 2 == 0:
            minus += 1
        width -= minus
        if i % 2 == 0:
            foot_width += 2
    fir = [&quot; &quot;*(int((len(fir[-1]))/2)-int(len(i)/2))+i for i in fir]
    for i in fir:
        print(i)
    for i in range(1,tree_size+1):
        print(&quot; &quot;*int((len(fir[-1]))/2-int(foot_width/2))+&quot;|&quot;*foot_width)

size = int(sys.argv[1])
firtree(size)

How can I improve it ?
Use comments to guide the reader through the major phases of the algorithm.
Imagine returning to this code to fix a bug or add a feature. Simple comments
can help you zero in on the needed location to do that work.
Centralize the creation of literal parameters (see space, wood, branch).
This makes it easy to quickly change stylistic details.
Let you code breath: add space around operators. This can help a lot with
readability and thus maintainability.
As a general rule (there are exceptions), don't reuse variable names for
different concepts. The first part of the function uses fir for uncentered
rows. Then you replace that fir with one having centered rows. Prioritize
code clarity by using different variable names. The same point can be made when
you create the trunk: do it in another variable.
Create convenience variables to eliminate repeated calculations, as shown in
max_width.
Invest more in laying out the code for readability, as shown in the list
comprehenion to create centered.
Take advantage of floor-division if you want an integer result (//).
When iterating i and j are conventional variable names when dealing with
indexes. Your code follows that convention. But it also uses i when iterating
over other things (like the rows). Less ambiguous is a short name that has
a conceptual connection to the thing you are iterating over: for example, if
iterating over rows, use r as the loop variable.
Separate computation from reporting. This is better for debugging and
automated testing. The firtree() function is where computation happens.
Do the printing at a higher level in the call stack.
Put orchestration code inside a function, as shown in main(). Also
better for testing and debugging.
Here's your code with those suggestions applied. Note this this edit does not
fix the bug in your code related to the width of the next top section (width
of next section is supposed to be width of previous section minus 2).
import sys

def main(args):
    size = int(args[0])
    fir = firtree(size)
    for row in fir:
        print(row)

def firtree(tree_size):
    # Setup.
    width = 1
    minus = 2
    foot_width = 1
    space = ' '
    wood = '|'
    branch = '*'

    # Create the top of the tree, first as uncentered rows.
    rows = []
    for i in range(1, tree_size + 1):
        for j in range(1, i + 4):
            rows.append(branch * width)
            width = width + 2
        if i % 2 == 0:
            minus += 1
        width -= minus
        if i % 2 == 0:
            foot_width += 2

    # Convert the rows to centered rows.
    max_width = len(rows[-1])
    centered = [
        space * (max_width // 2 - len(r) // 2) + r
        for r in rows
    ]

    # Build the trunk.
    trunk = [
        space * int(max_width / 2 - foot_width // 2) + wood * foot_width
        for i in range(1, tree_size + 1)
    ]

    # Profit.
    return centered + trunk

if __name__ == '__main__':
    main(sys.argv[1:])

But those types of suggestions only help so much. At the end of the day, this
kind of code is annoying because its so tediously algorithmic: too much math,
too much fine-grained list-indexing, etc. An easier way to solve the problem
can be found taking fuller advantage of an insight in your current code: focus
first on making uncentered rows, like this:
*
***
*****
*******
*******
*********
***********
*************
***************
|||
|||

Then let Python format-strings do all of the grubby work of centering the rows.
We can also improve code readability a bit more by delegating sub-calculations
to helper functions, each doing a very small thing. That approach keeps
the primary function fairly readable.
def firtree(tree_size):
    # Setup.
    wood = '|'
    branch = '*'

    # Rows for the tree branches, which are organized in sections.
    top = []
    row_len = 1
    for n_rows in range(4, 4 + tree_size):
        sect, row_len = section(n_rows, row_len, branch)
        top.extend(sect)

    # Rows for the tree trunk.
    is_even = not tree_size % 2
    width = tree_size + is_even
    height = tree_size
    trunk = [wood * width for _ in range(height)]

    # Return those rows, but centered.
    return centered(top + trunk)

def section(n_rows, init_len, marker):
    # Returns a (ROWS, NEXT_LEN) tuple for a tree section.
    # Handling the next-length calculation here, where it happens to be
    # easy to do, helps keep the primary function simpler.
    end_len = init_len + n_rows * 2
    next_len = end_len - 4
    rows = [marker * n for n in range(init_len, end_len, 2)]
    return (rows, next_len)

def centered(rows):
    # Takes rows. Returns centered rows.
    fmt = '{:^{}}'
    width = max(len(r) for r in rows)
    return [fmt.format(r, width) for r in rows]