SlideShare a Scribd company logo
1 of 84
Download to read offline
Web development,
  as you    it
Lukas Renggli
Academics
  PhD Student, University of Bern
Industry
  Independent Software Consultant
Communities
  Core-developer of Seaside
  Author of Magritte and Pier
Agenda

Natural Flow
Reusable Components
Secure by Default
Web 2.0
Applications
1
Natural Flow
Demo
<form action=quot;second.htmlquot;>
   <input type=quot;textquot; name=quot;value1quot;>
   <input type=quot;submitquot; value=quot;OKquot;>
</form>
<form action=quot;second.htmlquot;>
   <input type=quot;textquot; name=quot;value1quot;>
   <input type=quot;submitquot; value=quot;OKquot;>
</form>


<form action=quot;result.htmlquot;>
   <input type=quot;textquot; name=quot;value2quot;>
   <input type=quot;submitquot; value=quot;OKquot;>
</form>
<form action=quot;second.htmlquot;>
   <input type=quot;textquot; name=quot;value1quot;>
   <input type=quot;submitquot; value=quot;OKquot;>
</form>


<form action=quot;result.htmlquot;>
   <input type=quot;textquot; name=quot;value2quot;>
   <input type=quot;submitquot; value=quot;OKquot;>
</form>


<p>
   <% value1 + value2 %>
</p>
<form action=quot;second.htmlquot;>
   <input type=quot;textquot; name=quot;value1quot;>
   <input type=quot;submitquot; value=quot;OKquot;>
</form>


<form action=quot;result.htmlquot;>
   <input type=quot;textquot; name=quot;value2quot;>
   <input type=quot;submitquot; value=quot;OKquot;>
</form>


<p>
   <% value1 + value2 %>
</p>
<form action=quot;second.htmlquot;>
   <input type=quot;textquot; name=quot;value1quot;>
   <input type=quot;submitquot; value=quot;OKquot;>
</form>


<form action=quot;result.htmlquot;>
   <input type=quot;textquot; name=quot;value2quot;>
   <input type=quot;submitquot; value=quot;OKquot;>
</form>


<p>
   <% value1 + value2 %>
</p>
<form action=quot;second.htmlquot;>
   <input type=quot;textquot; name=quot;value1quot;>
   <input type=quot;submitquot; value=quot;OKquot;>
</form>


<form action=quot;result.htmlquot;>
   <input type=quot;textquot; name=quot;value2quot;>
   <input type=quot;submitquot; value=quot;OKquot;>
</form>


<p>
   <% value1 + value2 %>
</p>
<form action=quot;second.htmlquot;>
   <input type=quot;textquot; name=quot;value1quot;>
   <input type=quot;submitquot; value=quot;OKquot;>
</form>

<form action=quot;result.htmlquot;>
   <input type=quot;hiddenquot; name=quot;value1quot; value=quot;<% value1 %>quot;>
   <input type=quot;textquot; name=quot;value2quot;>
   <input type=quot;submitquot; value=quot;OKquot;>
</form>


<p>
   <% value1 + value2 %>
</p>
<form action=quot;second.htmlquot;>
   <input type=quot;textquot; name=quot;value1quot;>
   <input type=quot;submitquot; value=quot;OKquot;>
</form>

<form action=quot;result.htmlquot;>
   <input type=quot;hiddenquot; name=quot;value1quot; value=quot;<% value1 %>quot;>
   <input type=quot;textquot; name=quot;value2quot;>
   <input type=quot;submitquot; value=quot;OKquot;>
</form>


<p>
   <% value1 + value2 %>
</p>
Web Browser
Web Browser
/first
  parsing
processing
formatting




             Web Browser
/first
  parsing
processing
formatting


             value1




                      Web Browser
/first                   /second
  parsing                   parsing
processing                processing
formatting                formatting


             value1




                           value1
                      Web Browser
/first                   /second
  parsing                   parsing
processing                processing




                                       value1, value2
formatting                formatting


             value1




                           value1
                      Web Browser
/first                   /second                        /result
  parsing                   parsing                       parsing
processing                processing                    processing




                                       value1, value2
formatting                formatting                    formatting


             value1




                           value1




                                                         result
                      Web Browser
Who cares about
HTTP anyway?
is different
Concentrate on
your application ...
... no manual
request parsing
... no XML
configuration files
3 user interactions
3 lines of code
value1 := self request: ‘First Number’.
value1 := self request: ‘First Number’.
value2 := self request: ‘Second Number’.
value1 := self request: ‘First Number’.
value2 := self request: ‘Second Number’.
self inform: value1 + value2.
Demo
Reusable
Components
We don’t think in
   pages ...
..., but in stateful
   components
Demo
Demo
Components
  are c! l
        !
Reuseable
Model




    View           Controller




Model, View, Controller
Persistent
Valid




Source: stock.xchng, Al Nakib
CSS
Designer
XHTML
Developer & Seaside
DRY
Don't Repeat Yourself
Domain Specific
  Language
html div id: ‘title’; with: ‘Title’




<div id=”title”>Title</div>
html div id: ‘list’; with: [
  html span class: ‘item’; with: ‘Item 1’.
  html span class: ‘item’; with: ‘Item 2’ ]




<div id=”list”>
  <span class=”item”>Item 1</span>
  <span class=”item”>Item 2</span>
</div>
Demo
3
Secure by
 Default
Cross Site Scripting




Source: stock.xchng, Afonso Lima
Output is encoded
    by default
html text: '<script>alert(''xss'')</script>'




&lt;script&gt;alert('xss');&lt;/script&gt;
Replay Attacks




Source: stock.xchng, Afonso Lima
Session
_s=Ru8ZKgqjy0uDX3kf

       96-bit
Page
_k=K5EQyqKE

   48-bit
Parameter Tampering




Source: stock.xchng, Afonso Lima
Names are generated
   automatically
Names are bound
  to functions
No manual
request parsing
Don’t call Seaside,
Seaside will call you




                        Source: stock.xchng, Pawel Zawistowski
html anchor
! callback: [ self inform: ‘Hello World’ ];
! with: ‘Show Message’




<a href=”/seaside/example1
quot; ?_s=Ru8ZKgqjy0uDX3kf
quot; &_k=K5EQyqKE
! &32”>Show Message</a>
Web 2.0
Source: Flickr, Benjamin Jackson
AJAX




Source: Flickr, Benjamin Jackson
Tight, but optional
    integration
Feature complete
 and up-to-date
Say it in Smalltalk
Source: Flickr, psrman's
Comet




Source: Flickr, psrman's
Demo
scriptaculous.seasidehosting.st
5
Applications
In productive use
    since 2002
Demo
Seaside
MIT License
www.seaside.st
www.lukas-renggli.ch

More Related Content

What's hot

Client side scripting using Javascript
Client side scripting using JavascriptClient side scripting using Javascript
Client side scripting using Javascript
Bansari Shah
 
Javascript part1
Javascript part1Javascript part1
Javascript part1
Raghu nath
 
[DSBW Spring 2009] Unit 07: WebApp Design Patterns & Frameworks (3/3)
[DSBW Spring 2009] Unit 07: WebApp Design Patterns & Frameworks (3/3)[DSBW Spring 2009] Unit 07: WebApp Design Patterns & Frameworks (3/3)
[DSBW Spring 2009] Unit 07: WebApp Design Patterns & Frameworks (3/3)
Carles Farré
 
Building Web Service Clients with ActiveModel
Building Web Service Clients with ActiveModelBuilding Web Service Clients with ActiveModel
Building Web Service Clients with ActiveModel
pauldix
 

What's hot (20)

JavaScript: Ajax & DOM Manipulation
JavaScript: Ajax & DOM ManipulationJavaScript: Ajax & DOM Manipulation
JavaScript: Ajax & DOM Manipulation
 
FYBSC IT Web Programming Unit III Document Object
FYBSC IT Web Programming Unit III  Document ObjectFYBSC IT Web Programming Unit III  Document Object
FYBSC IT Web Programming Unit III Document Object
 
Web 2 | CSS - Cascading Style Sheets
Web 2 | CSS - Cascading Style SheetsWeb 2 | CSS - Cascading Style Sheets
Web 2 | CSS - Cascading Style Sheets
 
Java script
Java scriptJava script
Java script
 
Introduction to Javascript
Introduction to JavascriptIntroduction to Javascript
Introduction to Javascript
 
Building an api using golang and postgre sql v1.0
Building an api using golang and postgre sql v1.0Building an api using golang and postgre sql v1.0
Building an api using golang and postgre sql v1.0
 
Client side scripting using Javascript
Client side scripting using JavascriptClient side scripting using Javascript
Client side scripting using Javascript
 
Javascript
JavascriptJavascript
Javascript
 
FYBSC IT Web Programming Unit III Javascript
FYBSC IT Web Programming Unit III JavascriptFYBSC IT Web Programming Unit III Javascript
FYBSC IT Web Programming Unit III Javascript
 
Devoxx 2014-webComponents
Devoxx 2014-webComponentsDevoxx 2014-webComponents
Devoxx 2014-webComponents
 
AngularJS Basic Training
AngularJS Basic TrainingAngularJS Basic Training
AngularJS Basic Training
 
FYBSC IT Web Programming Unit III Core Javascript
FYBSC IT Web Programming Unit III  Core JavascriptFYBSC IT Web Programming Unit III  Core Javascript
FYBSC IT Web Programming Unit III Core Javascript
 
Javascript part1
Javascript part1Javascript part1
Javascript part1
 
Rails <form> Chronicle
Rails <form> ChronicleRails <form> Chronicle
Rails <form> Chronicle
 
22 j query1
22 j query122 j query1
22 j query1
 
[DSBW Spring 2009] Unit 07: WebApp Design Patterns & Frameworks (3/3)
[DSBW Spring 2009] Unit 07: WebApp Design Patterns & Frameworks (3/3)[DSBW Spring 2009] Unit 07: WebApp Design Patterns & Frameworks (3/3)
[DSBW Spring 2009] Unit 07: WebApp Design Patterns & Frameworks (3/3)
 
Building Web Service Clients with ActiveModel
Building Web Service Clients with ActiveModelBuilding Web Service Clients with ActiveModel
Building Web Service Clients with ActiveModel
 
WEB TECHNOLOGIES JavaScript
WEB TECHNOLOGIES JavaScriptWEB TECHNOLOGIES JavaScript
WEB TECHNOLOGIES JavaScript
 
PHP - Introduction to PHP Forms
PHP - Introduction to PHP FormsPHP - Introduction to PHP Forms
PHP - Introduction to PHP Forms
 
AngularJS
AngularJSAngularJS
AngularJS
 

Viewers also liked (12)

Seaside Slide Presentation
Seaside Slide PresentationSeaside Slide Presentation
Seaside Slide Presentation
 
Seaside Presentation
Seaside PresentationSeaside Presentation
Seaside Presentation
 
Ocean PPT
Ocean PPTOcean PPT
Ocean PPT
 
Sealife
SealifeSealife
Sealife
 
Philosophy Presentation - Buddhism
Philosophy Presentation - BuddhismPhilosophy Presentation - Buddhism
Philosophy Presentation - Buddhism
 
Complete Ppt Buddhism
Complete Ppt BuddhismComplete Ppt Buddhism
Complete Ppt Buddhism
 
Sea Creatures PowerPoint
Sea Creatures PowerPointSea Creatures PowerPoint
Sea Creatures PowerPoint
 
Best ppt on ocean facts
Best ppt on ocean factsBest ppt on ocean facts
Best ppt on ocean facts
 
Elderly Care
Elderly CareElderly Care
Elderly Care
 
Caring for the Elderly
Caring for the ElderlyCaring for the Elderly
Caring for the Elderly
 
Ocean powerpoint presentation
Ocean powerpoint presentationOcean powerpoint presentation
Ocean powerpoint presentation
 
Buddhism PowerPoint
Buddhism PowerPointBuddhism PowerPoint
Buddhism PowerPoint
 

Similar to Seaside - Web Development As You Like It

symfony: An Open-Source Framework for Professionals (Dutch Php Conference 2008)
symfony: An Open-Source Framework for Professionals (Dutch Php Conference 2008)symfony: An Open-Source Framework for Professionals (Dutch Php Conference 2008)
symfony: An Open-Source Framework for Professionals (Dutch Php Conference 2008)
Fabien Potencier
 
Intro to-rails-webperf
Intro to-rails-webperfIntro to-rails-webperf
Intro to-rails-webperf
New Relic
 
JSON-RPC Proxy Generation with PHP 5
JSON-RPC Proxy Generation with PHP 5JSON-RPC Proxy Generation with PHP 5
JSON-RPC Proxy Generation with PHP 5
Stephan Schmidt
 

Similar to Seaside - Web Development As You Like It (20)

5 Steps to Mastering the Art of Seaside
5 Steps to Mastering the Art of Seaside5 Steps to Mastering the Art of Seaside
5 Steps to Mastering the Art of Seaside
 
Bpmn2010
Bpmn2010Bpmn2010
Bpmn2010
 
Seaside - The Revenge of Smalltalk
Seaside - The Revenge of SmalltalkSeaside - The Revenge of Smalltalk
Seaside - The Revenge of Smalltalk
 
Java script
Java scriptJava script
Java script
 
symfony: An Open-Source Framework for Professionals (Dutch Php Conference 2008)
symfony: An Open-Source Framework for Professionals (Dutch Php Conference 2008)symfony: An Open-Source Framework for Professionals (Dutch Php Conference 2008)
symfony: An Open-Source Framework for Professionals (Dutch Php Conference 2008)
 
Writing Software not Code with Cucumber
Writing Software not Code with CucumberWriting Software not Code with Cucumber
Writing Software not Code with Cucumber
 
Nodejs Explained with Examples
Nodejs Explained with ExamplesNodejs Explained with Examples
Nodejs Explained with Examples
 
Nodejsexplained 101116115055-phpapp02
Nodejsexplained 101116115055-phpapp02Nodejsexplained 101116115055-phpapp02
Nodejsexplained 101116115055-phpapp02
 
MySQL Proxy tutorial
MySQL Proxy tutorialMySQL Proxy tutorial
MySQL Proxy tutorial
 
Intro to-rails-webperf
Intro to-rails-webperfIntro to-rails-webperf
Intro to-rails-webperf
 
More Secrets of JavaScript Libraries
More Secrets of JavaScript LibrariesMore Secrets of JavaScript Libraries
More Secrets of JavaScript Libraries
 
Ruby sittin' on the Couch
Ruby sittin' on the CouchRuby sittin' on the Couch
Ruby sittin' on the Couch
 
When To Use Ruby On Rails
When To Use Ruby On RailsWhen To Use Ruby On Rails
When To Use Ruby On Rails
 
JSON-RPC Proxy Generation with PHP 5
JSON-RPC Proxy Generation with PHP 5JSON-RPC Proxy Generation with PHP 5
JSON-RPC Proxy Generation with PHP 5
 
Postman On Steroids
Postman On SteroidsPostman On Steroids
Postman On Steroids
 
Adventurous Merb
Adventurous MerbAdventurous Merb
Adventurous Merb
 
AEM Sightly Template Language
AEM Sightly Template LanguageAEM Sightly Template Language
AEM Sightly Template Language
 
Google Back To Front: From Gears to App Engine and Beyond
Google Back To Front: From Gears to App Engine and BeyondGoogle Back To Front: From Gears to App Engine and Beyond
Google Back To Front: From Gears to App Engine and Beyond
 
Java script
Java scriptJava script
Java script
 
Metrics-Driven Engineering
Metrics-Driven EngineeringMetrics-Driven Engineering
Metrics-Driven Engineering
 

More from Lukas Renggli

Dynamic Language Embedding With Homogeneous Tool Support
Dynamic Language Embedding With Homogeneous Tool SupportDynamic Language Embedding With Homogeneous Tool Support
Dynamic Language Embedding With Homogeneous Tool Support
Lukas Renggli
 
Seaside — Agile Software Development
Seaside — Agile Software DevelopmentSeaside — Agile Software Development
Seaside — Agile Software Development
Lukas Renggli
 
Seaside Status Message
Seaside Status MessageSeaside Status Message
Seaside Status Message
Lukas Renggli
 

More from Lukas Renggli (17)

Mastering Grammars with PetitParser
Mastering Grammars with PetitParserMastering Grammars with PetitParser
Mastering Grammars with PetitParser
 
Natural Language Checking with Program Checking Tools
Natural Language Checking with Program Checking ToolsNatural Language Checking with Program Checking Tools
Natural Language Checking with Program Checking Tools
 
The Dynamic Language is not Enough
The Dynamic Language is not EnoughThe Dynamic Language is not Enough
The Dynamic Language is not Enough
 
Dynamic Language Embedding With Homogeneous Tool Support
Dynamic Language Embedding With Homogeneous Tool SupportDynamic Language Embedding With Homogeneous Tool Support
Dynamic Language Embedding With Homogeneous Tool Support
 
Seaside — Agile Software Development
Seaside — Agile Software DevelopmentSeaside — Agile Software Development
Seaside — Agile Software Development
 
Dynamic grammars
Dynamic grammarsDynamic grammars
Dynamic grammars
 
Domain-Specific Program Checking
Domain-Specific Program CheckingDomain-Specific Program Checking
Domain-Specific Program Checking
 
Embedding Languages Without Breaking Tools
Embedding Languages Without Breaking ToolsEmbedding Languages Without Breaking Tools
Embedding Languages Without Breaking Tools
 
Language Boxes — Bending the Host Language with Modular Language Changes
Language Boxes — Bending the Host Language with Modular Language ChangesLanguage Boxes — Bending the Host Language with Modular Language Changes
Language Boxes — Bending the Host Language with Modular Language Changes
 
jQuery for Seaside
jQuery for SeasidejQuery for Seaside
jQuery for Seaside
 
Seaside Status Message
Seaside Status MessageSeaside Status Message
Seaside Status Message
 
Magritte Blitz
Magritte BlitzMagritte Blitz
Magritte Blitz
 
Seaside - On not getting bogged down
Seaside - On not getting bogged downSeaside - On not getting bogged down
Seaside - On not getting bogged down
 
Magritte
MagritteMagritte
Magritte
 
Seaside - Past, Present and Future
Seaside - Past, Present and FutureSeaside - Past, Present and Future
Seaside - Past, Present and Future
 
Magritte - A Meta-Driven Approach to Empower Developers and End Users
Magritte - A Meta-Driven Approach to Empower Developers and End UsersMagritte - A Meta-Driven Approach to Empower Developers and End Users
Magritte - A Meta-Driven Approach to Empower Developers and End Users
 
Transactional Memory for Smalltalk
Transactional Memory for SmalltalkTransactional Memory for Smalltalk
Transactional Memory for Smalltalk
 

Recently uploaded

Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Victor Rentea
 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Victor Rentea
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Safe Software
 

Recently uploaded (20)

Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
Spring Boot vs Quarkus the ultimate battle - DevoxxUK
Spring Boot vs Quarkus the ultimate battle - DevoxxUKSpring Boot vs Quarkus the ultimate battle - DevoxxUK
Spring Boot vs Quarkus the ultimate battle - DevoxxUK
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor Presentation
 
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ..."I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
 
FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024
 
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf
 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
 
JohnPollard-hybrid-app-RailsConf2024.pptx
JohnPollard-hybrid-app-RailsConf2024.pptxJohnPollard-hybrid-app-RailsConf2024.pptx
JohnPollard-hybrid-app-RailsConf2024.pptx
 
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
 
Introduction to use of FHIR Documents in ABDM
Introduction to use of FHIR Documents in ABDMIntroduction to use of FHIR Documents in ABDM
Introduction to use of FHIR Documents in ABDM
 
WSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering DevelopersWSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering Developers
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptx
 

Seaside - Web Development As You Like It