Create Your Own WeChat Mini Program and Pulling External API Data to It

Weiming Chen
9 min readSep 29, 2021

WeChat mini program is phenomenal and ubiquitous these days. It is an interesting semi-Hybrid app that served inside WeChat app. You may think of it as a program inside an app, or even think of it as ‘function as a service’, a tiny app that is runnable without downloading.

The philosophy for it is defined by Allen Zhang (Godfather of WeChat):

‘Finish and Leave’.

No need to hook the users into it. Like a lambda function, you use it and flush it.

Common use cases: ordering food delivery, car-hailing, registration of an event, buying a movie ticket, e-commerce, get stock info, watching live streaming content, computing some math.

Do you install every native app for every single task? If so, Your device will be full of apps, messy, and stressful? Maybe you watch a movie five times a month, do you need your neighborhood cinema app or TicketMaster app idle on your device most of the time?

I don’t want to confuse you that WeChat mini program was better or worse than a native app. No. Native apps are generally offering much better user experiences, more seamless.

The WeChat mini program is very similar to the ReactNative Hybrid app experience also inherits some core functionaries and components from WeChat. Again, it is really up to a point that you decide whether you need to install an app for a single purpose.

So still people are confusing that what stacks the WeChat mini program build on? What the heck do you mean by an app inside an app? No worry, let’s uncover it and make your own first WeChat mini program.

Since WeChat mini programs are inside the WeChat app, there are limitations and restrictions to some extend. But we are in an API-first world. Nowadays, we encapsulate data, logic, computation in external backends, and are exposed to APIs. You don’t need to do computation inside the WeChat mini-programs. The ‘mini’ could just call your APIs to do tasks, like a load movie review, verify identity, make payment. Imagine that behind the mini program scenes, just some view model binding display and a bunch of HTTP C.R.U.D calls.

Let’s define our goal in this guide:

  • Create a WeChat mini program named ‘My Burger’
  • Interface: Two Tabs, Two Pages
  • Pages: ‘Home’ and ‘Burger’
  • Home page: static welcome greeting.
  • Burger page: pull burger data from an outside API, then display to the view.

Don’t be scare.

You only need fundamental HTML / CSS / JavaScript knowledge to start. Surprised? That’s it.If you can make basic web pages, you are totally able to create your own WeChat mini program. Yes, that’s all. You don’t have to use any Frontend frameworks.

Requirement and Environment

  • A WeChat developer account.
  • Install WeChat Devtools (IDE)
  • Basic HTML / CSS / JavaScript skills

About API policy

Please note for security practice, WeChat requires

  • Your API domain name to add to requestValid Domain Name list n your account Dashboard
  • Your API must be under HTTPS

Create a new mini program project via IDE

By default, the IDE creates two pages for you: ‘index’ and ‘log’.

We can safely delete them, to keep this example as simple as possible for illustration purposes, we will create our own ones (Home and Burger) very soon.

Note there are files named app.* under the project root folder.

app.js
app.json
app.wxss
  • app.js: put your app logic code in the JavaScript file.
  • app.wxss: global stylesheet. Think of it as site-wide css file.
  • app.json: app’s configuration file. You define your pages, tabBar, window etc here.

Right click on ‘pages’, select “New Page”, enter name ‘home’, also do for ‘burger’.

IDE will generate files for you. Like this:

To better organize pages, we put them in their dedicated folders.

Each page has its own js, wxml and wxss.

Think of them as js, html and css for that page.

  • /pages/home
  • /pages/burger

Set up app.json file, we define pages that to use and TabBar for our pages.

{    "pages":[
"pages/home/home",
"pages/burger/burger"
],
"window":{
"backgroundTextStyle":"light",
"navigationBarBackgroundColor": "#fff",
"navigationBarTitleText": "Weixin",
"navigationBarTextStyle":"black"
},
"tabBar": {
"list": [{
"pagePath": "pages/home/home",
"text": "Home"}, {
"pagePath": "pages/burger/burger",
"text": "Burger"
}]},

"style": "v2",
"sitemapLocation": "sitemap.json"}

In this part:

"pages":[
"pages/home/home",
"pages/burger/burger"
]

The order matters, the first one in the list will be served as the index (front) page when the mini program shows up.

Add some styles to our global app stylesheet.

app.wxss

/**app.wxss**/
.container {
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
padding: 200rpx 0;
box-sizing: border-box;
}

.page-title {
font-weight: bold;
align-items: center;
}

Now, edit our Home page.

home.wxml

<!--pages/home.wxml-->
<view class="container">

<view class="page-title">
<text>Home</text>
</view>

<view class="page-content">
<view>
<text>Hello World!</text>
</view>

<view>
<image src="/images/home_500x700.png" />
</view>

<view>
<text>Welcome to my first WeChat Mini Program.</text>
</view>
</view>

</view>

There are tags that specially defined in WeChat mini programs. For example,

  • <view> : think of it as a <div> in html
  • <text>: think of it as a <span> or <p> in html
  • <image>: think of it as <img> tag in html

Next write our burger page related files:

burger.wxml

<!--pages/burger/burger.wxml-->
<text class='burger-title'>My Burger</text>

<view class="burger-container">

<view class="swiper-container">
<swiper indicator-dots="true" autoplay="true">
<swiper-item>
<image src="/images/burger01_500x500.png" />
</swiper-item>

<swiper-item>
<image src="/images/burger02_500x500.png" />
</swiper-item>

<swiper-item>
<image src="/images/burger03_500x500.png" />
</swiper-item>
</swiper>
</view>

<view class="burger-data-container">
<view><text>Description: {{description}}</text></view>
<view><text>Price: {{price}}</text></view>
<view><text>Review: {{review}}</text></view>
</view>

</view>

burger.wxss

/* pages/burger/burger.wxss */
.burger-container {
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
}

.burger-title {
color: black;
font-weight: bold;
display: flex;
flex-direction: column;
align-items: center;
margin: 50rpx auto 50rpx auto;
}

.swiper-container {
width: 100%;
background-color: #eeeeee;
padding-top: 50rpx;
margin: 30rpx auto;
}

swiper {
width: 100%;
height: 500rpx;
}

swiper-item {
display: flex;
flex-direction: column;
align-items: center;
}

.burger-data-container {
width: 100%;
background-color: #eeeeee;
display: flex;
flex-direction: column;
align-items: center;
padding-top: 30px;
padding-bottom: 30px;
}

Let’s break down burger.wxml and explain it first.

In the burger page, we add a swiper component to the page, like a slideshow.

We hard-coded the image paths to our local images stored in the project’s images folder. (For swiper component attributes, refer to the docs at the end)

<swiper indicator-dots="true" autoplay="true">
<swiper-item>
<image src="/images/burger01_500x500.png" />
</swiper-item>

<swiper-item>
<image src="/images/burger02_500x500.png" />
</swiper-item>

<swiper-item>
<image src="/images/burger03_500x500.png" />
</swiper-item>
</swiper>

We set burger’s data placeholders (description, price, review).

This time, we don’t hard-code them.

Instead, we will load the information from an external API that queried a database. Once requested, update the view with the data.

<view>
<view><text>{{description}}</text></view>
<view><text>{{price}}</text></view>
<view><text>{{review}}</text></view>
</view>

Then for the logic and magic, we write in the burger.js script.

I show all code of the js first for a glance. Then I will break it down into parts to explain.

burger.js

// pages/burger/burger.js

// if you need to access global data in the global app object
// then app.globalData to access or update data to global
var app = getApp()


Page({

/**
* Page initial data
*/
data: {
description: '',
price: '',
review: ''
},

/**
* Lifecycle function -- Called when page load
*/
onLoad: function(options) {
this.fetchExternalData()

// Because we.request() is async way.
// So we need to do process the fetched results inside its success() function.
// We cannot stack after this method call since it will not get the data.

},

/**
* Custom functions -- Called in Lifecycle function.
*
* Utility functions:
* fetchExternalData(): request external API to get data.
* saveAPIResources(): save API data to page data object or global data object (depends on your needs)
* updatePageView(): update to page view (display).
*/

fetchExternalData: function() {
// Make a varible 'that' pointing to this Page object
var that = this;

wx.request({
url: 'https://api.yoursite.com/burger/get',

success(res) {
console.log('Requested success.')
console.log(res.data)

// Store data
that.saveAPIResources(res.data)

// Update page view with teh data
that.updatePageView()
},

fail: function(error) {
console.log(error)
}
})
},

saveAPIResources: function(data) {
// Option 1: Save to this Page's data
this.data.price = data.price;
this.data.description = data.description;
this.data.review = data.review;

// Option 2: Save to app's globalData
// Append a burger data obj to globalData
app.globalData.burger = {
'price': data.price,
'description': data.description,
'review': data.review
}

},

updatePageView: function() {
// Option 1: update page view with this page's data.
this.setData({
description: this.data.description,
price: this.data.price,
review: this.data.review
})

// Option 2: update page view with app's global data.
this.setData({
description: '(from global) ' + app.globalData.burger.description,
price: '(from global) ' + app.globalData.burger.price,
review: '(from global) ' + app.globalData.review
})

}

})

There are some Lifecycle functions (For more lifecycles, refer to official docs).

We can hook them with your logic and interaction for different stages of lifecycles.

However, in this case, we only concern with the onLoad() function, which will be called when the burger page is loaded.

We immediately call fetchExternalData() when the page is loaded.

onLoad: function() { 
// ...

fetchExternalData()

// ...
}

fetchExternalData() is our custom function, inside the function, we request to API for the resource.

wx.request()

Because wx.request() is asynchronous communication, which means cannot get data to return and pass to flow after fetchExternalData().

However wx.request() will pass the resource to its success() function, so we can do data processing inside the success() function.

Assume that your super cool backend API writer guy returns a JSON data like this:

Inside success(), do our callback.

  • Firstly save the resource to the app’s data object.
  • Secondly, update the burger’s view with the JSON data.
success: function() {

saveAPIResources()

updatePageView()

}

Then pass resource data to saveAPIResources().

Either decide to save the data to this page’s data object, or save it global app’s data object, or do both.

It depends on your need. If the data will be later cross pages, side-widely used, you better save it to the app’s globalData.

I show both saving for your references.

saveAPIResources: function(data) {

// Option 1: Save to this Page's data
this.data.price = data.price;
this.data.description = data.description;
this.data.review = data.review;

// Option 2: Save to app's globalData
// Append a burger data obj to globalData
app.globalData.burger = {
'price': data.price,
'description': data.description,
'review': data.review
}

}

For global app data, get the app object somewhere on top of the script.

var app = getApp()

Then you can access the app’s info such as app.globalData.

After saving is done, update to burger’s view.

updatePageView()

Next, bind data to those placeholders we defined in the burger view (burger.wxml).

updatePageView: function() {

setData({
description: some_data,
price: some_data,
review: some_data
})

}

(This is kind of one-way DataBinding if you are familiar with two ways Model–View–ViewModel (MVVM) pattern that is implemented in many modern frameworks such as Reactjs, VueJs, Angular.)

We are done.

Run the simulator or preview the app in your phone.

Navigate the tab Home / Burger down the bottom.

Swipe the burger, check the burger info.

You make your own WeChat mini program, how tasty. :)

In conclusion, our burger WeChat mini program is a very minimal setup to illustrate what a mini program project is, the basic structure, and how to communicate with your favorite backends.

People are confusing with the stacks and technologies behind it.It is nothing mysterious as we just uncovered it.It is a wrapped program under the WeChat ecosystem.

It does have many limitations but it can do so much more, view model binding, interaction, I/O, networking, media, gaming, components, framework, etc. Check on the official developer guide for full details.

Keep in mind its philosophy. Use, and flush. Don’t make mini programs way too far complicated. It never aims to replace native apps.

Official docs:

“Restrictions breed creativity”. There are also WeChat mini program frameworks you can use on.

List some popular here for your extend reading:

--

--

Weiming Chen

I occasionally write about software, web, blockchain, machine learning, random thoughts.