Onebite.dev

Developer tips & trick, one bite at a time

Migrate from firebase to Hugo

I want to migrate my firebase website, which data stored in firestore, to Hugo post. The problem is hugo made with files not database per se. So there is no direcy way to export and import from firebase firestore file to hugo markdown files

Here is how i convert or migrate from firebase to hugo markdown to create post. The step is:

Export database from firestore

Luckily we don’t have to do this ourself, Dalenguyen made a nodejs package for us to use, here is firebase import export

Tweak the exported json file a little bit, to this format (in this example i just use title and desc, feel free to add other datas)

{    
"0BVxYRh8MixS0mYEtZ8v":{
        "title":"the titls",
        "subject":"the subject"
},
"0BVxYRh8MixasdS0mYEtZ8v":{
        "title":"the titls2",
        "subject":"the subject2"
}
}

Write go script

After exported the database, now create “main.go” file and add this code

package main
    
import (
    "fmt"
    "os"
    "io"
    "io/ioutil"
    "encoding/json"
    "strings"
        "time"
)

type Blogs map[string]Blog

type Blog struct{
    Title string `json:"title"`
    Slug string `json:"slug"`
    Subject string `json:"desc"`
    Tag string `json:"tag"`
    Time `json:"created_at"`
}

type Time struct{
    Seconds int `json:"_seconds"`
}

func main() {
    // Open jsonFile
    jsonFile, err := os.Open("./tak-blog.json")

    if err != nil {
        fmt.Println(err)
    }
    defer jsonFile.Close()

    //convert to byte
    jsonByte, _ := ioutil.ReadAll(jsonFile)

    var blogs Blogs
    json.Unmarshal(jsonByte, &blogs)

    for _, blog := range blogs {
        //metaData add double quote
        title := "\"" + blog.Title + "\""
        description := "\"" + cutText(blog.Subject) + "\""
        tag   := "\"" + blog.Tag + "\""
        created_at := "\"" + convertTime(blog.Time.Seconds) + "\""

        slug  := blog.Slug
        subject := blog.Subject

        //markdown file structure
        text := "+++\n" +
                "title = "+ title + "\n" +
                "description = "+ description + "\n" +
                "date = "+ created_at + "\n" +
                "tag = "+ tag + "\n" +
                "+++ \n" +
                subject

        if err := WriteStringToFile(slug +".md", text); err != nil {
            panic(err)
        }
    }
}
    
//write string to a file
func WriteStringToFile(filepath, s string) error {
    fo, err := os.Create(filepath)
    if err != nil {
        return err
    }
    defer fo.Close()

    _, err = io.Copy(fo, strings.NewReader(s))
    if err != nil {
        return err
    }
    return nil
}

//convert seconds time to markdown format
func convertTime(seconds int) string {
    timeRaw := time.Unix(int64(seconds), 0)
    timeNew := strings.Split(timeRaw.String(), " ")
    date := timeNew[0]
    return date +"T"+ timeNew[1] + "+00:00"
}

//to make meta descrption that limited to 120 chars
func cutText(text string) string {
    text = strings.Replace(text, "\n", "", -1)
    if len(text) < 120 {
        return text
    } else {
        rune := []rune(text)
        return string(rune[0:120])
    }
}

Make sure the data types in struct model meets with your need.

Now run the script “go run main.go”, all files will be created, now just copy paste it to your hugo site

This code also available on github to tweak


🏊🏾‍♀️ Back Home