SlideShare uma empresa Scribd logo
1 de 112
Baixar para ler offline
Building a desktop app with
                   HTTP::Engine, SQLite & jQuery
                              Tatsuhiko Miyagawa
                           YAPC::NA 2009 Pittsburgh




Wednesday, June 24, 2009
Tatsuhiko Miyagawa



Wednesday, June 24, 2009
Wednesday, June 24, 2009
Software Engineer, TypePad
Wednesday, June 24, 2009
cpan: MIYAGAWA



Wednesday, June 24, 2009
Acme-DateTime-Duration-Numeric Acme-Module-Authors Acme-Sneeze Acme-Sneeze-JP Apache-ACEProxy Apache-
          AntiSpam Apache-Clickable Apache-CustomKeywords Apache-DefaultCharset Apache-GuessCharset Apache-JavaScript-
         DocumentWrite Apache-No404Proxy Apache-Profiler Apache-Session-CacheAny Apache-Session-Generate-ModUniqueId
          Apache-Session-Generate-ModUsertrack Apache-Session-PHP Apache-Session-Serialize-YAML Apache-Singleton Apache-
           StickyQuery Archive-Any-Create Attribute-Profiled Attribute-Protected Attribute-Unimplemented Bundle-Sledge CGI-
        Untaint-email CPAN-Mini-Growl Catalyst-Plugin-Authentication-Credential-AOL Catalyst-Plugin-Authentication-Credential-
            OpenID Catalyst-Plugin-JSONRPC Catalyst-View-JSON Catalyst-View-Jemplate Class-DBI-AbstractSearch Class-DBI-
        Extension Class-DBI-Pager Class-DBI-Replication Class-DBI-SQLite Class-DBI-View Class-Trigger Convert-Base32 Convert-
        DUDE Convert-RACE Data-YUID Date-Japanese-Era Date-Range-Birth DateTime-Span-Birthdate Device-KeyStroke-Mobile
         Dunce-time Email-Find Email-Valid-Loose Encode-DoubleEncodedUTF8 Encode-First Encode-JP-Mobile Encode-JavaScript-
            UCS Encode-Punycode File-Find-Rule-Digest File-Spotlight Geo-Coder-Google HTML-AutoPagerize HTML-Entities-
          ImodePictogram HTML-RelExtor HTML-ResolveLink HTML-Selector-XPath HTML-XSSLint HTTP-MobileAgent HTTP-
          ProxyPAC HTTP-Server-Simple-Authen HTTP-Server-Simple-Bonjour IDNA-Punycode Inline-Basic Inline-TT JSON-Syck
        Kwiki-Emoticon Kwiki-Export Kwiki-Footnote Kwiki-OpenSearch Kwiki-OpenSearch-Service Kwiki-TypeKey Kwiki-URLBL
            LWP-UserAgent-Keychain Lingua-JA-Hepburn-Passport Log-Dispatch-Config Log-Dispatch-DBI MSIE-MenuExt Mac-
         Macbinary Mail-Address-MobileJp Mail-ListDetector-Detector-Fml Module-Install-Repository Net-DAAP-Server-AAC Net-
          IDN-Nameprep Net-IPAddr-Find Net-Twitter-OAuth Net-YahooMessenger NetAddr-IP-Find P2P-Transmission-Remote
          PHP-Session POE-Component-Client-AirTunes POE-Component-Client-Lingr POE-Component-YahooMessenger Path-
         Class-URI Plagger RPC-XML-Parser-LibXML Template-Plugin-Clickable Template-Plugin-Comma Template-Plugin-FillInForm
           Template-Plugin-HTML-Template Template-Plugin-JavaScript Template-Plugin-MobileAgent Template-Plugin-ResolveLink
             Template-Plugin-Shuffle Template-Provider-Encoding Term-Encoding Term-TtyRec Test-Synopsis Text-Emoticon Text-
         Emoticon-GoogleTalk Text-Emoticon-MSN Text-Emoticon-Yahoo Text-MessageFormat TheSchwartz-Simple Time-Duration-
        Parse Time-Duration-ja URI-Find-UTF8 URI-git URI-tag URI-urn-uuid Video-Subtitle-SRT WWW-Baseball-NPB WWW-Blog-
         Metadata-MobileLinkDiscovery WWW-Blog-Metadata-OpenID WWW-Blog-Metadata-OpenSearch WWW-Cache-Google
          WWW-Mechanize-AutoPager WWW-Mechanize-DecodedContent WWW-NicoVideo-Download WWW-OpenSearch
           WWW-Shorten-RevCanonical WWW-Shorten-Simple Web-Scraper Web-oEmbed WebService-Bloglines WebService-
           ChangesXml WebService-Google-Suggest WebService-Lingr XML-Atom XML-Atom-Lifeblog XML-Atom-Stream XML-
                       Liberal XML-OPML-LibXML abbreviation autobox-DateTime-Duration capitalization plagger




Wednesday, June 24, 2009
twitter.com/miyagawa
                           (Slides will be linked. Follow me!)




Wednesday, June 24, 2009
Remedie

Wednesday, June 24, 2009
remediecode.org
                           Slides/Video in OSDC.TW




Wednesday, June 24, 2009
Building a desktop app with
                   HTTP::Engine, SQLite & jQuery
                              Tatsuhiko Miyagawa
                           YAPC::NA 2009 Pittsburgh




Wednesday, June 24, 2009
Desktop GUI apps



Wednesday, June 24, 2009
MFC/.NET
                           Visual C++,VB


Wednesday, June 24, 2009
wxWidgets



Wednesday, June 24, 2009
Objective-C
                               Cocoa
                           (PyObjC/RubyCocoa)



Wednesday, June 24, 2009
Adobe AIR



Wednesday, June 24, 2009
I’m a Perl guy
                    who knows JavaScript.


Wednesday, June 24, 2009
Web Developers!
Wednesday, June 24, 2009
Web app!



Wednesday, June 24, 2009
“Web 2.0 iPhone App”
                           Steve Jobs at WWDC 2007
Wednesday, June 24, 2009
Wednesday, June 24, 2009
PhoneGap
Wednesday, June 24, 2009
HTML5
                           geolocation, videos
                              local storage



Wednesday, June 24, 2009
HTML5 = Future
                             ??? = 2009


Wednesday, June 24, 2009
micro Web app = 2009



Wednesday, June 24, 2009
(2 min Demo video)
Wednesday, June 24, 2009
How I built this



Wednesday, June 24, 2009
Building a desktop app with
                   HTTP::Engine, SQLite & jQuery
                              Tatsuhiko Miyagawa
                           YAPC::NA 2009 Pittsburgh




Wednesday, June 24, 2009
“The most important
               project in Perl recently”
                      - jrockway


Wednesday, June 24, 2009
Based on
                           Catalyst::Engine


Wednesday, June 24, 2009
Ruby’s Rack
                           Python’s WSGI


Wednesday, June 24, 2009
use HTTP::Engine;
                  my $engine = HTTP::Engine‐>new(
                      interface => {
                          module => 'ServerSimple',
                          args   => {
                              host => 'localhost',
                              port => 9898,
                          },
                      request_handler => &handle_request,
                  });

                  $engine‐>run;




Wednesday, June 24, 2009
sub handle_request {
                      my $req = shift;
                      return HTTP::Engine::Response‐>new(
                          body => “Hello World”,
                      );
                  }




Wednesday, June 24, 2009
Standalone,
                           ServerSimple, POE,
                           FastCGI, mod_perl


Wednesday, June 24, 2009
Desktop app:
                             ServerSimple
                           POE (non-blocking)


Wednesday, June 24, 2009
Serve static files
                           (HTML/CSS/JS)


Wednesday, June 24, 2009
sub handle_request {
          my($self, $req) = @_;

          my $path = $req‐>path;
          my $res = HTTP::Engine::Response‐>new;

          if ($path =~ s!^/static/!!) {
              $self‐>serve_static_file($path, $req, $res);
          };

          return $res;
      }




Wednesday, June 24, 2009
use Path::Class;
                sub serve_static_file {
                    my($self, $path, $req, $res) = @_;

                    my $root = $self‐>conf‐>{root};
                    my $file = file($root, "static", $path);

                    my $size  = ‐s _;
                    my $mtime = (stat(_))[9];
                    my $ext = ($file =~ /.(w+)$/)[0];
                    $res‐>content_type( MIME::Types‐>new‐>mimeTypeOf($ext)
                        || "text/plain" );
                    # ...
                    open my $fh, "<:raw", $file
                        or die "$file: $!";
                    $res‐>headers‐>header('Last‐Modified' =>
                         HTTP::Date::time2str($mtime));
                    $res‐>headers‐>header('Content‐Length' => $size);
                    $res‐>body( join '', <$fh> );
                }




Wednesday, June 24, 2009
See Also:
                           HTTP::Engine::Middleware::Static




Wednesday, June 24, 2009
Implement Ajax
                           backend actions
                            (JSON-REST)


Wednesday, June 24, 2009
sub handle_request {
                my($self, $req) = @_;

                my $path = $req‐>path;

                my $res = HTTP::Engine::Response‐>new;

                if ($path =~ s!^/rpc/!!) {
                    $self‐>dispatch_rpc($path, $req, $res);
                }
            }




Wednesday, June 24, 2009
sub dispatch_rpc {
                my($self, $path, $req, $res) = @_;

                my @class  = split '/', $path;
                my $method = pop @class;
                die "Access to non‐public methods" if $method =~ /^_/;

                my $rpc_class = $self‐>load_rpc_class(@class);
                my $rpc = $rpc_class‐>new( conf => $self‐>conf );
                my $result = eval { $rpc‐>$method($req, $res) };

                unless ( $res‐>body ) {
                    $res‐>status(200);
                    $res‐>content_type("application/json; charset=utf‐8");
                    $res‐>body( Remedie::JSON‐>encode($result) );
                }
            }




Wednesday, June 24, 2009
Problem (1):
                           Dirty API routing


Wednesday, June 24, 2009
Path::Router, Path::Dispatcher,
                        HTTP::Dispatcher, JSORB




Wednesday, June 24, 2009
Problem (2):
                           Vulnerable (CSRF)


Wednesday, June 24, 2009
Authentication
                             Special Headers
                           Switch to JSONRPC


Wednesday, June 24, 2009
Bonjour
               (based on HTTP::Server::Simple::Bonjour)




Wednesday, June 24, 2009
Auto Discovery
                           Share subscriptions


Wednesday, June 24, 2009
Wednesday, June 24, 2009
Building a desktop app with
                   HTTP::Engine, SQLite & jQuery
                              Tatsuhiko Miyagawa
                           YAPC::NA 2009 Pittsburgh




Wednesday, June 24, 2009
SQL DB choices



Wednesday, June 24, 2009
MySQL/PostgreSQL
                           Good for Web apps.


Wednesday, June 24, 2009
SQLite:
                           file-based, type-less
                              Transactional


Wednesday, June 24, 2009
SQLite:
                      best for desktop apps


Wednesday, June 24, 2009
SQLite for desktop:
                           Firefox, Mail.app, iCal


Wednesday, June 24, 2009
End-users don’t want
                        to run *SQL server


Wednesday, June 24, 2009
Bonus:
                           Easy backup,
                           Dropbox sync


Wednesday, June 24, 2009
DB Schema



Wednesday, June 24, 2009
You don’t need DBA.
                     Make it simple, flexible and extensible.




Wednesday, June 24, 2009
Remedie schema
                              Few indexes
                            JSON key-values



Wednesday, June 24, 2009
CREATE TABLE channel (
       id      INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
       type    INTEGER NOT NULL,
       parent  INTEGER NOT NULL,
       ident   TEXT NOT NULL,
       name    TEXT NOT NULL,
       props   TEXT
     );

     CREATE UNIQUE INDEX channel_ident ON channel (ident);




Wednesday, June 24, 2009
CREATE TABLE item (
       id         INTEGER NOT NULL PRIMARY KEY 
     AUTOINCREMENT,
       channel_id INTEGER NOT NULL,
       type       INTEGER NOT NULL,
       ident      TEXT NOT NULL,
       name       TEXT NOT NULL,
       status     INTEGER NOT NULL,
       props      TEXT
     );

     CREATE INDEX item_status ON item (status)

     CREATE UNIQUE INDEX item_ident ON item (channel_id, 
     ident);




Wednesday, June 24, 2009
Key-Value is HOT



Wednesday, June 24, 2009
CouchDB, MongoDB
                          TokyoTyrant
                           (Need servers though)




Wednesday, June 24, 2009
SQLite for Key-Value



Wednesday, June 24, 2009
ORM?



Wednesday, June 24, 2009
Anything you like.



Wednesday, June 24, 2009
DBIx::Class
                           Rose::DB::Object


Wednesday, June 24, 2009
Rose::DB::Object
                            (I wanted some excuse)




Wednesday, June 24, 2009
See Also:
                           KiokuDB


Wednesday, June 24, 2009
KiokuDB
                           DBI / SQLite backend
                            Key-Value JSPON



Wednesday, June 24, 2009
Building a desktop app with
                   HTTP::Engine, SQLite & jQuery
                              Tatsuhiko Miyagawa
                           YAPC::NA 2009 Pittsburgh




Wednesday, June 24, 2009
Just use normal HTML
                    and CSS to design UI


Wednesday, June 24, 2009
Manipulate DOM
                           $.ajax to do Ajax


Wednesday, June 24, 2009
DOM Manipulation sucks.




Wednesday, June 24, 2009
jQuery.flydom



Wednesday, June 24, 2009
$("#channel‐pane").createAppend(
       'div', { className: 'channel‐header',
                id: 'channel‐header‐' + channel.id  }, [
         'div', { className: 'channel‐header‐thumb' }, [
            'img', { src: "/static/images/feed.png",
                     alt: channel.name }, null
         ],
       ]
     );




Wednesday, June 24, 2009
jQuery.hotkeys



Wednesday, June 24, 2009
$(document).bind(‘keydown’, ‘shift+n’, function(ev){
        // ‘N’ is entered
     });




Wednesday, June 24, 2009
jQuery.contextMenu



Wednesday, June 24, 2009
Wednesday, June 24, 2009
jQuery.corners



Wednesday, June 24, 2009
Wednesday, June 24, 2009
$.event.trigger
                           $(document).bind


Wednesday, June 24, 2009
jQuery UI



Wednesday, June 24, 2009
Fancy stuff
                           like Drag & Drop


Wednesday, June 24, 2009
jQuery.blockUI
                           jQuery.scrollTo
                            jQuery.jgrowl


Wednesday, June 24, 2009
Building a desktop app with
                   HTTP::Engine, SQLite & jQuery
                              Tatsuhiko Miyagawa
                           YAPC::NA 2009 Pittsburgh




Wednesday, June 24, 2009
More like
                           “Desktop app”


Wednesday, June 24, 2009
Client-Server



Wednesday, June 24, 2009
Web Client as “app”



Wednesday, June 24, 2009
Site Specific Browser



Wednesday, June 24, 2009
Fluid
                           Prism


Wednesday, June 24, 2009
Wednesday, June 24, 2009
Customize
               Userscripts / Userstyles


Wednesday, June 24, 2009
Fluid hooks
                           Growl integration
                             Dock menu


Wednesday, June 24, 2009
Wednesday, June 24, 2009
Client-Server
                           Decoupled via APIs


Wednesday, June 24, 2009
More Clients
                           More “Views”


Wednesday, June 24, 2009
iPhone



Wednesday, June 24, 2009
Wednesday, June 24, 2009
Wednesday, June 24, 2009
120 lines of HTML/JS
                         using iUI project


Wednesday, June 24, 2009
Server as “app”



Wednesday, June 24, 2009
Packaging a server



Wednesday, June 24, 2009
local::lib
                      build & install all deps


Wednesday, June 24, 2009
Also:
                           Shipwright


Wednesday, June 24, 2009
Platypus
                           Make .app


Wednesday, June 24, 2009
Download .zip, copy .app to
                             /Applications, Run it.
Wednesday, June 24, 2009
Also:
                      github.com/miyagawa/perl-app-builder




Wednesday, June 24, 2009
Summary

                   • micro web server as a desktop app
                   • HTTP::Engine, JSONRPC and router
                   • SQLite to store key-value
                   • jQuery plugins to enable desktop UIs
                   • More tools to make it really “.app”

Wednesday, June 24, 2009
That’s it!
                           Questions?


Wednesday, June 24, 2009
Thank you!
                     twitter.com/miyagawa


Wednesday, June 24, 2009

Mais conteúdo relacionado

Mais procurados

Deploying Plack Web Applications: OSCON 2011
Deploying Plack Web Applications: OSCON 2011Deploying Plack Web Applications: OSCON 2011
Deploying Plack Web Applications: OSCON 2011
Tatsuhiko Miyagawa
 
Psgi Plack Sfpm
Psgi Plack SfpmPsgi Plack Sfpm
Psgi Plack Sfpm
som_nangia
 
Web frameworks don't matter
Web frameworks don't matterWeb frameworks don't matter
Web frameworks don't matter
Tomas Doran
 
Ruby HTTP clients comparison
Ruby HTTP clients comparisonRuby HTTP clients comparison
Ruby HTTP clients comparison
Hiroshi Nakamura
 

Mais procurados (20)

Deploying Plack Web Applications: OSCON 2011
Deploying Plack Web Applications: OSCON 2011Deploying Plack Web Applications: OSCON 2011
Deploying Plack Web Applications: OSCON 2011
 
Plack basics for Perl websites - YAPC::EU 2011
Plack basics for Perl websites - YAPC::EU 2011Plack basics for Perl websites - YAPC::EU 2011
Plack basics for Perl websites - YAPC::EU 2011
 
No callbacks, No Threads - Cooperative web servers in Ruby 1.9
No callbacks, No Threads - Cooperative web servers in Ruby 1.9No callbacks, No Threads - Cooperative web servers in Ruby 1.9
No callbacks, No Threads - Cooperative web servers in Ruby 1.9
 
PSGI and Plack from first principles
PSGI and Plack from first principlesPSGI and Plack from first principles
PSGI and Plack from first principles
 
Modern Perl
Modern PerlModern Perl
Modern Perl
 
Psgi Plack Sfpm
Psgi Plack SfpmPsgi Plack Sfpm
Psgi Plack Sfpm
 
Web frameworks don't matter
Web frameworks don't matterWeb frameworks don't matter
Web frameworks don't matter
 
A reviravolta do desenvolvimento web
A reviravolta do desenvolvimento webA reviravolta do desenvolvimento web
A reviravolta do desenvolvimento web
 
Sinatra for REST services
Sinatra for REST servicesSinatra for REST services
Sinatra for REST services
 
Web Development in Perl
Web Development in PerlWeb Development in Perl
Web Development in Perl
 
Mojolicious
MojoliciousMojolicious
Mojolicious
 
"Swoole: double troubles in c", Alexandr Vronskiy
"Swoole: double troubles in c", Alexandr Vronskiy"Swoole: double troubles in c", Alexandr Vronskiy
"Swoole: double troubles in c", Alexandr Vronskiy
 
How to test code with mruby
How to test code with mrubyHow to test code with mruby
How to test code with mruby
 
DevOps tools for everyone - Vagrant, Puppet and Webmin
DevOps tools for everyone - Vagrant, Puppet and WebminDevOps tools for everyone - Vagrant, Puppet and Webmin
DevOps tools for everyone - Vagrant, Puppet and Webmin
 
Ruby HTTP clients comparison
Ruby HTTP clients comparisonRuby HTTP clients comparison
Ruby HTTP clients comparison
 
Modern Web Development with Perl
Modern Web Development with PerlModern Web Development with Perl
Modern Web Development with Perl
 
Deploying Symfony | symfony.cat
Deploying Symfony | symfony.catDeploying Symfony | symfony.cat
Deploying Symfony | symfony.cat
 
Webinar: Building Your First App in Node.js
Webinar: Building Your First App in Node.jsWebinar: Building Your First App in Node.js
Webinar: Building Your First App in Node.js
 
Speed up web APIs with Expressive and Swoole (PHP Day 2018)
Speed up web APIs with Expressive and Swoole (PHP Day 2018) Speed up web APIs with Expressive and Swoole (PHP Day 2018)
Speed up web APIs with Expressive and Swoole (PHP Day 2018)
 
Using Sinatra to Build REST APIs in Ruby
Using Sinatra to Build REST APIs in RubyUsing Sinatra to Build REST APIs in Ruby
Using Sinatra to Build REST APIs in Ruby
 

Semelhante a Building a desktop app with HTTP::Engine, SQLite and jQuery

Intro to PHP Testing
Intro to PHP TestingIntro to PHP Testing
Intro to PHP Testing
Ran Mizrahi
 
The symfony platform: Create your very own framework (PHP Quebec 2008)
The symfony platform: Create your very own framework (PHP Quebec 2008)The symfony platform: Create your very own framework (PHP Quebec 2008)
The symfony platform: Create your very own framework (PHP Quebec 2008)
Fabien Potencier
 
Socket applications
Socket applicationsSocket applications
Socket applications
João Moura
 
ZendCon2010 The Doctrine Project
ZendCon2010 The Doctrine ProjectZendCon2010 The Doctrine Project
ZendCon2010 The Doctrine Project
Jonathan Wage
 
symfony on action - WebTech 207
symfony on action - WebTech 207symfony on action - WebTech 207
symfony on action - WebTech 207
patter
 

Semelhante a Building a desktop app with HTTP::Engine, SQLite and jQuery (20)

Lone StarPHP 2013 - Building Web Apps from a New Angle
Lone StarPHP 2013 - Building Web Apps from a New AngleLone StarPHP 2013 - Building Web Apps from a New Angle
Lone StarPHP 2013 - Building Web Apps from a New Angle
 
And the Greatest of These Is ... Space
And the Greatest of These Is ... SpaceAnd the Greatest of These Is ... Space
And the Greatest of These Is ... Space
 
Xopus Application Framework
Xopus Application FrameworkXopus Application Framework
Xopus Application Framework
 
Charla EHU Noviembre 2014 - Desarrollo Web
Charla EHU Noviembre 2014 - Desarrollo WebCharla EHU Noviembre 2014 - Desarrollo Web
Charla EHU Noviembre 2014 - Desarrollo Web
 
関西アンカンファレンス PHP ではじめるテストコード
関西アンカンファレンス PHP ではじめるテストコード関西アンカンファレンス PHP ではじめるテストコード
関西アンカンファレンス PHP ではじめるテストコード
 
Intro to PHP Testing
Intro to PHP TestingIntro to PHP Testing
Intro to PHP Testing
 
Node js实践
Node js实践Node js实践
Node js实践
 
The symfony platform: Create your very own framework (PHP Quebec 2008)
The symfony platform: Create your very own framework (PHP Quebec 2008)The symfony platform: Create your very own framework (PHP Quebec 2008)
The symfony platform: Create your very own framework (PHP Quebec 2008)
 
HTML 5 - Overview
HTML 5 - OverviewHTML 5 - Overview
HTML 5 - Overview
 
Web Crawling with NodeJS
Web Crawling with NodeJSWeb Crawling with NodeJS
Web Crawling with NodeJS
 
Consegi 2010 - Dicas de Desenvolvimento Web com Ruby
Consegi 2010 - Dicas de Desenvolvimento Web com RubyConsegi 2010 - Dicas de Desenvolvimento Web com Ruby
Consegi 2010 - Dicas de Desenvolvimento Web com Ruby
 
Socket applications
Socket applicationsSocket applications
Socket applications
 
Sprockets
SprocketsSprockets
Sprockets
 
Building Smart Workflows - Dan Diebolt
Building Smart Workflows - Dan DieboltBuilding Smart Workflows - Dan Diebolt
Building Smart Workflows - Dan Diebolt
 
ZendCon2010 The Doctrine Project
ZendCon2010 The Doctrine ProjectZendCon2010 The Doctrine Project
ZendCon2010 The Doctrine Project
 
SymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years later
SymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years laterSymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years later
SymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years later
 
AFUP Lorraine - Symfony Webpack Encore
AFUP Lorraine - Symfony Webpack EncoreAFUP Lorraine - Symfony Webpack Encore
AFUP Lorraine - Symfony Webpack Encore
 
Selenium & PHPUnit made easy with Steward (Berlin, April 2017)
Selenium & PHPUnit made easy with Steward (Berlin, April 2017)Selenium & PHPUnit made easy with Steward (Berlin, April 2017)
Selenium & PHPUnit made easy with Steward (Berlin, April 2017)
 
symfony on action - WebTech 207
symfony on action - WebTech 207symfony on action - WebTech 207
symfony on action - WebTech 207
 
soft-shake.ch - Hands on Node.js
soft-shake.ch - Hands on Node.jssoft-shake.ch - Hands on Node.js
soft-shake.ch - Hands on Node.js
 

Mais de Tatsuhiko Miyagawa

Carton CPAN dependency manager
Carton CPAN dependency managerCarton CPAN dependency manager
Carton CPAN dependency manager
Tatsuhiko Miyagawa
 
Asynchronous programming with AnyEvent
Asynchronous programming with AnyEventAsynchronous programming with AnyEvent
Asynchronous programming with AnyEvent
Tatsuhiko Miyagawa
 
Why Open Matters It Pro Challenge 2008
Why Open Matters It Pro Challenge 2008Why Open Matters It Pro Challenge 2008
Why Open Matters It Pro Challenge 2008
Tatsuhiko Miyagawa
 
20 modules i haven't yet talked about
20 modules i haven't yet talked about20 modules i haven't yet talked about
20 modules i haven't yet talked about
Tatsuhiko Miyagawa
 
Web Scraper Shibuya.pm tech talk #8
Web Scraper Shibuya.pm tech talk #8Web Scraper Shibuya.pm tech talk #8
Web Scraper Shibuya.pm tech talk #8
Tatsuhiko Miyagawa
 

Mais de Tatsuhiko Miyagawa (17)

Carton CPAN dependency manager
Carton CPAN dependency managerCarton CPAN dependency manager
Carton CPAN dependency manager
 
cpanminus at YAPC::NA 2010
cpanminus at YAPC::NA 2010cpanminus at YAPC::NA 2010
cpanminus at YAPC::NA 2010
 
CPAN Realtime feed
CPAN Realtime feedCPAN Realtime feed
CPAN Realtime feed
 
Asynchronous programming with AnyEvent
Asynchronous programming with AnyEventAsynchronous programming with AnyEvent
Asynchronous programming with AnyEvent
 
Remedie OSDC.TW
Remedie OSDC.TWRemedie OSDC.TW
Remedie OSDC.TW
 
Why Open Matters It Pro Challenge 2008
Why Open Matters It Pro Challenge 2008Why Open Matters It Pro Challenge 2008
Why Open Matters It Pro Challenge 2008
 
20 modules i haven't yet talked about
20 modules i haven't yet talked about20 modules i haven't yet talked about
20 modules i haven't yet talked about
 
Web::Scraper for SF.pm LT
Web::Scraper for SF.pm LTWeb::Scraper for SF.pm LT
Web::Scraper for SF.pm LT
 
Web Scraper Shibuya.pm tech talk #8
Web Scraper Shibuya.pm tech talk #8Web Scraper Shibuya.pm tech talk #8
Web Scraper Shibuya.pm tech talk #8
 
Web::Scraper
Web::ScraperWeb::Scraper
Web::Scraper
 
XML::Liberal
XML::LiberalXML::Liberal
XML::Liberal
 
Test::Base
Test::BaseTest::Base
Test::Base
 
Hacking Vox and Plagger
Hacking Vox and PlaggerHacking Vox and Plagger
Hacking Vox and Plagger
 
Plagger the duct tape of internet
Plagger the duct tape of internetPlagger the duct tape of internet
Plagger the duct tape of internet
 
Tilting Google Maps and MissileLauncher
Tilting Google Maps and MissileLauncherTilting Google Maps and MissileLauncher
Tilting Google Maps and MissileLauncher
 
Writing Pluggable Software
Writing Pluggable SoftwareWriting Pluggable Software
Writing Pluggable Software
 
How we build Vox
How we build VoxHow we build Vox
How we build Vox
 

Último

Mifty kit IN Salmiya (+918133066128) Abortion pills IN Salmiyah Cytotec pills
Mifty kit IN Salmiya (+918133066128) Abortion pills IN Salmiyah Cytotec pillsMifty kit IN Salmiya (+918133066128) Abortion pills IN Salmiyah Cytotec pills
Mifty kit IN Salmiya (+918133066128) Abortion pills IN Salmiyah Cytotec pills
Abortion pills in Kuwait Cytotec pills in Kuwait
 
Jual Obat Aborsi ( Asli No.1 ) 085657271886 Obat Penggugur Kandungan Cytotec
Jual Obat Aborsi ( Asli No.1 ) 085657271886 Obat Penggugur Kandungan CytotecJual Obat Aborsi ( Asli No.1 ) 085657271886 Obat Penggugur Kandungan Cytotec
Jual Obat Aborsi ( Asli No.1 ) 085657271886 Obat Penggugur Kandungan Cytotec
ZurliaSoop
 
Mifepristone Available in Muscat +918761049707^^ €€ Buy Abortion Pills in Oman
Mifepristone Available in Muscat +918761049707^^ €€ Buy Abortion Pills in OmanMifepristone Available in Muscat +918761049707^^ €€ Buy Abortion Pills in Oman
Mifepristone Available in Muscat +918761049707^^ €€ Buy Abortion Pills in Oman
instagramfab782445
 
unwanted pregnancy Kit [+918133066128] Abortion Pills IN Dubai UAE Abudhabi
unwanted pregnancy Kit [+918133066128] Abortion Pills IN Dubai UAE Abudhabiunwanted pregnancy Kit [+918133066128] Abortion Pills IN Dubai UAE Abudhabi
unwanted pregnancy Kit [+918133066128] Abortion Pills IN Dubai UAE Abudhabi
Abortion pills in Kuwait Cytotec pills in Kuwait
 

Último (20)

PHX May 2024 Corporate Presentation Final
PHX May 2024 Corporate Presentation FinalPHX May 2024 Corporate Presentation Final
PHX May 2024 Corporate Presentation Final
 
Mifty kit IN Salmiya (+918133066128) Abortion pills IN Salmiyah Cytotec pills
Mifty kit IN Salmiya (+918133066128) Abortion pills IN Salmiyah Cytotec pillsMifty kit IN Salmiya (+918133066128) Abortion pills IN Salmiyah Cytotec pills
Mifty kit IN Salmiya (+918133066128) Abortion pills IN Salmiyah Cytotec pills
 
Horngren’s Cost Accounting A Managerial Emphasis, Canadian 9th edition soluti...
Horngren’s Cost Accounting A Managerial Emphasis, Canadian 9th edition soluti...Horngren’s Cost Accounting A Managerial Emphasis, Canadian 9th edition soluti...
Horngren’s Cost Accounting A Managerial Emphasis, Canadian 9th edition soluti...
 
Falcon Invoice Discounting: Empowering Your Business Growth
Falcon Invoice Discounting: Empowering Your Business GrowthFalcon Invoice Discounting: Empowering Your Business Growth
Falcon Invoice Discounting: Empowering Your Business Growth
 
Jual Obat Aborsi ( Asli No.1 ) 085657271886 Obat Penggugur Kandungan Cytotec
Jual Obat Aborsi ( Asli No.1 ) 085657271886 Obat Penggugur Kandungan CytotecJual Obat Aborsi ( Asli No.1 ) 085657271886 Obat Penggugur Kandungan Cytotec
Jual Obat Aborsi ( Asli No.1 ) 085657271886 Obat Penggugur Kandungan Cytotec
 
Falcon Invoice Discounting: The best investment platform in india for investors
Falcon Invoice Discounting: The best investment platform in india for investorsFalcon Invoice Discounting: The best investment platform in india for investors
Falcon Invoice Discounting: The best investment platform in india for investors
 
Cracking the 'Career Pathing' Slideshare
Cracking the 'Career Pathing' SlideshareCracking the 'Career Pathing' Slideshare
Cracking the 'Career Pathing' Slideshare
 
Mifepristone Available in Muscat +918761049707^^ €€ Buy Abortion Pills in Oman
Mifepristone Available in Muscat +918761049707^^ €€ Buy Abortion Pills in OmanMifepristone Available in Muscat +918761049707^^ €€ Buy Abortion Pills in Oman
Mifepristone Available in Muscat +918761049707^^ €€ Buy Abortion Pills in Oman
 
Putting the SPARK into Virtual Training.pptx
Putting the SPARK into Virtual Training.pptxPutting the SPARK into Virtual Training.pptx
Putting the SPARK into Virtual Training.pptx
 
Rice Manufacturers in India | Shree Krishna Exports
Rice Manufacturers in India | Shree Krishna ExportsRice Manufacturers in India | Shree Krishna Exports
Rice Manufacturers in India | Shree Krishna Exports
 
Falcon Invoice Discounting: Unlock Your Business Potential
Falcon Invoice Discounting: Unlock Your Business PotentialFalcon Invoice Discounting: Unlock Your Business Potential
Falcon Invoice Discounting: Unlock Your Business Potential
 
Arti Languages Pre Seed Teaser Deck 2024.pdf
Arti Languages Pre Seed Teaser Deck 2024.pdfArti Languages Pre Seed Teaser Deck 2024.pdf
Arti Languages Pre Seed Teaser Deck 2024.pdf
 
TVB_The Vietnam Believer Newsletter_May 6th, 2024_ENVol. 006.pdf
TVB_The Vietnam Believer Newsletter_May 6th, 2024_ENVol. 006.pdfTVB_The Vietnam Believer Newsletter_May 6th, 2024_ENVol. 006.pdf
TVB_The Vietnam Believer Newsletter_May 6th, 2024_ENVol. 006.pdf
 
Buy Verified TransferWise Accounts From Seosmmearth
Buy Verified TransferWise Accounts From SeosmmearthBuy Verified TransferWise Accounts From Seosmmearth
Buy Verified TransferWise Accounts From Seosmmearth
 
Organizational Transformation Lead with Culture
Organizational Transformation Lead with CultureOrganizational Transformation Lead with Culture
Organizational Transformation Lead with Culture
 
Getting Real with AI - Columbus DAW - May 2024 - Nick Woo from AlignAI
Getting Real with AI - Columbus DAW - May 2024 - Nick Woo from AlignAIGetting Real with AI - Columbus DAW - May 2024 - Nick Woo from AlignAI
Getting Real with AI - Columbus DAW - May 2024 - Nick Woo from AlignAI
 
Falcon Invoice Discounting: Tailored Financial Wings
Falcon Invoice Discounting: Tailored Financial WingsFalcon Invoice Discounting: Tailored Financial Wings
Falcon Invoice Discounting: Tailored Financial Wings
 
unwanted pregnancy Kit [+918133066128] Abortion Pills IN Dubai UAE Abudhabi
unwanted pregnancy Kit [+918133066128] Abortion Pills IN Dubai UAE Abudhabiunwanted pregnancy Kit [+918133066128] Abortion Pills IN Dubai UAE Abudhabi
unwanted pregnancy Kit [+918133066128] Abortion Pills IN Dubai UAE Abudhabi
 
Famous Olympic Siblings from the 21st Century
Famous Olympic Siblings from the 21st CenturyFamous Olympic Siblings from the 21st Century
Famous Olympic Siblings from the 21st Century
 
Call 7737669865 Vadodara Call Girls Service at your Door Step Available All Time
Call 7737669865 Vadodara Call Girls Service at your Door Step Available All TimeCall 7737669865 Vadodara Call Girls Service at your Door Step Available All Time
Call 7737669865 Vadodara Call Girls Service at your Door Step Available All Time
 

Building a desktop app with HTTP::Engine, SQLite and jQuery

  • 1. Building a desktop app with HTTP::Engine, SQLite & jQuery Tatsuhiko Miyagawa YAPC::NA 2009 Pittsburgh Wednesday, June 24, 2009
  • 6. Acme-DateTime-Duration-Numeric Acme-Module-Authors Acme-Sneeze Acme-Sneeze-JP Apache-ACEProxy Apache- AntiSpam Apache-Clickable Apache-CustomKeywords Apache-DefaultCharset Apache-GuessCharset Apache-JavaScript- DocumentWrite Apache-No404Proxy Apache-Profiler Apache-Session-CacheAny Apache-Session-Generate-ModUniqueId Apache-Session-Generate-ModUsertrack Apache-Session-PHP Apache-Session-Serialize-YAML Apache-Singleton Apache- StickyQuery Archive-Any-Create Attribute-Profiled Attribute-Protected Attribute-Unimplemented Bundle-Sledge CGI- Untaint-email CPAN-Mini-Growl Catalyst-Plugin-Authentication-Credential-AOL Catalyst-Plugin-Authentication-Credential- OpenID Catalyst-Plugin-JSONRPC Catalyst-View-JSON Catalyst-View-Jemplate Class-DBI-AbstractSearch Class-DBI- Extension Class-DBI-Pager Class-DBI-Replication Class-DBI-SQLite Class-DBI-View Class-Trigger Convert-Base32 Convert- DUDE Convert-RACE Data-YUID Date-Japanese-Era Date-Range-Birth DateTime-Span-Birthdate Device-KeyStroke-Mobile Dunce-time Email-Find Email-Valid-Loose Encode-DoubleEncodedUTF8 Encode-First Encode-JP-Mobile Encode-JavaScript- UCS Encode-Punycode File-Find-Rule-Digest File-Spotlight Geo-Coder-Google HTML-AutoPagerize HTML-Entities- ImodePictogram HTML-RelExtor HTML-ResolveLink HTML-Selector-XPath HTML-XSSLint HTTP-MobileAgent HTTP- ProxyPAC HTTP-Server-Simple-Authen HTTP-Server-Simple-Bonjour IDNA-Punycode Inline-Basic Inline-TT JSON-Syck Kwiki-Emoticon Kwiki-Export Kwiki-Footnote Kwiki-OpenSearch Kwiki-OpenSearch-Service Kwiki-TypeKey Kwiki-URLBL LWP-UserAgent-Keychain Lingua-JA-Hepburn-Passport Log-Dispatch-Config Log-Dispatch-DBI MSIE-MenuExt Mac- Macbinary Mail-Address-MobileJp Mail-ListDetector-Detector-Fml Module-Install-Repository Net-DAAP-Server-AAC Net- IDN-Nameprep Net-IPAddr-Find Net-Twitter-OAuth Net-YahooMessenger NetAddr-IP-Find P2P-Transmission-Remote PHP-Session POE-Component-Client-AirTunes POE-Component-Client-Lingr POE-Component-YahooMessenger Path- Class-URI Plagger RPC-XML-Parser-LibXML Template-Plugin-Clickable Template-Plugin-Comma Template-Plugin-FillInForm Template-Plugin-HTML-Template Template-Plugin-JavaScript Template-Plugin-MobileAgent Template-Plugin-ResolveLink Template-Plugin-Shuffle Template-Provider-Encoding Term-Encoding Term-TtyRec Test-Synopsis Text-Emoticon Text- Emoticon-GoogleTalk Text-Emoticon-MSN Text-Emoticon-Yahoo Text-MessageFormat TheSchwartz-Simple Time-Duration- Parse Time-Duration-ja URI-Find-UTF8 URI-git URI-tag URI-urn-uuid Video-Subtitle-SRT WWW-Baseball-NPB WWW-Blog- Metadata-MobileLinkDiscovery WWW-Blog-Metadata-OpenID WWW-Blog-Metadata-OpenSearch WWW-Cache-Google WWW-Mechanize-AutoPager WWW-Mechanize-DecodedContent WWW-NicoVideo-Download WWW-OpenSearch WWW-Shorten-RevCanonical WWW-Shorten-Simple Web-Scraper Web-oEmbed WebService-Bloglines WebService- ChangesXml WebService-Google-Suggest WebService-Lingr XML-Atom XML-Atom-Lifeblog XML-Atom-Stream XML- Liberal XML-OPML-LibXML abbreviation autobox-DateTime-Duration capitalization plagger Wednesday, June 24, 2009
  • 7. twitter.com/miyagawa (Slides will be linked. Follow me!) Wednesday, June 24, 2009
  • 9. remediecode.org Slides/Video in OSDC.TW Wednesday, June 24, 2009
  • 10. Building a desktop app with HTTP::Engine, SQLite & jQuery Tatsuhiko Miyagawa YAPC::NA 2009 Pittsburgh Wednesday, June 24, 2009
  • 12. MFC/.NET Visual C++,VB Wednesday, June 24, 2009
  • 14. Objective-C Cocoa (PyObjC/RubyCocoa) Wednesday, June 24, 2009
  • 16. I’m a Perl guy who knows JavaScript. Wednesday, June 24, 2009
  • 19. “Web 2.0 iPhone App” Steve Jobs at WWDC 2007 Wednesday, June 24, 2009
  • 22. HTML5 geolocation, videos local storage Wednesday, June 24, 2009
  • 23. HTML5 = Future ??? = 2009 Wednesday, June 24, 2009
  • 24. micro Web app = 2009 Wednesday, June 24, 2009
  • 25. (2 min Demo video) Wednesday, June 24, 2009
  • 26. How I built this Wednesday, June 24, 2009
  • 27. Building a desktop app with HTTP::Engine, SQLite & jQuery Tatsuhiko Miyagawa YAPC::NA 2009 Pittsburgh Wednesday, June 24, 2009
  • 28. “The most important project in Perl recently” - jrockway Wednesday, June 24, 2009
  • 29. Based on Catalyst::Engine Wednesday, June 24, 2009
  • 30. Ruby’s Rack Python’s WSGI Wednesday, June 24, 2009
  • 31. use HTTP::Engine; my $engine = HTTP::Engine‐>new(     interface => {         module => 'ServerSimple',         args   => {             host => 'localhost',             port => 9898,         },     request_handler => &handle_request, }); $engine‐>run; Wednesday, June 24, 2009
  • 32. sub handle_request {     my $req = shift;     return HTTP::Engine::Response‐>new(         body => “Hello World”,     ); } Wednesday, June 24, 2009
  • 33. Standalone, ServerSimple, POE, FastCGI, mod_perl Wednesday, June 24, 2009
  • 34. Desktop app: ServerSimple POE (non-blocking) Wednesday, June 24, 2009
  • 35. Serve static files (HTML/CSS/JS) Wednesday, June 24, 2009
  • 36. sub handle_request {     my($self, $req) = @_;     my $path = $req‐>path;     my $res = HTTP::Engine::Response‐>new;     if ($path =~ s!^/static/!!) {         $self‐>serve_static_file($path, $req, $res);     };     return $res; } Wednesday, June 24, 2009
  • 37. use Path::Class; sub serve_static_file {     my($self, $path, $req, $res) = @_;     my $root = $self‐>conf‐>{root};     my $file = file($root, "static", $path);     my $size  = ‐s _;     my $mtime = (stat(_))[9];     my $ext = ($file =~ /.(w+)$/)[0];     $res‐>content_type( MIME::Types‐>new‐>mimeTypeOf($ext)         || "text/plain" );     # ...     open my $fh, "<:raw", $file         or die "$file: $!";     $res‐>headers‐>header('Last‐Modified' =>          HTTP::Date::time2str($mtime));     $res‐>headers‐>header('Content‐Length' => $size);     $res‐>body( join '', <$fh> ); } Wednesday, June 24, 2009
  • 38. See Also: HTTP::Engine::Middleware::Static Wednesday, June 24, 2009
  • 39. Implement Ajax backend actions (JSON-REST) Wednesday, June 24, 2009
  • 40. sub handle_request {     my($self, $req) = @_;     my $path = $req‐>path;     my $res = HTTP::Engine::Response‐>new;     if ($path =~ s!^/rpc/!!) {         $self‐>dispatch_rpc($path, $req, $res);     } } Wednesday, June 24, 2009
  • 41. sub dispatch_rpc {     my($self, $path, $req, $res) = @_;     my @class  = split '/', $path;     my $method = pop @class;     die "Access to non‐public methods" if $method =~ /^_/;     my $rpc_class = $self‐>load_rpc_class(@class);     my $rpc = $rpc_class‐>new( conf => $self‐>conf );     my $result = eval { $rpc‐>$method($req, $res) };     unless ( $res‐>body ) {         $res‐>status(200);         $res‐>content_type("application/json; charset=utf‐8");         $res‐>body( Remedie::JSON‐>encode($result) );     } } Wednesday, June 24, 2009
  • 42. Problem (1): Dirty API routing Wednesday, June 24, 2009
  • 43. Path::Router, Path::Dispatcher, HTTP::Dispatcher, JSORB Wednesday, June 24, 2009
  • 44. Problem (2): Vulnerable (CSRF) Wednesday, June 24, 2009
  • 45. Authentication Special Headers Switch to JSONRPC Wednesday, June 24, 2009
  • 46. Bonjour (based on HTTP::Server::Simple::Bonjour) Wednesday, June 24, 2009
  • 47. Auto Discovery Share subscriptions Wednesday, June 24, 2009
  • 49. Building a desktop app with HTTP::Engine, SQLite & jQuery Tatsuhiko Miyagawa YAPC::NA 2009 Pittsburgh Wednesday, June 24, 2009
  • 50. SQL DB choices Wednesday, June 24, 2009
  • 51. MySQL/PostgreSQL Good for Web apps. Wednesday, June 24, 2009
  • 52. SQLite: file-based, type-less Transactional Wednesday, June 24, 2009
  • 53. SQLite: best for desktop apps Wednesday, June 24, 2009
  • 54. SQLite for desktop: Firefox, Mail.app, iCal Wednesday, June 24, 2009
  • 55. End-users don’t want to run *SQL server Wednesday, June 24, 2009
  • 56. Bonus: Easy backup, Dropbox sync Wednesday, June 24, 2009
  • 58. You don’t need DBA. Make it simple, flexible and extensible. Wednesday, June 24, 2009
  • 59. Remedie schema Few indexes JSON key-values Wednesday, June 24, 2009
  • 60. CREATE TABLE channel (   id      INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,   type    INTEGER NOT NULL,   parent  INTEGER NOT NULL,   ident   TEXT NOT NULL,   name    TEXT NOT NULL,   props   TEXT ); CREATE UNIQUE INDEX channel_ident ON channel (ident); Wednesday, June 24, 2009
  • 61. CREATE TABLE item (   id         INTEGER NOT NULL PRIMARY KEY  AUTOINCREMENT,   channel_id INTEGER NOT NULL,   type       INTEGER NOT NULL,   ident      TEXT NOT NULL,   name       TEXT NOT NULL,   status     INTEGER NOT NULL,   props      TEXT ); CREATE INDEX item_status ON item (status) CREATE UNIQUE INDEX item_ident ON item (channel_id,  ident); Wednesday, June 24, 2009
  • 63. CouchDB, MongoDB TokyoTyrant (Need servers though) Wednesday, June 24, 2009
  • 67. DBIx::Class Rose::DB::Object Wednesday, June 24, 2009
  • 68. Rose::DB::Object (I wanted some excuse) Wednesday, June 24, 2009
  • 69. See Also: KiokuDB Wednesday, June 24, 2009
  • 70. KiokuDB DBI / SQLite backend Key-Value JSPON Wednesday, June 24, 2009
  • 71. Building a desktop app with HTTP::Engine, SQLite & jQuery Tatsuhiko Miyagawa YAPC::NA 2009 Pittsburgh Wednesday, June 24, 2009
  • 72. Just use normal HTML and CSS to design UI Wednesday, June 24, 2009
  • 73. Manipulate DOM $.ajax to do Ajax Wednesday, June 24, 2009
  • 76. $("#channel‐pane").createAppend(   'div', { className: 'channel‐header',            id: 'channel‐header‐' + channel.id  }, [     'div', { className: 'channel‐header‐thumb' }, [        'img', { src: "/static/images/feed.png",                 alt: channel.name }, null     ],   ] ); Wednesday, June 24, 2009
  • 78. $(document).bind(‘keydown’, ‘shift+n’, function(ev){    // ‘N’ is entered }); Wednesday, June 24, 2009
  • 83. $.event.trigger $(document).bind Wednesday, June 24, 2009
  • 85. Fancy stuff like Drag & Drop Wednesday, June 24, 2009
  • 86. jQuery.blockUI jQuery.scrollTo jQuery.jgrowl Wednesday, June 24, 2009
  • 87. Building a desktop app with HTTP::Engine, SQLite & jQuery Tatsuhiko Miyagawa YAPC::NA 2009 Pittsburgh Wednesday, June 24, 2009
  • 88. More like “Desktop app” Wednesday, June 24, 2009
  • 90. Web Client as “app” Wednesday, June 24, 2009
  • 92. Fluid Prism Wednesday, June 24, 2009
  • 94. Customize Userscripts / Userstyles Wednesday, June 24, 2009
  • 95. Fluid hooks Growl integration Dock menu Wednesday, June 24, 2009
  • 97. Client-Server Decoupled via APIs Wednesday, June 24, 2009
  • 98. More Clients More “Views” Wednesday, June 24, 2009
  • 102. 120 lines of HTML/JS using iUI project Wednesday, June 24, 2009
  • 105. local::lib build & install all deps Wednesday, June 24, 2009
  • 106. Also: Shipwright Wednesday, June 24, 2009
  • 107. Platypus Make .app Wednesday, June 24, 2009
  • 108. Download .zip, copy .app to /Applications, Run it. Wednesday, June 24, 2009
  • 109. Also: github.com/miyagawa/perl-app-builder Wednesday, June 24, 2009
  • 110. Summary • micro web server as a desktop app • HTTP::Engine, JSONRPC and router • SQLite to store key-value • jQuery plugins to enable desktop UIs • More tools to make it really “.app” Wednesday, June 24, 2009
  • 111. That’s it! Questions? Wednesday, June 24, 2009
  • 112. Thank you! twitter.com/miyagawa Wednesday, June 24, 2009