<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Codality &#187; CMS UX</title>
	<atom:link href="http://blog.najmanowicz.com/category/software-development/best-practices/cms-ux/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.najmanowicz.com</link>
	<description>Code and Effect - solving problem with just enough amount of code - by Adam Najmanowicz</description>
	<lastBuildDate>Mon, 23 Jan 2012 16:06:30 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Continuous deployment in Sitecore with PowerShell</title>
		<link>http://blog.najmanowicz.com/2011/12/19/continuous-deployment-in-sitecore-with-powershell/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=continuous-deployment-in-sitecore-with-powershell</link>
		<comments>http://blog.najmanowicz.com/2011/12/19/continuous-deployment-in-sitecore-with-powershell/#comments</comments>
		<pubDate>Mon, 19 Dec 2011 11:28:03 +0000</pubDate>
		<dc:creator>Adam Najmanowicz</dc:creator>
				<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[Best Practices]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[CMS UX]]></category>
		<category><![CDATA[Code Samples]]></category>
		<category><![CDATA[Continuous Deployment]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Sitecore]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[Web applications]]></category>

		<guid isPermaLink="false">http://blog.najmanowicz.com/?p=464</guid>
		<description><![CDATA[A few days back a budy from our Sitecore team has alerted me to this interesting question on StackOverflow which asks for automation of content promotion from one Sitecore instance to another. He suggested &#8211; and rightly so – that the PowerShell Console could be used in that scenario. While this was always possible by [...]]]></description>
			<content:encoded><![CDATA[<p>A few days back a <a href="http://stackoverflow.com/users/3205/skolima" target="_blank">budy</a> from our Sitecore team has alerted me to this interesting question on <a href="http://stackoverflow.com/questions/8414482/is-it-possible-to-build-a-sitecore-data-package-from-command-line-or-outside-of" target="_blank">StackOverflow</a> which asks for automation of content promotion from one Sitecore instance to another. He suggested &#8211; and rightly so – that the <a href="http://trac.sitecore.net/SitecorePowershellConsole" target="_blank">PowerShell Console</a> could be used in that scenario. While this was always possible by simply writing it as a PowerShell code the latest version of the console added a few commandlets making building packages much easier.</p>
<p>The easiest approach is to build the package visually in the package designer, save it and then simply use the console to read it and generate the installation zip like:</p>
<pre class="ps1">get-package &quot;powershell console.xml&quot; `
  | Export-Package -FileName &quot;PowerShell Console.zip&quot; <b>-Zip</b></pre>
<p>That’s fine in most cases but if you have some more complex scenarios or want to generate some custom packages – you might want to generate packages directly in PowerShell. </p>
<p>To Create a Package you simply use:</p>
<pre class="ps1">$package = new-package &quot;Test Package&quot;;</pre>
<p>Now that you have that package you might want to add some files and items to it.</p>
<p>Let&#8217;s add for example our item templates by querying the master database and creating a dynamic item source: </p>
<pre class="ps1">$TemplatesSource = get-childitem &quot;master:/templates/Cognifide&quot; `
  | New-ItemSource &quot;Cognifide Templates&quot;;</pre>
<p>And subsequently add it to our new package: </p>
<pre class="ps1">$package.Sources.Add($TemplatesSource);</pre>
<p>While that by itself is fairly useful, the really cool part is that you have a full flexibility of PowerShell at your disposal when you create a source with static items. Let’s say you want to add all items of template “Article Template” that reside anywhere under your “home” node … now that would require quite a bit of clicking in the Package Designer, but is trivial with the PowerShell Console:</p>
<pre class="ps1">$ArticlesSource = get-childitem master:/content/home/about-us/* -recurse `
  | where-object { $_.TemplateName -match &quot;ArticleTemplate&quot; } `
  | New-ExplicitItemSource &quot;Cognifide Articles&quot;;

$package.Sources.Add($ArticlesSource);</pre>
<p>You can specify any automation or filter you can think of to your <strong>Get-ChildItem</strong>, and you really don’t have to skimp on the number of data sources – after all you can re-generate your package at any time!</p>
<p>Similarly you can do this to the files on disk. Let’s say – you want to add all .aspx, .ascx and .ashx files, just to make sure your deployment features all the latest code and for the sake of this example let’s assume your UI elements are located in the <em>Layouts</em> folder under your web application:</p>
<pre class="ps1">$LayoutsPath = $AppPath+&quot;layouts\*&quot;
$Layouts = get-childitem $LayoutsPath -include &quot;*.as?x&quot; -recurse -force `
  | New-ExplicitFileSource &quot;My Layouts&quot;;
$package.Sources.Add($Layouts);</pre>
<p>Easy enough… now let’s add everything that is within the bin folder as a dynamic file source:</p>
<pre class="ps1">$BinFolder = New-FileSource &quot;Bin Folder&quot; -Root &quot;/bin&quot;
$package.Sources.Add($BinFolder);</pre>
<p>That is it really… you may want to specify your package metadata which you would do like:</p>
<pre class="ps1">$package.Metadata.Author = &quot;Auto generated &quot; + `
  [DateTime]::Now.ToShortDateString();
$package.Metadata.Comment = &quot;Isn't it cool?!&quot;;
$package.Metadata.Publisher = &quot;Cognifide&quot;;</pre>
<p>and then save it for later opening in package designer:</p>
<pre class="ps1">$package | Export-Package -FileName &quot;test package.xml&quot;</pre>
<p>alternatively you can open such package as specified earlier</p>
<pre class="ps1">get-package &quot;test package.xml&quot;</pre>
<p>if you ever wanted to add more sources to it or export as a zip file to be imported with the assets in your target environment:</p>
<pre class="ps1">$package | Export-Package -FileName &quot;test package.zip&quot; -Zip</pre>
<p>… now on your target machine you need to upload your package to the Data\Packages folder. But then to install it all it takes is:</p>
<pre class="ps1">Import-Package &quot;test package.zip&quot;</pre>
<p>Obviously all of it can be hooked to ribbon, context items, or be scheduled… but I get ahead of myself&#8230;</p>
<h2>So how does it all relate to continuous deployment?</h2>
<p>All of this can be completely automated, all you need to do is create a Script item as described in <a href="http://blog.najmanowicz.com/2011/11/24/extending-sitecore-ribbon-with-powershell-scripts/" target="_blank">one of my previous posts</a> and call the PowerShell execution URL referencing your script from your CruiseControl server or whichever continuous integration product you use in a fashion similar to:</p>
<pre>http://myhost/Console/Layouts/PowerShellResults.aspx?scriptId={1680E211-BD28-49BE-82FB-DA7232814C62}&amp;scriptDb=web</pre>
<p>You need to deal with the fact that you are most probably not logged in with your continuous delivery environment – in this case probably best approach is to use the web database or the script item my turn out to be unavailable to you and the script will not execute.</p>
<p>Now in your source environment your script will create the package and upload it to an FTP server (there is plenty of ways to do this from PowerShell… you can find a <a href="http://stackoverflow.com/questions/1867385/upload-files-with-ftp-using-powershell" target="_blank">couple of samples on Stack Overflow</a>) and subsequently <a href="http://stackoverflow.com/questions/508565/how-to-make-an-authenticated-web-request-in-powershell" target="_blank">call a second part of the script on the target server</a>.</p>
<p>On the Target server – a complementary script will be executed in the similar fashion – by the originating server and if you don’t have direct access to the file on the FTP server you’ve just uploaded – you can download it and import the package.</p>
<p>Now if you integrate the script with a ribbon in Content Editor on the source server (<a href="http://blog.najmanowicz.com/2011/11/24/extending-sitecore-ribbon-with-powershell-scripts/" target="_blank">like described in the previous post</a>) you can have a one-click-deployment solution on your dev machine, but then the REALLY cool part would be to integrate it with the context menu (<a href="http://blog.najmanowicz.com/2011/11/22/context-powershell-scripts-for-sitecore/" target="_blank">as described in this post</a>) and be able to push parts of the site to production with a single click! Not to mention your nightlies can really be nightlies if you do it using the <a href="http://blog.najmanowicz.com/2011/11/29/powershell-driven-sitecore-scheduled-tasks/" target="_blank">scheduled tasks integration</a>.</p>
<img src="http://blog.najmanowicz.com/?ak_action=api_record_view&id=464&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://blog.najmanowicz.com/2011/12/19/continuous-deployment-in-sitecore-with-powershell/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Context PowerShell Scripts in EPiServer</title>
		<link>http://blog.najmanowicz.com/2011/05/04/context-powershell-scripts-in-episerver/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=context-powershell-scripts-in-episerver</link>
		<comments>http://blog.najmanowicz.com/2011/05/04/context-powershell-scripts-in-episerver/#comments</comments>
		<pubDate>Wed, 04 May 2011 06:00:00 +0000</pubDate>
		<dc:creator>Adam Najmanowicz</dc:creator>
				<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[CMS UX]]></category>
		<category><![CDATA[Code Samples]]></category>
		<category><![CDATA[EPiServer]]></category>
		<category><![CDATA[PowerShell]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[Solution]]></category>
		<category><![CDATA[Web applications]]></category>

		<guid isPermaLink="false">http://blog.najmanowicz.com/?p=225</guid>
		<description><![CDATA[Ok, so I’ve got my shot of endorphins writing about PowerShell last week (damn, it’s nice to be able to code again!), and I got pretty determined on making it usable and achieving all the goals I’ve initially envisioned. and in the process build a usable tool and a library of scripts that people can [...]]]></description>
			<content:encoded><![CDATA[<p>Ok, so I’ve got my shot of endorphins writing about PowerShell last week (damn, it’s nice to be able to code again!), and I got pretty determined on making it usable and achieving all the goals I’ve initially envisioned. and in the process build a usable tool and a library of scripts that people can use either directly or to modify to meet their needs.</p>
<p>The goal for this week: <strong>Context Scripts</strong></p>
<p>Context scripts are the first step to break the scripting out of the admin realm and into the editor’s space. Those scripts will still be written by admins and developers but the goal is for them to be usable by the authors. The goal for those scripts can be as trivial as e.g. syndicating all the great functionality little plugins like this <a title="Unpublish button by Ted" href="http://labs.episerver.com/en/Blogs/Ted-Nyberg/Dates/2009/2/Adding-a-custom-plugin-button-to-unpublish-a-page-in-EPiServer/" rel="nofollow" target="_blank">Unpublish button by Ted</a> in one place and then mix and match them to your liking.</p>
<p>Some of the important bits:</p>
<ul>
<li>Context scripts are something that is visible to users on “Scripts” page. </li>
<li>Scripts can be exposed to everyone or just the groups of your liking… you define it in the script. </li>
<li>Scripts are grouped in collections that are defined in *.psepi files that you drop into your application folder </li>
</ul>
<h2>How do I define a script collection?</h2>
<p><span id="more-225"></span><br />
<h2></h2>
<p>Each script collection is defined within a single .psepi file. A sample script can look as follows:</p>
<pre class="xml" name="code">

&lt;?xml version=&quot;1.0&quot;?&gt;
&lt;ContextScriptCollection&gt;
  &lt;Title&gt;Statistics Scripts&lt;/Title&gt;
  &lt;Description&gt;This is a sample script collection allows for calculating some interesting stats for the branch you're in.&lt;/Description&gt;
  &lt;Scripts&gt;
    &lt;ContextScript&gt;
      &lt;Title&gt;Author Statistics&lt;/Title&gt;
      &lt;Description&gt;Click to Learn more about how many pages under this one were created by which authors.&lt;/Description&gt;
      &lt;Script&gt;get-childitem -recurse | Group-Object  ChangedBy | Sort count -descending | format-table -property count, name&lt;/Script&gt;
        &lt;Icon&gt;/App_Themes/Default/Images/Tools/AddUser.gif&lt;/Icon&gt;
        &lt;Warning&gt;This script only calculates statistics so it does not really need a warning but let’s show it anyway. Do you want to calculate them?&lt;/Warning&gt;
      &lt;Groups&gt;
        &lt;string&gt;WebAdmins&lt;/string&gt;
        &lt;string&gt;Administrators&lt;/string&gt;
      &lt;/Groups&gt;
    &lt;/ContextScript&gt;
  &lt;/Scripts&gt;
&lt;/ContextScriptCollection&gt;

</pre>
<p>What does each of the tags mean?</p>
<ul>
<li><strong>Title</strong> &amp; <strong>Description</strong> on <strong>ContextScriptCollection</strong> are going to appear at the top of the list for the collection – pretty self explanatory. </li>
<li><strong>Scripts</strong> is a container for <strong>ContentScript</strong> tags, it can contain any number of them. </li>
<li>Each <strong>ContentScript</strong> tag represent a single script, where <strong>Title</strong> is what will appear on the button that the user will click to execute the script. </li>
<li><strong>Script</strong> tag contains the script body – this is where you put the code that will get executed </li>
<li><strong>Icon</strong> is a URL to an image that will appear on the button left of the button title. </li>
<li><strong>Warning</strong> tag contains a question that will get presented to the user before the script will be executed. This tag can be omitted in which case no warning will be shown. A rule of thumb would be that you should show a warning before a long running scripts and scripts that modify content so a user can back away from a mistakenly pressed button. </li>
<li><strong>Groups</strong> tag contains the list of groups that will have the right to see the script. if that tag is empty, all users will see the script. If you define at least one group, you need to define all groups that you want to see the button. </li>
</ul>
<h2>What does “Context” in Context scripts mean?</h2>
<p>Basically since we cannot show the editor a console and let them navigate to the page (for various reasons, like complexity and potential destructive powers <img style="border-bottom-style: none; border-left-style: none; border-top-style: none; border-right-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="http://blog.najmanowicz.com/wp-content/uploads/2011/05/wlEmoticon-smile.png" />) The scripting environment will put your script “in the current page” before releasing control to your script, which in essence is equivalent to typing before your script.</p>
<pre class="ps1">cd MyCMSDrive:\
cd /path/to/my/page/</pre>
<p>That means that your script can get access to the page the user is currently on simply by using the “get-item .” command or enumerate its children by use of “get-childitem” etc. in the case of the script above it calculates author statistics for the branch it is executed in. Pretty cool, huh? ;)</p>
<p>Additionally I’ve realized in the process of duplicating/extending the functionality of <a title="Unpublish button by Ted" href="http://labs.episerver.com/en/Blogs/Ted-Nyberg/Dates/2009/2/Adding-a-custom-plugin-button-to-unpublish-a-page-in-EPiServer/" rel="nofollow" target="_blank">Ted’s plugin</a> that modifying standard EPiServer properties is not necessarily very intuitive, hence I’ve created a few macros to help me with the scripting exercises. While I still need to call “CreateWritableClone” I’ve simplified the saving of a page by defining the “<strong>Save-Page</strong>” function and created a <strong>Get-CurrentPage</strong> as an alias to “get-item .”. So a following script unpublishes the current page:</p>
<pre class="ps1"><b>Get-CurrentPage</b> | foreach-object {
$writable = $_.CreateWritableClone();
$writable.StopPublish = [DateTime]::Now;
Save-Page($writable);
}</pre>
<p>While this one unpublishes all of its children</p>
<pre class="ps1"><b>get-childitem -recurse</b> | foreach-object {
$writable = $_.CreateWritableClone();
$writable.StopPublish = [DateTime]::Now;
Save-Page($writable);
}</pre>
<p>Notice the subtle difference in the script and the major difference in the effect? Pure PowerShell magic!</p>
<p>To be honest I was amused to find out that during the whole process I’ve still not broken the CMS 5 compatibility, but I don’t expect it to stay this way in the future.</p>
<p align="center"><a href="http://blog.najmanowicz.com/wp-content/uploads/2011/05/EPiServer5ContextScript.png" rel="lightbox[225]" title="EPiServer5ContextScript"><img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="EPiServer5ContextScript" border="0" alt="EPiServer5ContextScript" src="http://blog.najmanowicz.com/wp-content/uploads/2011/05/EPiServer5ContextScript_thumb.png" width="244" height="201" /></a>&#160;&#160;&#160; <a href="http://blog.najmanowicz.com/wp-content/uploads/2011/05/EPiServer6ContextScript.png" rel="lightbox[225]" title="EPiServer6ContextScript"><img style="background-image: none; border-right-width: 0px; margin: 3px 3px 0px 7px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="EPiServer6ContextScript" border="0" alt="EPiServer6ContextScript" src="http://blog.najmanowicz.com/wp-content/uploads/2011/05/EPiServer6ContextScript_thumb.png" width="244" height="204" /></a></p>
<p>Also at this moment you can add and remove the *.psepi files at any moment as the files are parsed on every request, if that proves to be a problem in the future, caching will get introduced. At this moment I don’t find it a problem as it only happens in edit mode.</p>
<p align="center"><a title="Download Powershell console with context script support" href="http://www.najmanowicz.com/blog_bin/Cognifide.EPiserverControls.PowerShell.Context.zip" target="_blank">[Download &amp; Enjoy]</a></p>
<p>Includes 2 bonus script collections!</p>
<h2>How to install?</h2>
<p>Extract the DLL form the ZIP file into the BIN folder of your web application to install the plugin. Remove the DLL to uninstall it.</p>
<p>All constructive feedback appreciated!</p>
<p><font color="#ff0000"><strong>Disclaimer – Responsibility</strong>: <em>With great powers comes great responsibility – this tool can do a lot of harm to a lot of content in a very short time – backup your system before using the plugin! I will not be held responsible for any use of it. Test your scripts on your development server first! Test on an exact copy of production before running scripts on production content. </em></font></p>
<p><font color="#ff0000"><strong>Disclaimer – Security</strong>: <em>While the tool requires a membership in either the “WebAdmin” or “Administrators” group, to execute, protect it with a &lt;location&gt; entry in web.config, to add another layer of security especially if your administration UI is exposed to the public. Manage your group memberships &amp; rights responsibly!</em></font></p>
<style type="text/css">
pre.ps1
{
        padding: 4px; 
        margin: 4px 0 4px 0;
        overflow: auto;
        background-color: #012456; 
        border: thin solid #aaa;
        color:#fff;
        font-weight:900;
        width: 95%;
        border: solid #000 1px;
}
</style>
<img src="http://blog.najmanowicz.com/?ak_action=api_record_view&id=225&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://blog.najmanowicz.com/2011/05/04/context-powershell-scripts-in-episerver/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>CMS UX &#8211; give the content some thought!</title>
		<link>http://blog.najmanowicz.com/2010/02/08/cms-ux-give-the-content-some-thought/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=cms-ux-give-the-content-some-thought</link>
		<comments>http://blog.najmanowicz.com/2010/02/08/cms-ux-give-the-content-some-thought/#comments</comments>
		<pubDate>Mon, 08 Feb 2010 12:01:38 +0000</pubDate>
		<dc:creator>Adam Najmanowicz</dc:creator>
				<category><![CDATA[Best Practices]]></category>
		<category><![CDATA[CMS UX]]></category>
		<category><![CDATA[EPiServer]]></category>
		<category><![CDATA[Faceted Navigation]]></category>
		<category><![CDATA[Web applications]]></category>

		<guid isPermaLink="false">http://blog.najmanowicz.com/2010/02/08/cms-ux-give-the-content-some-thought/</guid>
		<description><![CDATA[One of the many things we debate constantly at Cognifide is how to improve the user experience. How to make editor’s life easier, how to simplify the common everyday tasks, what can be automated, and simply how to make our customer smile a little when they use our projects. For that to work, apart from [...]]]></description>
			<content:encoded><![CDATA[<p>One of the many things we debate constantly at Cognifide is how to improve the user experience. How to make editor’s life easier, how to simplify the common everyday tasks, what can be automated, and simply how to make our customer smile a little when they use our projects.</p>
<p>For that to work, apart from the overall big blocks to be in place and working seamlessly (which is the absolute minimum required) – you need to be VERY attentive to details. </p>
<p>What happens when user enters a place in the system where they are not usually required to work, are they properly guided? What do they see if they click on a little link somewhere in the corner? Does every image has an Alt text attached to it? Do your buttons have tooltips? Do the users have alternate views on all content? Do the system communicates abnormal states in a descriptive way and guides the user towards the solution? Is the UI logically laid out? Did you REALLY think what property should go on which tab? Have you setup the property names in a way that they make sense to non programmer? Do they have descriptions?</p>
<p>Part of the job we do is help sometimes troubled EPiServer customers get their solution built elsewhere or in-house to work, and I seem to be noticing some patterns which we have addressed in Cognifide as being bad practices. Many of those stem from the lack of research of the content served being done in the discovery phase. </p>
<h2>Discovery phase? What’s that?</h2>
<p>It seems that a great deal of projects does not seem to be well thought out in many aspects. When you look at the solution, It feels like a developer just got some templates and ran with them. Once the front end matches what the html templates outline, the solution is pushed to production and forgotten by the design/development agency and the poor customer is struggling with it for years trying to improve the ever degrading performance and fighting the CMS UI that’s been thrown together in a rush. Possibly aggravating in the process and rebuilding it again and again.</p>
<p>You need to realize that once your site goes to production, the trouble begins for your customer, not ends.</p>
<h2>Understand your content, please</h2>
<p>A very basic tendency for a lot of them is storing all the content of one type under a single tree node. or a very basic hierarchy. But:</p>
<ul>
<li>What is the volume of content in the start? </li>
<li>Have you talked to the client about the maintenance of the content? </li>
<li>How do they plan to store older content?
<ul>
<li>Are they archiving it? </li>
<li>Do they plan to serve it to general while archived? </li>
<li>Is the old content actively browsed on the CMS side? </li>
</ul>
</li>
<li>What is the volume increase over time? </li>
<li>What is the profile of the content? Is it a catalogue? Chronological news library? </li>
<li>Is there a taxonomy in place? </li>
<li>How often and which content is being modified? </li>
</ul>
<p>EPiServer shows pages in a tree, and while we have observed the CMS performance improving over time there are some basic scenarios that the hierarchy structure will never be able to deal with efficiently if not well thought out.</p>
<p>So your potential edge case scenarios might be that the customer has:</p>
<ol>
<li>10 000 articles that need to be migrated for the site to go live, but they only plan to add 2-3 a month, </li>
<li>They might be starting fresh but they plan to add 20 to 30 articles a day! </li>
</ol>
<p>How do you deal with those?</p>
<p>Obviously the worst thing you can do is to put them all under the “Articles” node. The customer will be frustrated to no end! Both you and the CMS reputation gets damaged while they try to do any basic thing in the CMS.</p>
<p>In the first case you need to work with the client to dissolve them into the hierarchy that’s granular enough to leave you with the 20-50 articles per node tops. Dividing it into 10 categories of roughly 1000 items won’t do! If the page names are meaningful, you may attempt to create a structure based on the first and second letter of the articles. This works best for directories of people or places.</p>
<p>The second case is probably going to happen to you when you will be working with any kind of news site, be that intranet of sorts or a news agency, TV portal or an information broker. In which case, it seems to be making the most sense to put the content into a chronological structure. Have a node for each year, month (and day if needed) there is an article. </p>
<h2>AUTOMATE! </h2>
<p>When a user writes an article that is supposed to fit into your content plan, move it into the proper node automatically. In the first case, move it to the proper category or based on the page title move it around to the proper place in the catalogue. In the chronological plan, move it to the day or month node upon creation. If a new node needs to be created for it – that’s your responsibility to do it. Organize the content for the user or you will be in a world of pain sooner than you expect!</p>
<p>Those tasks are easily automated by hooking into the page save and create events. Your customer will love you for it.</p>
<p>Naturally you don’t necessarily have to have a single plan on a given site. A site can have both branches with news-like plan and directory-like sub trees.</p>
<p>The base line is – you need to plan it ahead, and you need to learn about the content profile.</p>
<h2>Distinction <strong>with</strong> a difference</h2>
<p>You need to realize the distinction between the content and the presentation of it. Don’t try to cram the content into the browsing structure. Separation of concerns should not be limited to code organization. Separate concerns in the content structure as well.</p>
<p>Have the user trip designed around the best SEO practices. The hub pages should make sense from the visitor’s perspective. DON’T try to put your articles under it just because the hub page browses them. this may work for a little tiny sites but then again, those are not the sites that you will run into troubles because it basically means your customer is barely ever touching them.</p>
<p>Have your content stored in a separate branch and reach out for it with a tag set that is related to the hub page. </p>
<h2>Build a logical taxonomy and stick to it!</h2>
<p>That basically means – treat your content equally no matter where it’s stored – preferably having it tagged with a high performance framework like the <a href="http://blog.najmanowicz.com/category/software-development/episerver/faceted-navigation/">Faceted Navigation Framework</a> published by Cognifide some time ago or make it <a href="http://incubator.apache.org/lucene.net/">Lucene.Net</a> based. You can try to use the EPiServer built in categories. We have had limited success with it and the performance of FindPagesWithCriteria (which we have effectively banned from our arsenal) but I was told the performance in that front have improved greatly in the latest EPiServer CMS release.</p>
<p>Regardless – don’t rely on the page hierarchy structure to select the content, it doesn’t matter where it is, the metadata is what should be driving the content stream. You can hand pick your navigation links, fine, but article lists, news, announcements, events, treat it as a single content stream. Use a taxonomy to divide it into categories and you will be much happier in the long run as you will gain much more flexibility to reorganize the structure and move the content around when its profile changes later.</p>
<p>Using the EPiServer CMS for nearly 4 years now, those are the basic principles we have come to establish. </p>
<p>I wonder what are your practices? Where do you think our practices do or do not fit your design philosophy? Is there anything we could do better? Do you have practices regarding content planning? How do you analyze the content to make the best plan for it?</p>
<img src="http://blog.najmanowicz.com/?ak_action=api_record_view&id=168&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://blog.najmanowicz.com/2010/02/08/cms-ux-give-the-content-some-thought/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

