Thursday, March 27, 2014

Build responsive websites with Visual Studio 2013 and Bootstrap 3.0

Summary: Materials for the Sacramento .NET User Group presentation.
Thanks a lot to everyone who attended my presentation yesterday. You have been an awesome audience. Also, many thanks to Josh Gurin (TEKsystems) for the pizzas and wings and Jason Singh (Microsoft) for the excellent meeting space. I was a bit concerned about parking, but there were lots of free after 6 PM parking spaces around the building.

Here are the materials I promised: In case you don't want to bother downloading the files, here is the presentation:


The PowerPoint slides provide the same information as the web application built by the demo project. If you only want to check references and resources mentioned at the session, just use the slides. If you intend to see how the concepts were applied in the actual application, get the project. When you run the demo app, you will see the same content available in the presentation, although in a slightly different format. Links should work from both the presentation and the demo app.

If you run into any issues or have questions, please post a comment below or contact me directly.

Friday, May 10, 2013

WiX woes: What is your installer doing?

Summary: How to detect different modes of installation.
When building an application installer, it's often necessary to distinguish between different modes of installation, i.e. initial installation, repair, upgrade, uninstall, etc. And as with everything important in MSI, detecting the mode of installation is a PITA (and by PITA, I do not mean flat bread of Mediterranean origin). To help you a little bit, here is a table adopted from a StackOverflow topic (and comments), that shows the values of various Windows Installer properties can help you determine the installation mode:

Install Uninstall Repair Modify Upgrade
INSTALLED FALSE TRUE FALSE TRUE TRUE
REINSTALL TRUE FALSE TRUE FALSE FALSE
REMOVE="ALL" FALSE TRUE FALSE TRUE TRUE
UPGRADINGPRODUCTCODE TRUE FALSE TRUE TRUE TRUE

You can use logical operators NOT, AND, OR to build complex conditions.

Here is how you can detect some common conditions:

First-time installation
  • NOT Installed
Any installation
  • NOT Installed AND NOT PATCH
Installation and repairs
  • NOT REMOVE
First-time installation and repairs
  • NOT Installed OR MaintenanceMode="Modify"
Upgrades only (during uninstall phase)
  • Installed AND UPGRADINGPRODUCTCODE
Upgrades
  • Installed AND NOT REMOVE
Full uninstall (except when triggered by a major upgrade)
  • (REMOVE="ALL") AND (NOT UPGRADINGPRODUCTCODE)
Any uninstall
  • REMOVE~="ALL"
If you notice errors or want to include some other conditions, please post a comment.

See also:
MSI Property Patterns: Upgrading, FirstInstall and Maintenance
Upgrading, FreshInstall, Maintenance and other MSI convenience properties
MSI Writing Guidelines: Installation Scenarios
How to execute custom action only in install (not uninstall)

Thursday, April 25, 2013

My Walmart account was hacked

Summary: Lessons from my Walmart account hacking incident.
Out of the blue, I get an email from Walmart:
Dear Alek Davis,

Personal information associated with your Walmart.com account - name, email address and/or password - has been successfully updated as requested. If the account change included an update to the email, for your added security this account update confirmation is sent to both the new and old email addresses. All future emails will be sent to the new address only.

If the account information update is correct, no further action is needed.

If you did not make these changes to your account, please call us immediately at 1-800-966-6546.

If you have any questions, please reply to this email and let us know how we can help.

We appreciate the opportunity to assist you and look forward to your next visit.

Sincerely,

Your Walmart.com Customer Service Team
I try to log on to my Walmart account and fail to authenticate. I attempt to use the I Forgot My Password feature, but get a message stating that my email address is not registered with Walmart. It's obvious: someone hacked my Walmart account!

I call the above mentioned 1-800 number, but the customer support department is closed (it's around 10 PM PST, but apparently, the world's largest retailer cannot afford 24x7 customer support). There is no option to report the problem online. What's a girl to do?

The best thing I can do is send an email reply describing the problem. I get a canned response indicating that I will get a human response within 24 hours. Okay, what's next?

Results from a quick Google search suggest that a common pattern of Walmart hacking involves using saved credit card data to purchase digital goods. So, I log on to my credit card's account (for the card that I normally use at Walmart.com) and see two unauthorized transactions: one in the amount of $60 (turns out to be 2 Straight Talk 1000-Minute, 1000-Text, 30MB Web Access Service Cards), and another in the amount of $50 (2 SKYPE $25 Prepaid eGift Cards). I call the credit card company to report fraud. I also checked other credit cards that could've been on file with Walmart, but do not notice anything suspicious.

I try logging on to Walmart.com again, and notice a strange address popping up in the email field of the Sign In form for a second just before it is overwritten by my original (and no longer good) address filled in by LastPass. Apparently, I have a low-security personalization cookie, that is not good for anything important (like checking or changing account info, or submitting orders), but it could give me some info about the hacker. I disable LastPass and reload the form. Get the email field populated with this address: ssuper981@yahoo.com. Hello, hacker. How're you doing?

Silly idea: what if I try to log in with my original password? The hacker can't be that careless, but... One... two... three... I'm in! Dear, ssuper981@yahoo.com, thank you for failing Hacking 101. I change my email address back, change the password, and remove all credit card info from the account. I see the two orders in the processing state, and successfully cancel one of them. I use a form to send an order cancellation request for the second purchase, but apparently the Skype eGift cards have been already sent. Well, it's now between Walmart and my credit card company to dispute the charge.

What else can I do? I go to the Yahoo! Security Center and try to find an option to report fraudulent activity coming from a Yahoo! email, but Yahoo! does not provide any way to do this (via a form, email, or phone).

The next morning, I call Walmart (thank God Walmart can afford customer support during normal business hours) to report the incident to a human and have a short conversation with a nice woman (btw, have the companies started bringing customer support back from the foreign lands? talking to a motivated native speaker is so refreshing!). Now, it's time to get back to life, but first, lessons learned:
  1. Never save credit card information when shopping online! Yeah, it's convenient, but may eventually cause more hassles.
  2. Read #1.
And a couple of comments:
  • Walmart: No 24x7 customer support? Seriously? Even for security issues? Come on, you can do better!
  • Walmart: Good call on sending notification to old customer's email on personal profile changes. Have I not seen this message, it would have taken me much longer to realize that my account was hacked.
  • Walmart: Shouldn't user activity that starts with personal profile (and email) changes and is followed by an immediate purchase of digital goods raise a flag for suspicious activity? I know that you rush to get a payment, but you see: you lost $60 (which could've easily been $110), and I'm sure you need that money to hire more support people (at the very least, for security related issues).
  • Yahoo!: Would it be too much to ask for some way of reporting fraudulent activity originating from a Yahoo! email account? Just asking.
Have a nice day, everyone. Be safe!

Wednesday, March 27, 2013

Send HTML email from VBScript using CDO

Summary: VBScript to send HTML (and plain text) email.
It's 2013 and apparently there are no tools that would allow you to easily send HTML-formatted email.

Don't get me wrong: of course, Outlook, Thunderbird, Gmail, or whatever client you use, allows (and sometimes forces) you to send email in HTML format, but what if you want to test a format of a message that your application (code) and not you (person) sends? What do you use? Sure, both Outlook and Thunderbird allow you to insert an HTML file as the body of the text, but as soon as you do, they alter your HTML source in a way you you would not imagine, so that the delivered message will show little resemblance to the original.

After wasting several hours with existing email clients and trying available scripting samples (e.g. the ones written by Paul Sadowski and Rob Vanderwoude), I decided to do it the right way and wrote a little utility that would take your HTML file and send it without making any changes to the source code. Lo and behold, here is a VBScript file that you can use for sending email messages:
IMPORTANT: This script requires the helper Common.vbs file to be located in the same folder (or in the PATH).
SendMail.wsf script takes email body from command line or retrieves it from a file. It supports both HTML and plain text formats. You can send your message via a remote mail server or using the local SMTP service. You can also include attachments with the message.

Here is the usage info (you can get this output by running the script with the /? or /h command-line switch):
cscript //nologo SendMail.wsf /h

DESCRIPTION:

  Sends an email.

USAGE:

  cscript SendMail.wsf [/option[:parameter[;...]]] [...]

OPTIONS:

  from
    Email From address.

  to
    Email To address. Use comma to separate multiple addresses.

  cc
    [Optional] Email CC address. Use commas to separate multiple addresses.

  bcc
    [Optional] Email BCC address. Use commas to separate multiple addresses.

  subject
    [Optional] Email Subject line. 
    [Default: TEST]

  body
    Plain text, HTML text, or path to file containing email message.

  smtp
    [Optional] SMTP server.
    [Default: localhost]

  port
    [Optional] SMTP server port.
    [Default: 25]

  html
    [Optional] Indicates whether email message format is HTML.
    [Values: yes|no|y|n|true|false|t|f]
    [Default: no]

  file
    [Optional] Indicates whether the [/body] parameter points to a file.
    [Values: yes|no|y|n|true|false|t|f]
    [Default: no]

  add
    [Optional] Indicates paths to file attachments.
    Multiple files must be separated by semicolons.

This is how you would invoke the script:

Example 1: Send HTML-formatted email with email body defined in a file and with two JPEG file attachments using local SMTP service

cscript SendMail.wsf /from:me@mail.com /to:a@b.com /cc:"b@c.com,c@d.com" /subject:"Hey!" /body:Test.html /html:y /file:y /add:"a.jpg;b.jpg"
Example 2: Send plan text email using a remote SMTP server

cscript SendMail.wsf /from:me@mail.com /to:a@b.com /cc:"b@c.com,c@d.com" /subject:"Hey!" /body:"How are you?" /html:n /file:n /smtp:"smtp.server.com"

TIP: If you reference files when invoking the script (such as attachments or file containing message body), make sure that you use ether absolute path or path relative to the current directory; otherwise you may get the "File not found" error.
And here is the source code, in case you need to take a peek at the logic:
<!-------------------------------------------------------------------
  -- DESCRIPTION
  --  Sends email message with optional attachments.
  ------------------------------------------------------------------>
<package>
<job ID="SendMail">

<script Language="VBScript" Src="Common.vbs" />
<script Type="text/vbscript">
Option Explicit

Const SWITCH_FROM    = "from"
Const SWITCH_TO      = "to"
Const SWITCH_CC      = "cc"
Const SWITCH_BCC     = "bcc"
Const SWITCH_SUBJECT = "subject"
Const SWITCH_BODY    = "body"
Const SWITCH_SERVER  = "smtp"
Const SWITCH_PORT    = "port"
Const SWITCH_HTML    = "html"
Const SWITCH_FILE    = "file"
Const SWITCH_ADD     = "add"

Const SWITCH_ADD_DELIMETER = ";"

Wscript.Quit(Main())

'--------------------------------------------------------------------
' Method
'   Main
'
' Description
'   Performs the main operation.
'--------------------------------------------------------------------
Function Main()

  Dim strFrom, strTo, strCc, strBcc, strSubject, strBody
  Dim strServer, nPort
  Dim bIsHtml, bIsFile
  Dim arAttachments
  Dim i
 
  Main = -1
 
  ' Make sure the script is executed via cscript (not wscript).
  RevertToCscript(False)

  ' Show help if needed.
  If (IsHelpMode(False)) Then
    ShowHelp()
    Main = 0
    Exit Function
  End If
 
  ' Initialize run-time parameters.
  If Not Initialize _
  ( _
    strFrom, strTo, strCc, strBcc, strSubject, strBody, _
    strServer, nPort, bIsHtml, bIsFile, _
    arAttachments _
  ) Then
    Exit Function
  End If
 
  ' Make sure that all files (if any) exist.
  If (bIsFile) Then
    If Not FileExists(GetAbsolutePath(strBody)) Then
      WScript.Echo "File '" & strBody & "' does not exist."
      Exit Function
    End If
  End If

  If GetArraySize(arAttachments) > 0 Then
    For i = LBound(arAttachments) To UBound(arAttachments)
      If Not FileExists(GetAbsolutePath(arAttachments(i))) Then
        WScript.Echo "File '" & arAttachments(i) & "' does not exist."
        Exit Function
      End If
    Next
  End If
 
  ' Get contents of the message body from a file.
  If (bIsFile = True) Then
    strBody = ReadTextFromFile(GetAbsolutePath(strBody))
  End If
 
  SendEmail _
    strFrom, strTo, strCc, strBcc, _
    strSubject, strBody, strServer, nPort, _
    bIsHtml, arAttachments
 
    Main = 0
 
  WScript.Echo "Done."
End Function

'--------------------------------------------------------------------
' Method
'   SendEmail
'
' Description
'   Sends email using CDO.
'
' Parameters
'   Self-explinatory
'--------------------------------------------------------------------
Sub SendEmail _
( _
  ByVal strFrom, _
  ByVal strTo, _
  ByVal strCc, _
  ByVal strBcc, _
  ByVal strSubject, _
  ByVal strBody, _
  ByVal strServer, _
  ByVal nPort, _
  ByVal bIsHtml, _
  ByRef arAttachments _
)
  ' Standard housekeeping
  Dim i, oEmail

  ' Create an e-mail message object
  Set oEmail = CreateObject("CDO.Message")

  ' Fill in the field values
  With oEmail
    .From = strFrom
    .To   = strTo
        
    If Not IsEmptyString(strCc) Then
      .Cc = strCc
    End If
  
    If Not IsEmptyString(strBcc) Then
      .Bcc = strBcc
    End If
  
    .Subject = strSubject
  
    If bIsHtml = True Then
      .HTMLBody = strBody
    Else
      .TextBody = strBody
    End If
  
    If GetArraySize(arAttachments) > 0 Then
      For i = LBound(arAttachments) To UBound(arAttachments)
        .AddAttachment Replace(GetAbsolutePath(arAttachments(i)), "\", "\\" ), "", ""
      Next
    End If

    If Not IsEmptyString(strServer) Then
      With .Configuration.Fields
        .Item( "http://schemas.microsoft.com/cdo/configuration/sendusing")  = 2 ' cdoSendUsingPort
        .Item( "http://schemas.microsoft.com/cdo/configuration/smtpserver") = strServer
        .Item( "http://schemas.microsoft.com/cdo/configuration/smtpserverport") = nPort
        .Update
      End With
    End If
  
    ' Send the message
    .Send
  End With 

  ' Release the e-mail message object
  Set oEmail = Nothing
End Sub

'--------------------------------------------------------------------
' Method
'   Initialize
'
' Description
'   Processes command-line switches and initializes run-time
'   parameters.
'
' Returns
'   True on success; otherwise, False.
'
' Parameters
'   Self-explinatory
'--------------------------------------------------------------------
Function Initialize _
( _
  ByRef strFrom, _
  ByRef strTo, _
  ByRef strCc, _
  ByRef strBcc, _
  ByRef strSubject, _
  ByRef strBody, _
  ByRef strServer, _
  ByRef nPort, _
  ByRef bIsHtml, _
  ByRef bIsFile, _
  ByRef arAttachments _
)
  Initialize = False

  Dim strValue, strErrMsg
 
  strErrMsg = "Missing required parameter: " 
 
  strFrom = GetParamValue(SWITCH_FROM)
  If (IsEmptyString(strFrom)) Then
    WScript.Echo strErrMsg & SWITCH_FROM
    Exit Function
  End If
 
  strTo = GetParamValue(SWITCH_TO)
  If (IsEmptyString(strTo)) Then
    WScript.Echo strErrMsg & SWITCH_TO
    Exit Function
  End If
 
  strCc  = GetParamValue(SWITCH_CC)
  strBcc = GetParamValue(SWITCH_BCC)
 
  strSubject = GetParamValue(SWITCH_SUBJECT)
  If (IsEmptyString(strSubject)) Then
    strSubject = "TEST"
  End If
 
  strBody = GetParamValue(SWITCH_BODY)
  If (IsEmptyString(strBody)) Then
    WScript.Echo strErrMsg & SWITCH_BODY
    Exit Function
  End If

  strServer = GetParamValue(SWITCH_SERVER)

  strValue = GetParamValue(SWITCH_PORT)
  If (IsEmptyString(strValue)) Then
    nPort = 25
  Else
    nPort = CInt(strValue)
  End If

  strValue = GetParamValue(SWITCH_HTML)
  If (IsEmptyString(strValue)) Then
    bIsHtml = False
  Else
    strValue = UCase(strValue)
  
    If (strValue = "YES") Or (strValue = "Y") Or _
      (strValue = "TRUE") Or (strValue = "T") Then
      bIsHtml = True
    Else
      bIsHtml = False
    End If
  End If

  strValue = GetParamValue(SWITCH_FILE)
  If (IsEmptyString(strValue)) Then
    bIsFile = False
  Else
    strValue = UCase(strValue)
  
    If (strValue = "YES") Or (strValue = "Y") Or _
      (strValue = "TRUE") Or (strValue = "T") Then
      bIsFile = True
    Else
      bIsFile = False
    End If
  End If

  arAttachments = GetParamValues(SWITCH_ADD, SWITCH_ADD_DELIMETER)
 
  Initialize = True
End Function

'--------------------------------------------------------------------
' Function
'   ShowHelp
'
' Description
'   Displays help and usage info.
'--------------------------------------------------------------------
Sub ShowHelp()
  Dim strMsg          ' help message

  ' We know that user wants to see help, so generate help message.
  strMsg =    _
  "DESCRIPTION:" & vbCrLf &_
  vbCrLf &_
  "  Sends an email." & vbCrLf &_
  vbCrLf &_
  "USAGE:"  & vbCrLf &_
  vbCrLf &_
  "  cscript " & Wscript.ScriptName &_
  " [/option[:parameter[" & SWITCH_ADD_DELIMETER & "...]]] [...]" & vbCrLf &_
  vbCrLf &_
  "OPTIONS:" & vbCrLf &_
  vbCrLf &_
  "  " & SWITCH_FROM & vbCrLf &_
  "    Email From address." & vbCrLf &_
  vbCrLf &_
  "  " & SWITCH_TO & vbCrLf &_
  "    Email To address. Use comma to separate multiple addresses." & vbCrLf &_
  vbCrLf &_
  "  " & SWITCH_CC & vbCrLf &_
  "    [Optional] Email CC address. Use comma to separate multiple addresses." & vbCrLf &_
  vbCrLf &_
  "  " & SWITCH_BCC & vbCrLf &_
  "    [Optional] Email BCC address. Use comma to separate multiple addresses." & vbCrLf &_
  vbCrLf &_
  "  " & SWITCH_SUBJECT & vbCrLf &_
  "    [Optional] Email Subject line. " & vbCrLf &_
  "    [Default: TEST]" & vbCrLf &_
  vbCrLf &_
  "  " & SWITCH_BODY & vbCrLf &_
  "    Plain text, HTML text, or path to file containing email message." & vbCrLf &_
  vbCrLf &_
  "  " & SWITCH_SERVER & vbCrLf &_
  "    [Optional] SMTP server." & vbCrLf &_
  "    [Default: localhost]" & vbCrLf &_
  vbCrLf &_
  "  " & SWITCH_PORT & vbCrLf &_
  "    [Optional] SMTP server port." & vbCrLf &_
  "    [Default: 25]" & vbCrLf &_
  vbCrLf &_
  "  " & SWITCH_HTML & vbCrLf &_
  "    [Optional] Indicates whether email message format is HTML." & vbCrLf &_
  "    [Values: yes|no|y|n|true|false|t|f]" & vbCrLf &_
  "    [Default: no]" & vbCrLf &_
  vbCrLf &_
  "  " & SWITCH_FILE & vbCrLf &_
  "    [Optional] Indicates whether the [/" & SWITCH_BODY & "] parameter points to a file." & vbCrLf &_
  "    [Values: yes|no|y|n|true|false|t|f]" & vbCrLf &_
  "    [Default: no]" & vbCrLf &_
  vbCrLf &_
  "  " & SWITCH_ADD & vbCrLf &_
  "    [Optional] Indicates paths to file attachments." & vbCrLf &_
  "    Multiple files must be separated by semicolons."

  Wscript.Echo strMsg
End Sub
</script>
</job>
</package>
I did use the script to complete my project, but I did not thoroughly test it, so if you run into problems, please let me know.

Tuesday, November 6, 2012

Part V: Maintenance (Building a small business website)

Summary: How to run your small business website.
In this section, I will go over the things you need to be aware of when running your small business website. For other topics, see:

Table of contents Domain name renewal
Your custom domain registration is not forever. Make sure you do not forget to renew the registration; otherwise, it will expire and will be up for grabs. The worst thing you can do for your online presence is lose your domain name. It also makes sense to take advantage of registration promotions when you can save 15-25% off the renewal fees.

Tools
In addition to the website builder and webmaster tools offered by search engines, you may find the following tools helpful: Search-engine optimization (SEO)
Once you publish your site and it stays online for a few months, you will probably start receiving solicitations from third parties for improving your Google ranking, or what is known in the industry as search-engine optimization, or SEO. Should you pay your hard-earned dollars for a promise of getting more visibility in search results? The short answer is: no. For a longer answer read Paul Boag's article The Inconvenient Truth About SEO.

Examples
Finally here is a list of small business websites, that were built using the principles I outlined in this series: If you want to share a small business website that was built and hosted on the cheap, leave a comment, and if I find it interesting, I'll add it to the list. When recommending a website, include pertinent info, such as where the site is hosted, if it's free, if not, how much is the annual fee, etc. WARNING: All spam will be deleted without a reply.

Resources
250 Quick Web Design Tips (Part I)
Web Developer Checklist

<< Read Part IV

Part IV: Deployment (Building a small business website)

Summary: How to publish and promote your small business website.
In this section, I will explain how to improve visibility of your new small business website on the web. For other topics, see:

Table of contents How to publish your website?
Instructions for publishing your website under your custom domain will differ (they will mostly depend on the particular website builder and domain name registrar that you use), e.g.: After publishing and making sure that you can access your website using the custom domain name, test it to make sure that it looks and works as expected.

Getting the website indexed by search engines
Once your website is visible at your custom domain, submit it for indexing to Google and Microsoft Bing: To submit your new website to a search engine for indexing, you will need to create a free Google and Microsoft (Microsoft owns Bing) accounts (unless you already have existing ones). (NOTE: Don't forget to submit the sitemap URL to the search engine.)

Verify your website
Once you add a new website to a search engine you will need to pass the site verification process to confirm legal ownership. Your website builder should have instructions explaining how to verify your website, e.g.: I could not find good instructions explaining how to verify your website hosted at Wix, or how to verify a website hosted at any of the preferred website builder against Bing. If these options are not available, you can just submit your website to the search engine for indexing: Check if your website is indexed
It may take a few days for your website to appear in the search engine index. To check if your website is indexed, go to the search engine's home page and run a search for site: followed by the domain name of your website, e.g. site:myverysmallbusiness.com. If the search returns any results, it means that the website is indexed. If you do not see your website indexed after a week or so from submission, check the search engine's webmaster tools page for articles explaining common problems.

Set up Google Analytics
Google Analytics will collect site usage and statistics from your website. The steps will vary depending on your hosting platform, e.g: Add your business to Google and Bing Places for Business
If your business has a physical address, you can advertise it on Google Places for free. The process will be complete after you enter verification code (Google will send it to you via a postcard addressed to your business address or your business phone number). After verification, Google will display your small business information in the search results. You can use Google Places portal to monitor your site statistics, create coupons and promotions, and do other useful things. Do the same on Bing Places for Business.

Create a Facebook (and/or Google+) business page
If you do not have a fundamental opposition to using Facebook (as a marketing tool), create a Facebook page for your small business. Then share it with your friends. Here are some examples of a few Facebook pages created for local small businesses: As an alternative (or in addition) to Facebook, you can create a business page at Google+.

Write a blog
This advice is not for everyone, but if you are passionate about your business, can write reasonably well, and are eager to share insights with the world, create a blog and use it to share stories, ideas, tips, and tricks. You can create a free blog at Google's Blogger or WordPress.com (between the two, I'd recommend Blogger because its free version comes with fewer limitation; on the other hand, WordPress.com has a better editor, but it will also display ads to unsuspected viewers). You can also create a blog at most website builders, like the one that hosts your small business website, but I would keep your blog separate from the website in case you decide to move your website somewhere else. It would help if you name your blog after your website (e.g. myverysmallbusiness.blogspot.com). Keeping a blog requires dedication, so if you are not sure if this is something you want to do, then do not bother.

Get people talking
If you have satisfied customers, ask them to post honest reviews on social commentary sites, such as Yelp, Kudzu, Google Places, etc. If you get negative reviews, follow up with the unsatisfied customers so that the issues are resolved and corrections are noted.

<< Read Part III Read Part V >>

See also:
How to Use Google+ for Business (eBook)
Facebook for Business
50 Ways to Get Your Site Noticed
4 Easy Steps To Promote Your Business On Facebook

Monday, November 5, 2012

Part III: Development (Building a small business website)

Summary: Basics of small business website building.
In this section, I will share some tips that can help you build a small business website. For other topics, see:

Table of contents
At this point, I assume, you have picked a website builder and went through the beginner's tutorials (if these are not enough, there are lots of tutorials -- videos and articles -- available; just search for the name of your website builder and terms such as tutorial, getting started, introduction, beginner's guide, etc, e.g.: weebly beginner's tutorial).

Set up a dedicated email address
I suspect you already have an email address (possibly, more than one). If you only have a personal email address, create a new email account dedicated to your small business, so you can keep all of your business communication separate from your personal life. Just don't create it at your Internet Service Provider (ISP), such as Comcast, AT&T, Verizon, Cox, etc. Using an ISP-specific email addresses (whether personal, or group, or business) is never a good idea because you may need to switch to a different ISP and what would you do then? Migrate all your messages? Send new email address to your friends? Modify all your online profiles (at online stores, etc)? You can do this, but why deal with such hassle when you can get a fully functional email box at Google (GMail) for free? If you don't like Google's interface, you can forward all incoming messages to any other address (including your ISP's), so if you change your ISP, then you will just need to update your GMail message forwarding settings. [Note: At the time of writing, GMail was the only email provider that allowed you to forward incoming messages to external -- i.e. non-GMail -- accounts.] To summarize:
  • Use GMail.
  • Create a separate GMail account for your business (if you already have a Google account, you can link it to your existing Google profile).
  • Give your small business GMail account a meaningful name (ideally, it should be named after your business, e.g. myverysmallbusiness@gmail.com or myverysmallbusiness.owner@gmail.com).
  • Forward messages from your small business Gmail account to the one that you prefer (in case you have more than one email accounts).
Create a website
When you create a website, give it a meaningful title and address. The address will be temporary, until you're ready to publish it under your own domain name, but it can be helpful if addresses match. For example, if your custom domain name is myverysmallbusiness.com, then, assuming you create your website using Weebly, set the temporary address to myverysmallbusiness.weebly.com. The website title should reflect the name or the nature of your business. In my example, a reasonable title would be My Very Small Business. You can also include keywords that you may expect customers to use when they perform searches or append a location (if you operate locally), such as My Very Small Business: Gadgets and Gizmos in New York City, NY (this may help your website get better ranking). Just don't make the title too long.

Pick a website template
When picking a website template you need to think about aesthetics (it should look nice), performance (it must load fast), and function (it must support the layout and navigation needs). Here are a few rules of thumb:
  • Avoid overly flashy templates. Lots of graphics and big pictures generally take longer to load.
  • Less is more. Try picking a template with fewer elements. It may be easier to customize and tweak than a more complex template.
  • Use bigger font. If the website builder or specific template does not allow font customization, make sure that the font size is big enough. With population aging, bigger fonts will make your site more pleasing to more viewers.
  • Think cross-browser. See how the template looks in different web browsers. At the very least, try it in Internet Explorer, Google Chrome, Mozilla Firefox, and Safari.
  • No splash page. Your website should launch at the home page with useful information, not a useless animation, invitation to click the only link, or similar silliness.
  • Keep it quiet. Interaction with your website should be absolutely quiet. This means no "cool" sounds when user clicks links, flips pages, no greeting audio on the home page, et.
  • No autoplay. If you decide to embed video or audio, make sure it does not start to play automatically (the user must click the Play button to get it going).
If you see a website (maybe competitor's or unrelated) which design you really like, do not copy it. It's good to incorporate other people's ideas, but it's bad to make exact replicas (and it can be illegal, too).

Website structure
At the very least, your website must have the following pages:
  • Home: This is your introduction page. Use it to briefly describe your business and offer the information that would be useful to a potential customer. Don't make it too wordy.
  • Contact: Here you specify all the ways a customer can reach you: phone, fax, email, address. If you are operating a brick and mortar shop, include a map with a link to driving directions.
  • Portfolio*: If you have pictures to demonstrate your previous works or items on sale, put their photos on a separate page. This is a personal preference, but I would not use a slide show to display your work; I would use a photo gallery instead. The photo gallery will allow your customers to find what they look for quicker. If you have a lot of photos you want to share or if you continuously update them, I would keep a dozen or so of your best works on the website and store the rest at a different photo hosting site, such as Flickr or Picasa; then add a link to your web albums at the photo hosting site.
    * This is not the best name for the page, so try using something else that fits better for your purpose, such as Gallery, Photos, etc.
  • Services: If you offer fixed-price services, add a page that lists them. If you offer promotions or coupons, include this information as well (it can go to a separate page).
  • Resources: If you have links to useful information that you think can be helpful to your customers (even if they never contact you), include them in this page. Be a good citizen regardless of business impact (although, this can indirectly help you, too).
  • About: Use this page to offer a more detailed overview of your business. Specify when your business has been lunched and where it operates. List the terms of your workers compensation insurance. Include your business or permit license number. Use links to sources that customers can use to verify the information.
Web graphics
I'd recommend that at the first draft of your small business website, you do not put any pictures on the web pages (unless they are part of the template). Try to make it look nice without any graphics. Then add graphics but try to limit it to one primary graphics file per page (not counting smaller images, such as thumbnails or logos). Of course, you can break this rule if you have a valid reason.

Where to get graphics?
It is best to use your own graphics files. If you operate a brick and mortar business, you can take a photo of your shop. You may also want to display a photo of yourself and/or your employees and partners (make sure you get their permission in advance). If you include your business' history in the About page, photos from the past (most likely scanned) can make the information more interesting. When using your own images, make sure you optimize them for the web (e.g. trim white space, reduce picture dimensions, set JPEG quality to 80%).

Stock photos
It gets a bit tricky if you want to use stock photos. The basic rule is: do not copy photos from other sites (or link to them) unless you are absolutely sure that you will not violate the copyright laws (in most cases, you would). Some website builders (such as Weebly) allow you to easily search for and embed images in your web pages. You can also buy stock photos from such sites as iStockPhoto or get some for free from stock.xchng. You can also search for free images at GettyImagesFlickr, Google, or Creative Commons. Just make sure that you follow the terms of use for the particular license type (i.e. don't forget to include attribution when needed).

Writing for the web
When you add text to a web page, keep in mind the following rules. First, remember that people do not read business websites; they scan them for keywords and click the very first link that vaguely resembles a match. Therefore, do not write a composition. Use lists, short phrases, and brief paragraphs. Eliminate all unnecessary words. After your first draft, see if you can reduce the amount of text by half. Do it. Then try reducing what is left by half again. When you write text for a web page, use the exact combinations of keywords that you expect your potential customers to search for. This will help you get better page ranking.

Layout
When it comes to the web page layout, the simpler, the better. Use a simple layout and simple content. Don't try to impress people with sophistication (unless this is the nature of your business). Keep it minimal, keep it simple. Limit styles to the minimum. You should use at most 3 font sizes (one for headings, one for paragraphs, one for small print) and two font faces (one for headings and another for everything else).

Getting better
If you are a novice building your very first website, here are some books that can help you get better. If you were to get just one book on the topic, I'd recommend Steve Krug's Don't Make Me Think: A Common Sense Approach to Web Usability (this is a short and entertaining book, which I finished in a couple of evenings). The Non-Designer's Design Book by Robin Williams is a good primer that will help you understand the basic design principles.
Final touches
Do not publish your website (to your custom domain) until it's ready. If you publish a half-baked site, you will be penalized by search engines. When working on your website, and especially when making lots of changes, leave it for a few days and then visit it again. Taking a break from your website will give you a better perspective and help you catch the problems with a fresh eye. Before publishing the site, show it to someone and ask for an honest feedback. It would be helpful to find someone with background in web design and/or web development, but even without it, having more people to check out your work will help you find the things that you have missed. Also, make sure that you check the following:
  • Verify that the site works in all major web browsers (Internet Explorer, Chrome, Firefox, Safari).
  • Test it using a smart phone and/or a portable/mobile device, such as a tablet.
  • Inspect all content: text (make sure there are no error or typos), images, links (click on every link to see if it points to the right location), downloads (if you host any files, such as PDF documents).
Once you have reviewed and tested your website, you should be ready to publish it.

<< Read Part II Read Part IV >>

See also:
How to keep your text clean
10 Things Every Small-Business Website Needs
How To Make A Website - Free Tutorial
How to use photography in web design