Skip to content
ArtSuite (ArtEngine + ArtReact + ArtFlux) tutorial
JavaScript CoffeeScript HTML
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
cafSource
coffeeSource
docs
extlib
.gitignore
README.md
Server.caf
art.build.config.caf
caffeine-mc.config.caf
index.html
index.md
package.json
register.js
source
step01.coffee
step02.coffee
step03.coffee
step04.coffee
step05.coffee
tool
webpack.config.js

README.md

art-suite-tutorial

ArtSuite (ArtEngine + ArtReact + ArtFlux) tutorial

This tutorial shows how to make a realtime chat app in 5 easy steps.

Install and Run

git clone https://github.com/imikimi/art-suite-tutorial/
cd art-suite-tutorial
npm install
./node_modules/.bin/webpack-dev-server

Then go to: http://localhost:8080/webpack-dev-server/

To run Step 5, you also need to start a local DynamoDb server. Open up another terminal window:

cd art-suite-tutorial
./node_modules/art-aws/start_dynamo_db_local_server.coffee

In 5 Steps

Steps 1-3 lay the foundations and are all non-interactive. Step 4 adds real interactivity, and Step 5 adds a real back-end database.

step01: Hello world! (run)

# step01/Main.caf
&ArtSuiteApp.initArtSuiteClient
  MainComponent: &App
  title:         :Chat-App

# step01/App.caf
import &ArtSuite

class App extends Component

  render: ->
    CanvasElement
      draw: #eee

      TextElement
        padding:  10
        fontSize: 25
        text:     "" Hello world!

Step 2: ArtEngine and ArtReact UI Basics & Hot Loading (+ChatView) (run)

Step 2 jumps right in and builds out a large chunk of the UI, and yet, it doesn't require much code. The entirety of changes from Step 1 are listed below.

# step02/Main.caf - no change
# step02/App.caf
import &ArtSuite

class App extends Component

  render: ->
    CanvasElement
      draw: #eee

      Element
        childrenLayout: :row
        childrenMargins: 10
        padding: 10

        &ChatView currentUser: :Alice
        &ChatView currentUser: :Bill

# step02/ChatView.caf
import &ArtSuite

class ChatView extends Component

  render: ->
    {currentUser} = @props

    Element
      childrenLayout:     :column

      draw:
        color:            :white
        shadow:
          blur:           10
          offset:         y: 3
          color:          #0007

      Element
        size:             hch: 1
        draw:             #00bcd4
        TextElement
          color:          :white
          fontFamily:     :sans-serif
          padding:        10
          text:           currentUser

      TextElement
        size:             hh: 1
        fontFamily:       :sans-serif
        padding:          10
        opacity:          .25
        text:             "" (messages go here)

      Element
        size:             h: 45
        draw:             #eee
        TextInputElement
          fontFamily:     :sans-serif
          padding:        10
          placeholder:    "" new message from #{currentUser}

Step 3: Styles (+ChatMessage +StyleProps) (run)

Step 3 adds the ChatMessage view and shows how you can do styles. Here is a partial listing:

# step03/Main.caf - no change
# step03/App.caf - no change
# step03/Palette.caf
import &ArtSuite

class Palette extends HotStyleProps
  @primaryBackground:      #00bcd4
  @lightPrimaryBackground: #c7ebf0
  @grayBackground:         #eee

  @white: primary: #fffe
  @black: primary: #000e   secondary: #0007

# step03/StyleProps.caf
import &ArtSuite

class StyleProps extends HotStyleProps

  @titleText:
    color:      &Palette.white.primary
    fontFamily: :sans-serif
    fontSize:   16

  @mediumText:
    color:      &Palette.black.primary
    fontFamily: :sans-serif
    fontSize:   16

  @smallText:
    color:      &Palette.black.primary
    fontFamily: :sans-serif
    fontSize:   12

  @chatViewBackground:
    color:      :white
    shadow:
      blur:     10
      offsetY:  3
      color:    #0007

# step03/ChatMessage.caf
import &ArtSuite, &StyleProps

class ChatMessage extends Component

  render: ->
    {currentUser, user, message} = @props

    currentUsersMessage = user == currentUser

    Element
      margin:           10
      size:             hch: 1
      childrenLayout:   :row
      animators:
        size: toFrom:   h: 0
        axis: toFrom:   x: if currentUsersMessage then -1 else 1

      Element
        size:               hch: 1
        childrenLayout:     :column
        childrenMargins:    5
        childrenAlignment:  if currentUsersMessage then :right else :left

        Element
          size: cs: 1   max: ww: 1
          if currentUsersMessage
            axis:     x:  1
            location: xw: 1

          draw:
            if currentUsersMessage
              &Palette.lightPrimaryBackground
            else
              &Palette.grayBackground

          TextElement
            mediumText
            padding:  10
            text:     message
            size:     cs: 1   max: ww:1

        TextElement
          smallText
          text:   user
          color:  &Palette.black.secondary

# step03/ChatView.caf
import &ArtSuite

class ChatView extends Component

  history:
    # Some fake history
    {} user: :Alice   message: "" Hi!
    {} user: :Bill    message: "" Hi, Alice!
    {} user: :Alice   message: "" How have you been?

  render: ->
    Element
      childrenLayout: :column
      draw: &StyleProps.chatViewBackground

      Element
        size: hch:1
        draw: &Palette.primaryBackground

        TextElement
          &StyleProps.titleText
          padding:  10
          text:     @props.currentUser

      ScrollElement
        clip: true

        Element
          padding:        10
          size:           hch: 1
          childrenLayout: :column

          array postMessage from @history
            &ChatMessage
              postMessage
              {} @props.currentUser

      Element
        size: h: 45
        draw: &Palette.grayBackground

        TextInputElement
          &StyleProps.mediumText
          padding:      10
          placeholder:  "" new message from #{@props.currentUser}

Step 4: ArtFlux with local data (+ChatModel) (run)

Step 4 adds a local FluxModel for storing state. Finally the chat actually works! Alice and Bill can post messages to each other. Here is all the gist of the new code:

# step04/Main.caf - no change
# step04/App.caf - no change
# step04/Palette.caf - no change
# step04/ChatMessage.caf - no change

# step04/ChatModel.caf
import &ArtSuite

class Chat extends ApplicationState

  @stateFields
    history: []

  postMessage: (user, message) ->
    @history = arrayWith @history, {} user, message

# step04/ChatView.caf
import &ArtSuite

class ChatView extends FluxComponent
  # NEW in Step 4
  @subscriptions :chat.history

  # NEW in Step 4
  postMessage: ({target}) ->
    @models.chat.postMessage @props.currentUser, target.value
    target.value = ""

  render: ->
    Element
      childrenLayout: :column
      draw: &StyleProps.chatViewBackground

      Element
        size: hch:1
        draw: &Palette.primaryBackground

        TextElement
          &StyleProps.titleText
          padding: 10
          text: @props.currentUser

      ScrollElement
        clip: true

        Element
          padding:        10
          size:           hch: 1
          childrenLayout: :column

          array postMessage from @history
            &ChatMessage
              postMessage
              {} @props.currentUser

      Element
        size: h: 45
        draw: &Palette.grayBackground

        TextInputElement
          &StyleProps.mediumText
          on: enter: @postMessage # NEW in Step 4
          padding: 10
          placeholder: "" new message from #{@props.currentUser}

Step 5: ArtFlux with remote Data on DynamoDb

Step 5 introduces remote data. It uses DynamoDb as an example. To run, follow the Install instructions above.

Learn More

See the Art Suite Wiki

You can’t perform that action at this time.