Many sites use the MediaWiki software, including wikiHow! As you can see, despite the fact that MediaWiki comes with a set of ready-to-use skins, many sites, such as wikiHow, choose to have their own skin to give the site a unique look and feel. Customizing how a MediaWiki based site looks can be achieved in many ways all involving skins. Usually, creating a new skin from scratch is not necessary for many levels of customizations. In other situations, creating a skin based on one of the already-implemented ones, such as MonoBook, then tweaking it to your needs will be more than enough. However, if you really want to dramatically change the layout of the wiki, you might need to create your own skin from the ground up. This article will guide you with doing this in a systematic, organized and easy way![1]

For the purpose of demonstration, the article will assume your new skin will be called TrialSkin. You should replace all references to "TrialSkin" with the name of your skin.

Method 1
Method 1 of 2:

Setting Up Your Skin

  1. 1
    Create the basic file structure for your new skin. This includes creating the following files and folders (all of which should be added to the skins folder of your MediaWiki installation):
    • A TrialSkin.php file - This is where you will put most of the code and define the layout of pages.
    • A TrialSkin.deps.php file - This is a standard file that most likely will contain the same code. It is created to fix a bug with PHP.
    • The trialskin directory - All other files related to your skin should go in this directory, including style-sheets and images.
    • A /skins/trialskin/main.css file which will contain the main stylesheet for the skin - [Optional, but most likely to be needed]
    • Browser specific stylesheet fixes files, such as /skins/trialskin/IE60Fixes.css - [Optional, but preferred]
  2. 2
    Add the initialization code. Replace TrialSkin with the name of your skin and trialskin with the name of your skin after turning all letters to small case.
      <?php
      // initialization code
      if( !defined('MEDIAWIKI') )
      	die("This Skin file is not a valid Entry Point.");
      require_once('includes/SkinTemplate.php');
       
      // inherit main code from SkinTemplate, set the CSS and template filter
      class SkinTrialSkin extends SkinTemplate {
      	function initPage(&$out) {
      		SkinTemplate::initPage($out);
      		$this->skinname  = 'trialskin';
      		$this->stylename = 'trialskin';
      		$this->template  = 'TrialSkinTemplate';
      	}
      }
       
      class TrialSkinTemplate extends QuickTemplate {
      	//Other code sections will be appended to this class body
      
    Advertisement
  3. 3
    Add the "Category List Fix" code. Just copy and paste the following code to the body of the template class (TrialSkinTemplate in this example), preferably after the initialization code.
      	/* hijack category functions to create a proper list */
       
      	function getCategories() {
      		$catlinks=$this->getCategoryLinks();
      		if(!empty($catlinks)) {
      			return "<ul id='catlinks'>{$catlinks}</ul>";
      		}
      	}
       
      	function getCategoryLinks() {
      		global $wgOut, $wgUser, $wgTitle, $wgUseCategoryBrowser;
      		global $wgContLang;
       
      		if(count($wgOut->mCategoryLinks) == 0)
      			return '';
       
      		$skin = $wgUser->getSkin();
       
      		# separator
      		$sep = "";
       
      		// use Unicode bidi embedding override characters,
      		// to make sure links don't smash each other up in ugly ways
      		$dir = $wgContLang->isRTL() ? 'rtl' : 'ltr';
      		$embed = "<li dir='$dir'>";
      		$pop = '</li>';
      		$t = $embed . implode ( "{$pop} {$sep} {$embed}" , $wgOut->mCategoryLinks ) . $pop;
       
      		$msg = wfMsgExt('pagecategories', array('parsemag', 'escape'), count($wgOut->mCategoryLinks));
      		$s = $skin->makeLinkObj(Title::newFromText(wfMsgForContent('pagecategorieslink')), $msg)
      			. $t;
       
      		# optional 'dmoz-like' category browser - will be shown under the list
      		# of categories an article belongs to
      		if($wgUseCategoryBrowser) {
      			$s .= '<br /><hr />';
       
      			# get a big array of the parents tree
      			$parenttree = $wgTitle->getParentCategoryTree();
      			# Skin object passed by reference because it can not be
      			# accessed under the method subfunction drawCategoryBrowser
      			$tempout = explode("\n", Skin::drawCategoryBrowser($parenttree, $this));
      			# clean out bogus first entry and sort them
      			unset($tempout[0]);
      			asort($tempout);
      			# output one per line
      			$s .= implode("<br />\n", $tempout);
      		}
       
      		return $s;
      	}
      
  4. 4
    Define the execute() function, which will be called to output the pages' contents to client browsers.
  5. 5
    Declare the global variable $wgUser in the execute() function and use its getSkin() method to obtain a $skin variable/object. You will most likely need that variable. However, if you do not need it, then there is no need to do this step. You'll find a standard example of declaring the execute() function with the most commonly used code in the "Declaration of the execute() Function" sub-section.
  6. 6
    Start adding code (both PHP and XHTML) to render pages in your wiki. Most likely, although you might need to dramatically change the layout, but you'll need to render the same set of information that normal skins do (with some alterations maybe). The most commonly added elements/components/blocks for a page are (see corresponding sub-sections for details and/or sample codes):
    • The XHTML code which opens (and eventually closes) the HTML output that will be sent to the client's browser.
    • The head element, which imports style-sheets, scripts, defines the page's meta data, and specifies the title to be displayed in the browser's title bar for the specific page being viewed.
    • The body opening tag. This tag opens the body element of the page and specifies what happens when the page loads or is double clicked if such handlers exist.
    • The site's name block.
    • The site's logo image.
    • The site's tag-line
    • Site Notice block.
    • User message notification block (if there is a need for it)
    • The user's toolbar.
    • Intrapage navigation block.
    • Search.
    • Toolbox.
    • Language links.
    • Page name.
    • Page subtitle.
    • Undelete notice.
    • Page contents.
    • Category links.
    • Page toolbar.
    • Footer.
    • Closing trail.
  7. Advertisement
Method 2
Method 2 of 2:

Adding Code to Your Pages

  1. 1
    Use this example for your Main execute() Method Code. You might remove the lines that declare $wgUser, $wgSitename and $skin if you are not going to use them.
      	function execute() {
      		// declaring global variables and getting the skin object in case you need to use them later
      		global $wgUser, $wgSitename;
      		$skin = $wgUser->getSkin();
       
      		// retrieve site name
      		$this->set('sitename', $wgSitename);
       
      		// suppress warnings to prevent notices about missing indexes in $this->data
      		wfSuppressWarnings();
      
  2. 2
    Add the Main XHTML Structure Code. This is the Oening Code - here, you instruct the skin to output the HTML tag and declare all necessary XHTML namespaces. The following code is a standard declaration that you might customize but most likely will not need to.
      ?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
      <html xmlns="<?php $this->text('xhtmldefaultnamespace') ?>" <?php 
      	foreach($this->data['xhtmlnamespaces'] as $tag => $ns) {
      		?>xmlns:<?php echo "{$tag}=\"{$ns}\" ";
      	} ?>xml:lang="<?php $this->text('lang') ?>" lang="<?php $this->text('lang') ?>" dir="<?php $this->text('dir') ?>">
      
    • The head element - here, you output the head element along with all its contents. This includes style-sheets links, client-side scripts and meta data for robots and browsers. The code included here is a standard code that you might need to modify to include any custom scripts or style-sheets to be included.
      • For this code to work as expected you'll need to have the following files (you may remove the lines importing any of these style-sheets if you don't need them):
        • /common/commonPrint.css - style-sheet for printing pages. You might change the path to this style-sheet if you don't want to use the standard print style-sheet.
        • main.css, contents.css - main style-sheets for your skin. These must be in your skin's directory (/skins/trialskin in this example)
        • handheld.css - a style-sheet to be used with hand-held devices.
        • IE50Fixes.css, IE55Fixes.css, IE60Fixes.css, IE70Fixes.css - fixes for different browsers. You may copy these files from one of the already-existing skins, most likely you'll need to change nothing on these files.
      • The last lines, starting at "/*** various MediaWiki-related scripts and styles ***/ " include user specific, page specific and site-wide specific style-sheets. If you don't support these features, just remove them all up to the <!-- Head Scripts --> comment.
      • It has been noticed that the $this->html('headscripts') call sometimes causes trouble, so if anything goes wrong try to remove it.
      • In case the code does not work for some reason, you might forget about this code altogether and write your own, including the style-sheet links, scripts, and title tag all written by your own code!
          	<head>
          		<meta http-equiv="Content-Type" content="<?php $this->text('mimetype') ?>; charset=<?php $this->text('charset') ?>" />
          		<?php $this->html('headlinks') ?>
          		<title><?php $this->text('pagetitle') ?></title>
          		<?php /*** general style sheets ***/ ?>
          		<style type="text/css" media="screen,projection">/*<![CDATA[*/
          			@import "<?php $this->text('stylepath') ?>/<?php $this->text('stylename') ?>/main.css?<?php echo $GLOBALS['wgStyleVersion'] ?>";
          			@import "<?php $this->text('stylepath') ?>/<?php $this->text('stylename') ?>/contents.css?<?php echo $GLOBALS['wgStyleVersion'] ?>";
          		/*]]>*/</style>
          		<?php /*** media-specific style sheets ***/ ?>
          		<link rel="stylesheet" type="text/css" <?php if(empty($this->data['printable']) ) { ?>media="print"<?php } ?> href="<?php $this->text('stylepath') ?>/common/commonPrint.css?<?php echo $GLOBALS['wgStyleVersion'] ?>" />
          		<link rel="stylesheet" type="text/css" media="handheld" href="<?php $this->text('stylepath') ?>/<?php $this->text('stylename') ?>/handheld.css?<?php echo $GLOBALS['wgStyleVersion'] ?>" />
          		<?php /*** browser-specific style sheets ***/ ?>
          		<!--[if lt IE 5.5000]><style type="text/css">@import "<?php $this->text('stylepath') ?>/<?php $this->text('stylename') ?>/IE50Fixes.css?<?php echo $GLOBALS['wgStyleVersion'] ?>";</style><![endif]-->
          		<!--[if IE 5.5000]><style type="text/css">@import "<?php $this->text('stylepath') ?>/<?php $this->text('stylename') ?>/IE55Fixes.css?<?php echo $GLOBALS['wgStyleVersion'] ?>";</style><![endif]-->
          		<!--[if IE 6]><style type="text/css">@import "<?php $this->text('stylepath') ?>/<?php $this->text('stylename') ?>/IE60Fixes.css?<?php echo $GLOBALS['wgStyleVersion'] ?>";</style><![endif]-->
          		<!--[if IE 7]><style type="text/css">@import "<?php $this->text('stylepath') ?>/<?php $this->text('stylename') ?>/IE70Fixes.css?<?php echo $GLOBALS['wgStyleVersion'] ?>";</style><![endif]-->
          		<?php /*** general IE fixes ***/ ?>
          		<!--[if lt IE 7]>
          		<script type="<?php $this->text('jsmimetype') ?>" src="<?php $this->text('stylepath') ?>/common/IEFixes.js?<?php echo $GLOBALS['wgStyleVersion'] ?>"></script>
          		<meta http-equiv="imagetoolbar" content="no" />
          		<![endif]-->
           
          		<?php print Skin::makeGlobalVariablesScript($this->data); ?>
           
          		<?php /*** various MediaWiki-related scripts and styles ***/ ?>
          		<script type="<?php $this->text('jsmimetype') ?>" src="<?php $this->text('stylepath') ?>/common/wikibits.js?<?php echo $GLOBALS['wgStyleVersion'] ?>"><!-- wikibits js --></script>
          <?php	if($this->data['jsvarurl']) { ?>
          		<script type="<?php $this->text('jsmimetype') ?>" src="<?php $this->text('jsvarurl') ?>"><!-- site js --></script>
          <?php	} ?>
          <?php	if($this->data['pagecss']) { ?>
          		<style type="text/css"><?php $this->html('pagecss') ?></style>
          <?php	}
          		if($this->data['usercss']) { ?>
          		<style type="text/css"><?php $this->html('usercss') ?></style>
          <?php	}
          		if($this->data['userjs']) { ?>
          		<script type="<?php $this->text('jsmimetype') ?>" src="<?php $this->text('userjs' ) ?>"></script>
          <?php	}
          		if($this->data['userjsprev']) { ?>
          		<script type="<?php $this->text('jsmimetype') ?>"><?php $this->html('userjsprev') ?></script>
          <?php	}
          		if($this->data['trackbackhtml']) print $this->data['trackbackhtml']; ?>
          		<!-- Head Scripts -->
          		<?php $this->html('headscripts') ?>
          	</head>
          
    • The body opening tag - renders the opening body tag. Most likely, you won't need to modify this unless you want to hard code the body styles into the tag.
        <!-- Body -->
        <body <?php if($this->data['body_ondblclick']) { ?>ondblclick="<?php $this->text('body_ondblclick') ?>"<?php } ?>
        	<?php if($this->data['body_onload']) { ?>onload="<?php $this->text('body_onload') ?>"<?php } ?>
        	class="mediawiki <?php $this->text('nsclass') ?> <?php $this->text('dir') ?> <?php $this->text('pageclass') ?>">
        
    • Closing trail - this is appended at the end of the file. It closes any opened tags, scripts, php code ... etc. All following code should be put before this, it should be the last lines of the skin file.
        <!-- scripts and debugging information -->
        <?php $this->html('bottomscripts'); /* JS call to runBodyOnloadHook */ ?>
        <?php $this->html('reporttime') ?>
        <?php if ( $this->data['debug'] ): ?>
        <!-- Debug output:
        <?php $this->text( 'debug' ); ?>
         
        -->
        <?php endif; ?>
        </body>
         
        </html>
        <?php
        	wfRestoreWarnings();
        	} // end of execute() method
        } // end of class
        ?>
        
  3. 3
    Use this example of common site elements' code. The use of $this->text($msg) and $this->html($msg). it will be used a lot across the skin.
    • Site's name:
        <?php echo $this->text('sitename') ?>
        
    • Site's logo image:
        	<div class="portlet" id="p-logo">
        		<a style="background-image: url(<?php $this->text('logopath') ?>);" <?php
        			?>href="<?php echo htmlspecialchars($this->data['nav_urls']['mainpage']['href'])?>"<?php
        			echo $skin->tooltipAndAccesskey('n-mainpage') ?>></a>
        	</div>
        	<script type="<?php $this->text('jsmimetype') ?>"> if (window.isMSIE55) fixalpha(); </script> <!-- IE alpha-transparency fix -->
        
    • Site's tag-line:
        <h3 id="siteSub"><?php $this->msg('tagline') ?></h3>
        
    • The site-notice block - site notice content is usually edited and added to the WikiMedia:Sitenotice message page.
        <?php if($this->data['sitenotice']) { ?><div id="siteNotice"><?php $this->html('sitenotice') ?></div><?php } ?>
        
    • User message notification block:
        <?php if($this->data['newtalk']) { ?><div class="usermessage"><?php $this->html('newtalk') ?></div><?php } ?>
        
    • Intrapage navigation block - this is optional.
        <?php if($this->data['showjumplinks']) { ?><div id="jump-to-nav"><?php $this->msg('jumpto') ?> <a href="#column-one"><?php $this->msg('jumptonavigation') ?></a>, <a href="#searchInput"><?php $this->msg('jumptosearch') ?></a></div><?php } ?>
        
  4. 4
    Incorporate common page elements' code.
    • Page name:
        <h1 class="firstHeading"><?php $this->data['displaytitle']!=""?$this->html('title'):$this->text('title') ?></h1>
        
    • Page subtitle:
        <div id="contentSub"><?php $this->html('subtitle') ?></div>
        
    • Page contents:
        <?php $this->html('bodytext') ?>
        
    • Category links:
        <?php if($this->data['catlinks']) { ?><div id="catlinks"><?php $this->html('catlinks') ?></div><?php } ?>
        
    • Footer - this code is iterative so take care while copying it!
        			<div id="footer">
        <?php
        		if($this->data['poweredbyico']) { ?>
        				<div id="f-poweredbyico"><?php $this->html('poweredbyico') ?></div>
        <?php 	}
        		if($this->data['copyrightico']) { ?>
        				<div id="f-copyrightico"><?php $this->html('copyrightico') ?></div>
        <?php	}
         
        		// generate additional footer links
        ?>
        			<ul id="f-list">
        <?php
        		$footerlinks = array(
        			'lastmod', 'viewcount', 'numberofwatchingusers', 'credits', 'copyright',
        			'privacy', 'about', 'disclaimer', 'tagline',
        		);
        		foreach( $footerlinks as $aLink ) {
        			if( isset( $this->data[$aLink] ) && $this->data[$aLink] ) {
        ?>				<li id="<?php echo$aLink?>"><?php $this->html($aLink) ?></li>
        <?php 		}
        		}
        ?>
        			</ul>
        		</div>
        
  5. 5
    Use this example of common toolbars code.
    • This renders the user's navigation links such as the user's page, talk page, logout link ... etc.
        	<div class="portlet" id="p-personal">
        		<h5><?php $this->msg('personaltools') ?></h5> <!-- User Toolbar Label/Caption [optional] -->
        		<div class="pBody">
        			<ul>
        <?php 			foreach($this->data['personal_urls'] as $key => $item) { ?>
        				<li id="pt-<?php echo Sanitizer::escapeId($key) ?>"<?php
        					if ($item['active']) { ?> class="active"<?php } ?>><a href="<?php
        				echo htmlspecialchars($item['href']) ?>"<?php echo $skin->tooltipAndAccesskey('pt-'.$key) ?><?php
        				if(!empty($item['class'])) { ?> class="<?php
        				echo htmlspecialchars($item['class']) ?>"<?php } ?>><?php
        				echo htmlspecialchars($item['text']) ?></a></li>
        <?php			} ?>
        			</ul>
        		</div>
        	</div>
        
    • Page toolbar - which includes the edit, create, discuss links along with others depending on the user's group.
        	<div id="p-cactions" class="portlet">
        		<h5><?php $this->msg('views') ?></h5> <!-- Page Toolbar Label/Caption [optional] -->
        		<div class="pBody">
        			<ul>
        	<?php			foreach($this->data['content_actions'] as $key => $tab) { ?>
        				 <li id="ca-<?php echo Sanitizer::escapeId($key) ?>"<?php
        					 	if($tab['class']) { ?> class="<?php echo htmlspecialchars($tab['class']) ?>"<?php }
        					 ?>><a href="<?php echo htmlspecialchars($tab['href']) ?>"<?php echo $skin->tooltipAndAccesskey('ca-'.$key) ?>><?php
        					 echo htmlspecialchars($tab['text']) ?></a></li>
        	<?php			 } ?>
        			</ul>
        		</div>
        	</div>
        
    • Undelete notice - if the page was deleted before and the user can undelete pages, this link should appear (if you choose to).
        <?php if($this->data['undelete']) { ?><div id="contentSub2"><?php $this->html('undelete') ?></div><?php } ?>
        
  6. 6
    Incorporate portlets (main navigation blocks).
    • Search portlet - the search box. This is a minimal implementation that only shows what needs to be outputted for the search box to work.
        	<div id="p-search" class="portlet">
        		<h5><label for="searchInput"><?php $this->msg('search') ?></label></h5>
        		<div id="searchBody" class="pBody">
        			<form action="<?php $this->text('searchaction') ?>" id="searchform"><div>
        				<input id="searchInput" name="search" type="text"<?php echo $skin->tooltipAndAccesskey('search');
        					if( isset( $this->data['search'] ) ) {
        						?> value="<?php $this->text('search') ?>"<?php } ?> />
        				<input type='submit' name="go" class="searchButton" id="searchGoButton"	value="<?php $this->msg('searcharticle') ?>"<?php echo $skin->tooltipAndAccesskey( 'search-go' ); ?> />&nbsp;
        				<input type='submit' name="fulltext" class="searchButton" id="mw-searchButton" value="<?php $this->msg('searchbutton') ?>"<?php echo $skin->tooltipAndAccesskey( 'search-fulltext' ); ?> />
        			</div></form>
        		</div>
        	</div>
        
    • Toolbox portlet:
        	<div class="portlet" id="p-tb">
        		<h5><?php $this->msg('toolbox') ?></h5>
        		<div class="pBody">
        			<ul>
        <?php
        		if($this->data['notspecialpage']) { ?>
        				<li id="t-whatlinkshere"><a href="<?php
        				echo htmlspecialchars($this->data['nav_urls']['whatlinkshere']['href'])
        				?>"<?php echo $skin->tooltipAndAccesskey('t-whatlinkshere') ?>><?php $this->msg('whatlinkshere') ?></a></li>
        <?php
        			if( $this->data['nav_urls']['recentchangeslinked'] ) { ?>
        				<li id="t-recentchangeslinked"><a href="<?php
        				echo htmlspecialchars($this->data['nav_urls']['recentchangeslinked']['href'])
        				?>"<?php echo $skin->tooltipAndAccesskey('t-recentchangeslinked') ?>><?php $this->msg('recentchangeslinked') ?></a></li>
        <?php 		}
        		}
        		if(isset($this->data['nav_urls']['trackbacklink'])) { ?>
        			<li id="t-trackbacklink"><a href="<?php
        				echo htmlspecialchars($this->data['nav_urls']['trackbacklink']['href'])
        				?>"<?php echo $skin->tooltipAndAccesskey('t-trackbacklink') ?>><?php $this->msg('trackbacklink') ?></a></li>
        <?php 	}
        		if($this->data['feeds']) { ?>
        			<li id="feedlinks"><?php foreach($this->data['feeds'] as $key => $feed) {
        					?><span id="feed-<?php echo Sanitizer::escapeId($key) ?>"><a href="<?php
        					echo htmlspecialchars($feed['href']) ?>"<?php echo $skin->tooltipAndAccesskey('feed-'.$key) ?>><?php echo htmlspecialchars($feed['text'])?></a>&nbsp;</span>
        					<?php } ?></li><?php
        		}
         
        		foreach( array('contributions', 'blockip', 'emailuser', 'upload', 'specialpages') as $special ) {
         
        			if($this->data['nav_urls'][$special]) {
        				?><li id="t-<?php echo $special ?>"><a href="<?php echo htmlspecialchars($this->data['nav_urls'][$special]['href'])
        				?>"<?php echo $skin->tooltipAndAccesskey('t-'.$special) ?>><?php $this->msg($special) ?></a></li>
        <?php		}
        		}
         
        		if(!empty($this->data['nav_urls']['print']['href'])) { ?>
        				<li id="t-print"><a href="<?php echo htmlspecialchars($this->data['nav_urls']['print']['href'])
        				?>"<?php echo $skin->tooltipAndAccesskey('t-print') ?>><?php $this->msg('printableversion') ?></a></li><?php
        		}
         
        		if(!empty($this->data['nav_urls']['permalink']['href'])) { ?>
        				<li id="t-permalink"><a href="<?php echo htmlspecialchars($this->data['nav_urls']['permalink']['href'])
        				?>"<?php echo $skin->tooltipAndAccesskey('t-permalink') ?>><?php $this->msg('permalink') ?></a></li><?php
        		} elseif ($this->data['nav_urls']['permalink']['href'] === '') { ?>
        				<li id="t-ispermalink"<?php echo $skin->tooltip('t-ispermalink') ?>><?php $this->msg('permalink') ?></li><?php
        		}
         
        		wfRunHooks( 'TrialSkinTemplateToolboxEnd', array( &$this ) );
        ?>
        			</ul>
        		</div>
        	</div>
        
    • Language links:
        <?php if( $this->data['language_urls'] ) { ?>
        	<div id="p-lang" class="portlet">
        		<h5><?php $this->msg('otherlanguages') ?></h5>
        		<div class="pBody">
        			<ul>
        <?php		foreach($this->data['language_urls'] as $langlink) { ?>
        				<li class="<?php echo htmlspecialchars($langlink['class'])?>"><?php
        				?><a href="<?php echo htmlspecialchars($langlink['href']) ?>"><?php echo $langlink['text'] ?></a></li>
        <?php		} ?>
        			</ul>
        		</div>
        	</div>
        <?php } ?>
        
  7. Advertisement

Warnings

  • Always backup your MediaWiki database, installation directory and any related items before attempting to create or change your new skin.
    ⧼thumbs_response⧽
  • This procedure should be performed by someone (or at least under the supervision of someone) with moderate knowledge of the MediaWiki software and the PHP language. Errors in code might cause unexpected results and bugs.
    ⧼thumbs_response⧽
Advertisement

About This Article

wikiHow is a “wiki,” similar to Wikipedia, which means that many of our articles are co-written by multiple authors. To create this article, 18 people, some anonymous, worked to edit and improve it over time. This article has been viewed 62,318 times.
How helpful is this?
Co-authors: 18
Updated: November 3, 2022
Views: 62,318
Categories: Featured Articles | Wikis
Advertisement