New site running Orchard

Topics: Announcements, General
Jun 26, 2011 at 7:12 PM

Hey everybody, I am proud to announce that after many many months of development, we have officially launched our new Orchard-based site: http://aclj.org

Thank you Orchard team for all of your assistance, and for putting out such a great platform. We're proud to be running on Orchard!

Chris Bower
Lead Developer
ACLJ

Jun 26, 2011 at 9:53 PM

Congratulations! Looks fantastic. Maybe you could provide a short description of what you have been doing, ie. modules you have used, or developed yourself. I think it could be very useful for other developers looking into the possibilities in using Orchard CMS.

Jun 27, 2011 at 2:55 AM

This is a beautiful site, congratulations.

Would you be willing to tell us about the modules you used and other customizations you made to Orchard to make it so nice?

Jun 27, 2011 at 4:24 AM

Here's the reply I posted to similar questions on the Orchard-Discuss mailing list:

 

Thanks guys. Some of what we learned I shared on my blog, http://chrisbower.com.

 

We used a lot of different techniques throughout the site, but the biggest key for us were shape methods. It allowed us to call anything we needed to from within a shape or layout, and also allowed us to have a very easy-to-use cache methodology.

 

I've created a fairly comprehensive cache module that I'll be releasing to the community in the coming weeks (once things slow down a bit, and I get some rest) that I think will prove very beneficial. It vastly improved the performance of our site, especially when so many different content items and parts are pulled on to every page.

 

The gist of how our implementation works:

  • We have 28 custom written modules, about 1 for every major section of the site, plus a few miscellaneous things like: image management (we have a module that crops and resizes images to the Rackspace file cloud), a YouTube module that scrapes our YT feed and populates video content, a common shape library module, caching modules, etc.
  • We have a different layout file for every different template used on the site (some dupes, based on a controller/action using the same sort of template as another controller/action).
  • The layout files pull shapes into the appropriate zones like so (An example of some shapes pulled into our homepage layout):

    WorkContext.Layout.Featured.Add(New.TopStoriesArea(), "1");

    WorkContext.Layout.Featured.Add(New.MiniPetition(), "2");

    WorkContext.Layout.BeforeMain.Add(New.FeaturedMedia(), "1");

    WorkContext.Layout.BeforeMain.Add(New.FeaturedLinksArea(), "2");

    WorkContext.Layout.AfterContent.Add(New.CurrentCasesScroller(CasesSetSize:4), "1");

    WorkContext.Layout.TripelFirst.Add(New.MostRecentLegalDocs(), "1");

    WorkContext.Layout.TripelSecond.Add(New.MostRecentJusticeFiles(), "1");

    WorkContext.Layout.TripelThird.Add(New.FeaturedPoll(), "1");

  •  
    • Note that we experimented first with widgets, but decided that trying to create a widget for each of the 100+ widget-like shapes we have on our site wouldn't have been a good idea.
  • Shapes are first defined by a shape method, then implemented by a "shape view", like so:
  •         [Shape,Cache]
  •         public IHtmlString SidebarAd(dynamic Display) {
  •             var ads = ContentManager.Query(VersionOptions.Published, "HouseAd").List().AsPart<HouseAdPart>().ToList();
  •             return Display.SidebarAdView(Ads: ads);
  •         }
  • (A file named SidebarAdView.cshtml would then implement the shape with the provided parameters.)
  • Shape methods acted like controllers for partials. We could include logic wherever we needed to, pulled in from services
  • Shape methods were also called very often from other shapes:

 @foreach(var d in legalDocs)

        {

            var sourcePart = d.As<SourcePart>();

            var source = "";

            if(sourcePart!=null && sourcePart.Source !=null){

                source = sourcePart.Source;

            }

            <li>@Display.ContentTitle(item:d, limit:35)<br />

                <span>@Display.ContentDate(item:d)</span> </li>

        }

  • ContentTitle and ContentDate are shape methods that are our standard way of rendering a title and date for our content types.  We probably could have done it in a more standard way by using Display(contentItem) and then defined display types and placements, but this seemed to be less complicated for us. That's one of the things I love about Orchard. There's not just one way to do something. It allows us to be opinionated, rather than being forced to the framework's opinion.

To answer the DB question, we're just using MSSQL. We're hosted on a virtual web farm at Rackspace with a couple of web VMs and a DB vm. The entire site was built on Orchard, with the only exception being our donations being handled by Kimbia widgets.

 

From a metrics standpoint, it might be interesting to note that our site was developed by myself and Jesse Wise (who came up with the shape method implementation, major props) in about 5 months. We 'broke ground' in Orchard in the middle of January and launched on June 25th. Neither of us had any Orchard experience before that point. Having been involved in a few other larger sites, I felt pretty good about the speed which we were able to implement this project in Orchard, even with the (somewhat steep) learning curve.

Jun 27, 2011 at 5:53 AM

Nice!  Question for you, what are you using as your radio player?

Jun 27, 2011 at 5:04 PM

Not sure exactly... The other guy wrote that piece :)

Jul 1, 2011 at 10:37 PM

Just noticed this post.  I'm the other guy who worked on the radio player.  It was done with jplayer which was chosen for the flash and html5 fallback.  This way it plays nice on most browsers even mobile safari on the iphone/ipad, unfortunately the android browser wasn't working last time i checked because of the lack of mp3 streaming support in the browser if I remember correctly.

Jul 2, 2011 at 8:46 PM

Great website for a great organization!  Great response time!   Whatever you did for caching, Orchard should integrate it into the product.  Look forward to that module.  This site really shows what a masterpiece of design and flexibility Orchard is.

Jul 6, 2011 at 9:10 PM

Looks great! I really like what you're doing with the shape methods. I am developing a site for which I also don't think widgets make sense, and this looks like a great alternative.

1. From reading your blog, it looks like you started out by defining ShapeTableProviders to hook up the shapes, and later moved to defining individual shape methods using the Shape attribute. In your first post, you mention that you were having troubles injecting the IContentManager through constructor injection, and had to make due with injecting IHttpContextAccessor and IWorkContextAccessor through the constructor, then using those to resolve the IContentManager. Did you also find that you needed to do this for the individual Shape methods? (I did...I guess I am really wondering if you found another way around that.) 

2. For the average shape, what are all the different objects you have defined? Following your example, I ended up with (see below). Is any of this unnecessary, and did I miss anything?

  • a shape method (i.e. SidebarAd, in your example above)
  • a view for displaying the shape on the site (i.e. SidebarAdView)
  • a part and record to define the fields of the items in this shape (i.e. HouseAd and HouseAdPart in your example)
  • a HouseAdHandler to add a StorageFilter for IRepository<HouseAd>
  • a HouseAdDriver that overrides Display, Edit(GET) and Edit(POST) methods, for editing/displaying HouseAds within the admin
  • Views for editing/displaying HouseAds within the admin
  • a migration for creating the HouseAd table and defining the part

3. For anyone else following along, like me, there is a very subtle naming requirement in the example you posted. If you named the view "SidebarAd" instead of "SidebarAdView", adding a New.SidebarAd() shape in the layout would simply display that view, rather than calling the shape method. I was stuck on that for a while.

Jul 8, 2011 at 3:39 PM

1. Yes, we had to continue to resolve when using shape methods

2. You seem to have covered most of it, although keep in mind our shapes weren't necessarily 1:1 with parts/records. Most of our shapes are a composite of a bunch of different parts.

3. Correct