Try Tuts+ Premium, Get Cash Back!
Magento for Designers: Part 5

Magento for Designers: Part 5

Tutorial Details
  • Technology: Magento
  • Difficulty: Intermediate
  • Completion Time: 1 Hour
This entry is part 5 of 8 in the Magento for Designers Session
« PreviousNext »

Magento is a stunningly powerful e-commerce platform. In this miniseries, we’ll learn how to get started with the platform, getting to know the terminologies, setting up a store and all related aspects of it and finally learn how to customize it to make it our very own.

In this fifth part, we’ll be building one of the main views of our store – the product information page. Excited? Let’s get started!


The Full Series


A Quick Recap

In the last part, we laid down the framework for the theme by building the repeating portions of the theme and essentially defining the general layout of the theme.

We also took a practical look at how theming in Magento works by going through how the layout is constructed, how the blocks work and how all the different pieces of the puzzle fit in together.


What are We Building Today?

Today, we’ll build the individual product view page. Just like before, the source files, both the front end and back end, are included. You can use it to see how the page looks but outside of that, the theme should look broken since, you know, we haven’t touched the rest of the views yet. So till we build the rest, try to not venture out of our sandbox.


Goals for the Page

Our goal for this specific page is relatively simple. We want a no-nonsense page that does only the essentials. Thus, I’ve drawn up a short list of elements that I think it needs:

  • The product’s title: Fairly obvious
  • Ability to show an image of the product
  • A quick and full overview
  • Availability and price of the product and finally
  • An add to cart button to place it in the cart

That’s it. I want to keep it as simple as possible and thus opted to not over do it. Once you’ve learnt the general principles, feel free to add as many whizbang features as possible.


The Basic Look

The page basically has to look like so:


Step 1 – The HTML

We’ll first look at the HTML for the content part alone. I’m assuming you’re fairly fluent in HTML and CSS so I’ll skip to the fairly important parts.

<div id="content" class="product">
<div id="main-product-image"><img src="images/primg.gif" /></div>

<div id="product-details">
<div id="product-availability">Availability <span class="available">In stock</span></div>
<div id="product-price">Price <span>$29.00</span></div>
<a class="button" href="#">Add to cart</a>
</div>

<h1>Photoshop to HTML</h1>

<h2>Quick Overview</h2>
<p class="quick-overview">
</p>

<h2>Product Description</h2>
<div class="product-description">

</div>

First up, notice that I’ve wrapped the product image with a div to make it easier to add features in the future. Suppose you want to add a quick caption to the displayed image in the future, this way will let us add this a lot more quicker.

We have another div element holding the availability and pricing information along with the add to cart button. We’ll be sprucing it up with a little CSS3 in a bit.

The rest of the HTML is very straightforward. The title resides in a h1 section while the individual section headings take up h2. The quick overview is nested in a paragraph while the full overview takes up a div.

We can move on to the styling part now.


Step 2 – The CSS

/* Product page */

#main-product-image {
	margin: 0 20px 10px 0;
	padding: 10px;
	float: left;
	border: 1px solid #E1E1E1;
	background: #F3F3F3;
}

#product-details {
	width: 180px;
	padding: 10px;
	float: right;
	border: 1px solid #E1E1E1;
	background: #F3F3F3;
	margin: 0 0 0 20px;
}

#product-availability span.available, #product-price span {
	color: #7db000;
	float: right;
}

.button {
	margin: 10px auto;
	display: block;
	width: 140px;
	padding: 5px 10px;
	text-align: center;
	text-decoration: none;
	color: #555;
	border: 1px solid #ccc;
	font-size: 18px;
	background: #ddd;
	border-radius: 12px;
	-webkit-border-radius: 12px;
	-moz-border-radius: 12px;
	box-shadow: 1px 1px 2px rgba(0,0,0,.5);
	-webkit-box-shadow: 1px 1px 2px rgba(0,0,0,.5);
	-moz-box-shadow: 1px 1px 2px rgba(0,0,0,.5);
	text-shadow: #fff 0px 1px 1px;
	background: -webkit-gradient(linear, left top, left bottom, from(#eeeeee), to(#cccccc));
	background: -moz-linear-gradient(top,  #eeeeee,  #cccccc);

	}

.button:hover {
	background: #014464;
 	background: -webkit-gradient(linear, left top, left bottom, from(#cccccc), to(#999999));
	background: -moz-linear-gradient(top,  #cccccc,  #999999);
	color: #000;
	}

.button:active {
	-moz-box-shadow: 0 2px 6px black;
	-webkit-box-shadow: 0 2px 6px black;
	}

Nothing fancy here. Very basic CSS to place the elements in position.

I’ve also used a bit of CSS3 to make the buttons a little better looking.


Step 3 – Creating our catalog.xml File

As I mentioned in the earlier part, each module gets its own XML file to dictate what items to include and the general layout of the page. The page we’re building today relies on a file called catalog.xml to define its contents and structure.

This file should be present in the layout folder so let’s create an XML file and name it catalog.

The complete file for today looks like so. I’ll explain each bit part by part below.

<?xml version="1.0"?>
<layout version="0.1.0">
    <catalog_product_view translate="label">
        <label>Catalog Product View (Any)</label>
        <!-- Mage_Catalog -->
        <reference name="root">
            <action method="setTemplate"><template>page/1column.phtml</template></action>
        </reference>
		<reference name="head">
            <action method="addCss"><stylesheet>css/product.css</stylesheet></action>
        </reference>
        <reference name="content">
            <block type="catalog/product_view" name="product.info" template="catalog/product/view.phtml">
               <block type="catalog/product_view_media" name="product.info.media" as="media" template="catalog/product/view/media.phtml"/>
               <block type="catalog/product_view_description" name="product.description" as="description" template="catalog/product/view/description.phtml"/>
               <block type="catalog/product_view_type_simple" name="product.info.simple" as="product_type_data" template="catalog/product/view/type/simple.phtml"/>
               <block type="catalog/product_view" name="product.info.addtocart" as="addtocart" template="catalog/product/view/addtocart.phtml"/>
            </block>
        </reference>
    </catalog_product_view>
</layout>

Disregard the initial XML and layout version declarations. They’re of no significance to us now.

<catalog_product_view translate="label">

First, we let the system know that we’re intending to modify the product view part of the system. This is because catalog.xml houses the layout for a number of other views and so it’s imperative that we specify which view we intend to modify.

<reference name="root">
            <action method="setTemplate"><template>page/1column.phtml</template></action>
</reference>

Now, we tell Magento to load up the 1column.phtml file as the main master template for this view. This is because each individual view can use any predefined structure. For example, your home page could use a very complex custom structure, your product page a dual column and your search page a single column layout.

If nothing is specified, it’ll load up the default template mentioned in page.xml. Since we’re using it for everything else, this part is redundant but when you’re modifying this template for your personal use, editing the file’s name is a lot easier than adding chunks of XML to the layout file.

<reference name="head">
    <action method="addCss"><stylesheet>css/product.css</stylesheet></action>
</reference>

And now we come across one of the niftier parts of Magento. Yes, we can throw all our view specific CSS into one giant CSS file but we aren’t cavemen, are we? Cries of multiple HTTP requests aside, this method lets us streamline our CSS better.

First we acquire a reference to the head section of the file and then insert our page specific content into it. Here, I’m inserting a file called product.css which contains all the page specific CSS we looked at above.

Note that you aren’t limited to CSS. Including JS and other assets is possible too.

<block type="catalog/product_view" name="product.info" template="catalog/product/view.phtml">

We now ask Magento to use a specific template for the content portion of the page

 <block type="catalog/product_view_media" name="product.info.media" as="media" template="catalog/product/view/media.phtml"/>
 <block type="catalog/product_view_description" name="product.description" as="description" template="catalog/product/view/description.phtml"/>
 <block type="catalog/product_view_type_simple" name="product.info.simple" as="product_type_data" template="catalog/product/view/type/simple.phtml"/>
 <block type="catalog/product_view" name="product.info.addtocart" as="addtocart" template="catalog/product/view/addtocart.phtml"/>

This block defines all the individual blocks inside the main content block. Essentially, we use individual templates for displaying the product’s image, overview and description, availability/price and finally the add to cart functionality.

And with this, our base catalog.xml file is complete.


Step 4 – Creating our Main Template

Ok, now that we’ve specified our layout we can move on to creating the catalog/product/view.phtml file that we specified as the main template for the content section in the XML earlier.

This file is slightly different from the skeleton template we created in the last part because we’ll be adding some small things directly instead of going through the template path to avoid bloat along with a smidgen of API calls to help us.

<?php
    $_helper = $this->helper('catalog/output');
    $_product = $this->getProduct();
?>

<form action="<?php echo $this->getAddToCartUrl($_product) ?>" method="post" id="product_addtocart_form"<?php if($_product->getOptions()): ?> enctype="multipart/form-data"<?php endif; ?>>
        <div class="no-display">
            <input type="hidden" name="product" value="<?php echo $_product->getId() ?>" />
            <input type="hidden" name="related_product" id="related-products-field" value="" />
<div id="main-product-image"><?php echo $this->getChildHtml('media') ?></div>

<div id="product-details">
<?php echo $this->getChildHtml('product_type_data') ?>
<?php echo $this->getChildHtml('addtocart') ?>
</div>

<h1><?php echo $_helper->productAttribute($_product, $_product->getName(), 'name') ?></h1>

<?php if ($_product->getShortDescription()):?>
                    <h2><?php echo $this->__('Quick Overview') ?></h2>
                    <p class="quick-overview"><?php echo $_helper->productAttribute($_product, nl2br($_product->getShortDescription()), 'short_description') ?></p>
<?php endif;?>

<?php echo $this->getChildHtml('description') ?>
</form>
</div>

If you take a quick look, you’ll notice that we’re making a number of getChildHtml calls to acquire that blocks content. These work just like as expected and the contents of these contents will be covered a little later below.

<?php
    $_helper = $this->helper('catalog/output');
    $_product = $this->getProduct();
?>

At the moment, we don’t need to know what this means. In layman’s terms though, we’re essentially asking Magento for this specific product’s store information so we can process it and then display it on the page.

<form action="<?php echo $this->getAddToCartUrl($_product) ?>" method="post" id="product_addtocart_form"<?php if($_product->getOptions()): ?> enctype="multipart/form-data"<?php endif; ?>>

Here we use one of Magento’s API methods to dynamically generate the URL the form needs to post to.

<h1><?php echo $_helper->productAttribute($_product, $_product->getName(), 'name') ?></h1>

We use another of Magento’s methods to acquire the product’s title directly.

<?php if ($_product->getShortDescription()):?>
                    <h2><?php echo $this->__('Quick Overview') ?></h2>
                    <p class="quick-overview"><?php echo $_helper->productAttribute($_product, nl2br($_product->getShortDescription()), 'short_description') ?></p>
<?php endif;?>

And again, since the quick overview is going to be just a sentence or two, I’m opting to import it directly instead of using a template. We use the same function we used to acquire the title.


Step 5 – Creating the Templates for our Blocks

With all the main parts done, we can concentrate on the individual blocks now. Now that we’ve already dealt with this when constructing the main template, this should be a lot easier now.

We’ll tackle each in order of appearance in our code:

Product image

getChildHtml(‘media’) maps directly to catalog/product/view/media.phtml. Our file looks like so:

<?php
    $_product = $this->getProduct();
    $_helper = $this->helper('catalog/output');
?>

    <?php
        $_img = '<img id="image" src="'.$this->helper('catalog/image')->init($_product, 'image').'" alt="'.$this->htmlEscape($this->getImageLabel()).'" title="'.$this->htmlEscape($this->getImageLabel()).'" />';
        echo $_helper->productAttribute($_product, $_img, 'image');
?>

Some simple PHP code. We use the helper methods to acquire the product’s image and then render it on screen.

Availability/Price

getChildHtml(‘product_type_data’) maps directly to catalog/product/view/type/simple.phtml. Our file looks like so:

<?php $_product = $this->getProduct() ?>
<div id="product-availability">Availability 
<?php if($_product->isSaleable()): ?>
    <span class="available"><?php echo $this->__('In stock') ?></span>
<?php else: ?>
    <span class="unavailable"><?php echo $this->__('Out of stock') ?></span>
<?php endif; ?>
</div>
<div id="product-price">Price <span><?php echo $this->getPriceHtml($_product) ?></span></div>

We first check whether the item is available or not and then output the required HTML. Acquiring the price of the product is a simple method call away!

Add to cart

getChildHtml(‘addtocart’) maps directly to catalog/product/view/addtocart.phtml. Our file looks like so:

<?php $_product = $this->getProduct() ?>

<?php if($_product->isSaleable()): ?>
        <button title="<?php echo $this->__('Add to Cart') ?>" class="button btn-cart"><?php echo $this->__('Add to Cart') ?></button>
<?php endif; ?>

As is logical, we check whether an item is up for sale before we output the required HTML. It’s a simple button as is apparent.

Product Description

getChildHtml(‘description’) maps directly to catalog/product/view/description.phtml. Our file looks like so:

<?php $_description = $this->getProduct()->getDescription(); ?>
<?php if ($_description): ?>
        <h2>Product Description</h2>
		<div class="product-description"><?php echo $this->helper('catalog/output')->productAttribute($this->getProduct(), nl2br($_description), 'description') ?></div>
<?php endif; ?>

Similar to how we included the quick overview, we use Magento’s inbuilt methods to acquire the necessary information. We do check for the description’s existence before we render it.

In case you’re curious, I typically tend to include the description separately via templates mostly because in production templates you’ll almost always be post procession the description in some way. In those scenarios, it’s easier to split this logic off onto its own template. A quick overview, on the other hand, are usually quite small and thus are included directly.


What We’ll be Building in the Next Part

.. is completely up to you. There are quite a number of views you could design but it’s rather presumptuous of me to pick one. Thus I’m asking you, the reader, to suggest a view to cover in the next part through a comment in the comments section below. Don’t forget to tell me which one to cover next!


The Last Word

And we are done! Today, we created the first view of our custom Magento theme, the product view along with looking a how Magento lets us add page specific assets and content. Hopefully this has been useful to you and you found it interesting. Since this is a rather new topic for a lot of readers I’ll be closely watching the comments section so chime in there if you’re having any doubts.

Questions? Nice things to say? Criticisms? Hit the comments section and leave me a comment. Happy coding!

Siddharth is Siddharth on Codecanyon
Tags: magento
Note: Want to add some source code? Type <pre><code> before it and </code></pre> after it. Find out more
  • John

    I would love to see some banners on the home page or sidebar, integrated with the the back end maybe. Like a rotating splash image advertising categories, or special products, or sales. Would also like to see how to integrate that so the client can upload the images, and set up new banners etc.

    Maybe its a little advanced right now, but I think it would help a lot of the designers here.

    • John

      Great series by the way, perfect timing!

      • http://www.sz-media.org Sz-Media.org

        Yes, i agree :D nettuts can read our minds and bring tutorials to the problems we are stucked just in time. Its about the fifth time they help me^^

    • http://www.quizzpot.com Crysfel

      yeah, me too! I’m working in a store where I want to add some banners in the home page, look what I have:

      http://magento.crysfel.com/

      I have created a ‘Banner Image’ custom attribute and Im trying to get the URL for the image uploaded with the product. After I created a new attribute, added it to the default attribute set, and assigned an image to it, I am able to see the media image attribute coming back in the product’s attribute set. however I can’t get the URL of the uploaded image in the front page, right now I’m just displaying the default image of the product but I’d like to display the “Banner image”.

    • http://www.ssiddharth.com Siddharth
      Author

      Duly noted. I’ll cover the home page in the next part.

      Thanks for reading!

  • http://www.sladewebsolutions.com Thomas

    Great tutorial!

  • http://www.graphicom.ca Guillaume

    This series is getting better and better. I don’t think there is that kind of Magento tutorial elsewhere. Keep up the good work!

  • C-64

    Excellent, simple and useful. Thank you.

  • Maurizio

    I agree I’d like to see banners integrated with the back end.
    Also I think a part about security issues might be very interesting.

    Great series let me add!

  • http://www.ate5.com Jordan Walker

    That is an excellent tutorial for magento ecommerce theme development.

  • Levan

    Awesome TUT as always…

    I’d love to see shopping cart view tutorial, as almost all mage shopping carts look identical, it would be nice to layout something unique…

  • http://pixelcoder.co.uk Alistair

    i’d like to see whatever view you chose to do recorded in a screencast. Great posts but hard to quickly digest. Maybe i’m lazy, only time get to view Nettuts is late at night in bed.

    Keep up the find work.

  • http://www.newoutlet.com/ Wai Phyo Han

    I have been waiting for a magento tutorial like this. thanks!

  • http://www.bigcolors.com Bigcolors

    Excellent post. Really love that you have taken the time to give designers this information!

  • http://www.breevmedia.com Frank Martin

    Great work, it’s hard to find good quality tutorials for Magento but this one is definitely worth a bookmark!

  • http://kuzvac.ru kuzvac

    Awesome! Great tutorial.

  • d.williams

    Maybe a little early for that this… but I would love to see some info on how to create and install a custom module. Maybe something like a module that will do something simple like display a random product “quick view” or something more complicated like creating the ability to apply a shipping cost on an item-by-item basis (couldn’t do this about six months ago when I was playing around with Magento).

    I am enjoying these Magento tutorials!

    • http://www.ssiddharth.com Siddharth
      Author

      I’ll probably cover custom modules and such down the road.

      Thanks for reading!

      • http://cmsigniter.com/ damu

        Looking forward to read your more posts on magento. Gr8 job Siddharth.

  • janice

    thanks for this series of tutorials, there is surprisingly very little in the way of Magento tutorials like this one…cheers

  • http://www.strafecreative.co.uk Web Design Nottingham

    This is a great series of blog posts, working my way through them! Magento is very in depth and it is nice to read through these and learn a little more each time! Great work so far!

  • http://www.behance.net/cre8vmedia/frame Adedoyin Kassem

    Well this is quite an interesting tutorial on this subject but I think instead of delving into the individual page from where you stopped in the series (Part 4: Building the Theme), you should have done some work on the Landing page (Home page).
    Maybe, how to display a couple of items on the page. Why I am suggest this is, after the last tutorial someone I referred to it said he would really like to know how to manipulate his homepage. The person also specified that the homepage was the most important part of the shop development for him (and I think I agree…). So you may want to look into this for a possible scope of your next tutorial on this serie.

    • http://www.ssiddharth.com Siddharth
      Author

      The next part is going to cover the home/landing page as requested by you and a ton of other readers.

      Thanks for reading!

  • http://mdeepu1@gmail.com Deepz

    HI,

    Its awesome one,i really lacking some basic knowledge in Magento.Please do notes abt Profiler and Also debugging.I wish this tut..rockz.

  • http://www.mohdesign.de moh

    I think, a tutorial for landing pages would be really great!

  • http://www.previousdesign.com Darpan

    wow, Awesome!
    Great tutorial
    You are a superman

  • http://dnacouturela.com Daniel

    Maybe you can show us how to integrate a 3rd party CMS with the perks of Magento, such as adding an item to cart without using Magento’s template system.

    Thanks for the great tut!

    Dan

  • James King

    What I find lacking in everything about Magento is, for instance, in step one how did you know the product page was called catalog_product_view and what does translate=”label” mean? Is there documentation somewhere that lists these values and what they mean?

    Another is page/1column.phtml

    Is there a list of all possible methods for action and what they do? Or is it all trial and error?

  • Istvan

    Great job. I’m waiting to come out how to manipulate the home page.

  • http://ooopx.net Inerds

    Great series of articles. I think it would be great if you would also include about using custom attributes and attribute sets and how it can be included in the templates. May be in a new tab or somewhere else.

    • http://www.ecommercesteakhouse.com Robert

      I too would like to learn more about displaying custom attributes on category/product pages, especially the “media image” attribute type. Thanks for the Magento series, keep up the great work.

  • http://www.measureddesigns.com Andrew Taylor

    A list of template and store directives would be helpful in the next post.

  • Darko

    well done

  • http://www.ecommercesteakhouse.com Robert

    Great Magento Tutorials! For future posts on Magento, I think as a designer, it would be nice to learn how to implement customized category menu navigation, implement fancy jquery effects seen on popular ecommerce sites like “quick view” on category pages, or drop down mini shopping cart in the header, image switching on product pages, jquery image zoom effects. Sorry if that was alot of requests, but Magento is awesome and there is just so much I still want to do with it. Look forward to more Magento tutorials. Thanks.

  • http://google.com ebonz

    God thanx for this tut. Can’t wait for the next series–Home Page.

  • http://onlinestationers.com Arun

    Hi,

    Please please…Can you do a tutorial on how we can do the homepage look & Feel customizations…That would be really helpful. I have been breaking my head on this for donkey’s years…You 5 tutorials are going to be very useful..but right now this is what I am looking for..

    -Arun

  • http://www.youngstream.net/ Youngstream

    Thanks for the great series, helped me getting up and running.
    Waiting for more. =)

  • chinkton

    Hello,

    Great series.

    One thing that has been bothering me for a while is how to change the image based upon color (attribute selection) with configurable products.

    There’s a number of solutions out there e.g: http://inchoo.net/ecommerce/magento/create-a-color-switcher-in-magento/ and http://www.magentocommerce.com/wiki/4_-_themes_and_template_customization/catalog/change_product_image_on_view_page_to_associated_product_s_image?do=show

    But, no of them seem to work for 1.4. I’m sure this would be simple for siddharth to sort.

    Any clues?

    • bluepanties

      Did you ever find a solution to this as I am unable to get this to work either?

  • http://elliscreative.co.uk Matthew Ellis

    The actual docs for Magento really suck! This series has been very helpful.

    Can anyone tell me how to remove style.css from being imported in the head? It seems to load by default – even though I’m calling in a custom CSS file from my Layout XML file, like this:

    css/local.css

    • http://elliscreative.co.uk Matthew Ellis

      Ah! Code got zapped!

      action method = “addCSS” > custom.css < ect…

  • thegreat

    Great post …

    It really helpful post. keep it up i am waiting the next series of your post related to module ….

  • http://neerajkumar.name/ Neeraj Kumar

    Hi Sidd,

    These tutes are really nice and very helpful. Thanks for devoting your time.

    I have a question though. It’s a beginners question.

    I couldn’t understand the flow of rendering view in magento. I mean, Which is parsed first? XML or phtml files? and i don’t understand the use of XML files, cause what i could understand is that XML files are mirroring the phtml files….

    i am very confused and after asking this question i think i got more confused :P

    anyways can you point me to some good tutorial explaining xml, phtml concepts in “plain english”.

    • http://www.neerajkumar.name Neeraj Kumar

      nevermind… i am getting a hold of it now…

      It’s really confusing at first, but in the end… it’s just pure sweetness… :) conclusion? if you want to learn magento, then straight away jump into the coding part… (it working for me atleast)

      thanks for these tutorials.

  • http://www.twitterevolutions.com/ Ognjen Knaus

    Hi, thanks for such great tutorials!

    Can you maybe show us what need to be added to catalog.xml and php file in order to display reviews *just reviews) on a product page so users can comments.
    Also is there a way I can display just text withouth the raitng stuff? I want to use it just so users can comment on a specific products.

    thanks!

  • http://bomolasses.com Sugarcane

    Excellent tutorial so far! When can expect the next installments?

  • Mike

    One thing that truly bothers me about the Tuts network of sites is when series like this just die off with no continuation, there really should be some kind of agreement made with authors who produce series like this that they have to complete it to some agreed upon standard, maybe plan out the series in advance so people know when it’s ending instead of just letting helpful series fade away. Paying to be a member of the sites has been helpful but I’d like to see these series have better guidelines in the future.

  • http://techsloution4u.com/ Maidul

    This is what i needed!Please continue the series.Thanks!!

  • http://xhtmlandcsshelp.blogspot.com/ Anjan

    How to get product details from Product Sku

  • http://www.iconshub.com Iconshub

    Its really very helpful post.Thanks for this important infomation.

  • http://www.madhursangam.com ravi

    Very Good article

    Thanks
    JeevanSathi

  • jyoti saini

    Great tutorial!!!!!!!!!!!!!!

  • http://psdtomagento.com Tuba

    wonderful tutorial to start magento designing.

  • Drew

    Hi Sid,

    Fantastic tutorial, I’ve really learnt a lot from this series!

    I was just wondering if the content across this series is relevant for 2012?
    Has much changed since 2010?

    Once again, thank you!

  • http://www.webleydevelopment.com Matthew Webley

    Hi, thanks for the tutorials. great introduction.
    I was wondering why it’s not picking up my basic.html file.. should this be happening?
    its picking up my css file okay but its displaying something else, not the basic.html file.

    thanks.

  • Amr Qudah

    thanks for the tutorials. great introduction.

  • Muhammad Ali

    Thanks, this is really a nice tutorial. Great introduction. I would suggest to write a tutorial on 3 column layout.
    By this beginners will know how to create sidebars and they would be able how to customize according to their own needs.

  • Linish

    excellent tutorial